See #1100: clean compat and XXX in the code
This commit is contained in:
parent
b7f1c02c6f
commit
e271851f67
|
@ -74,11 +74,6 @@ v1_patterns += [
|
|||
include(("funkwhale_api.history.urls", "history"), namespace="history"),
|
||||
),
|
||||
url(r"^", include(("funkwhale_api.users.api_urls", "users"), namespace="users"),),
|
||||
# XXX: 1.0: remove this
|
||||
url(
|
||||
r"^users/",
|
||||
include(("funkwhale_api.users.api_urls", "users"), namespace="users-nested"),
|
||||
),
|
||||
url(
|
||||
r"^oauth/",
|
||||
include(("funkwhale_api.users.oauth.urls", "oauth"), namespace="oauth"),
|
||||
|
|
|
@ -2,18 +2,13 @@ from channels.auth import AuthMiddlewareStack
|
|||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
|
||||
from django.conf.urls import url
|
||||
from funkwhale_api.common.auth import TokenAuthMiddleware
|
||||
from funkwhale_api.instance import consumers
|
||||
|
||||
application = ProtocolTypeRouter(
|
||||
{
|
||||
# Empty for now (http->django views is added by default)
|
||||
"websocket": AuthMiddlewareStack(
|
||||
TokenAuthMiddleware(
|
||||
URLRouter(
|
||||
[url("^api/v1/activity$", consumers.InstanceActivityConsumer)]
|
||||
)
|
||||
)
|
||||
URLRouter([url("^api/v1/activity$", consumers.InstanceActivityConsumer)])
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -169,17 +169,7 @@ os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = env.bool(
|
|||
"DJANGO_ALLOW_ASYNC_UNSAFE", default="true"
|
||||
)
|
||||
|
||||
# XXX: deprecated, see #186
|
||||
FEDERATION_ENABLED = env.bool("FEDERATION_ENABLED", default=True)
|
||||
FEDERATION_HOSTNAME = env("FEDERATION_HOSTNAME", default=FUNKWHALE_HOSTNAME).lower()
|
||||
# XXX: deprecated, see #186
|
||||
FEDERATION_COLLECTION_PAGE_SIZE = env.int("FEDERATION_COLLECTION_PAGE_SIZE", default=50)
|
||||
# XXX: deprecated, see #186
|
||||
FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool(
|
||||
"FEDERATION_MUSIC_NEEDS_APPROVAL", default=True
|
||||
)
|
||||
# XXX: deprecated, see #186
|
||||
FEDERATION_ACTOR_FETCH_DELAY = env.int("FEDERATION_ACTOR_FETCH_DELAY", default=60 * 12)
|
||||
FEDERATION_SERVICE_ACTOR_USERNAME = env(
|
||||
"FEDERATION_SERVICE_ACTOR_USERNAME", default="service"
|
||||
)
|
||||
|
@ -1129,11 +1119,6 @@ Exemples:
|
|||
CSRF_USE_SESSIONS = True
|
||||
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
||||
|
||||
# Playlist settings
|
||||
# XXX: deprecated, see #186
|
||||
PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250)
|
||||
|
||||
|
||||
ACCOUNT_USERNAME_BLACKLIST = [
|
||||
"funkwhale",
|
||||
"library",
|
||||
|
@ -1170,8 +1155,6 @@ EXTERNAL_REQUESTS_TIMEOUT = env.int("EXTERNAL_REQUESTS_TIMEOUT", default=10)
|
|||
"""
|
||||
Default timeout for external requests.
|
||||
"""
|
||||
# XXX: deprecated, see #186
|
||||
API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
|
||||
|
||||
MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None)
|
||||
"""
|
||||
|
@ -1285,8 +1268,6 @@ FUNKWHALE_SUPPORT_MESSAGE_DELAY = env.int("FUNKWHALE_SUPPORT_MESSAGE_DELAY", def
|
|||
"""
|
||||
Delay in days after signup before we show the "support Funkwhale" message
|
||||
"""
|
||||
# XXX Stable release: remove
|
||||
USE_FULL_TEXT_SEARCH = env.bool("USE_FULL_TEXT_SEARCH", default=True)
|
||||
|
||||
MIN_DELAY_BETWEEN_DOWNLOADS_COUNT = env.int(
|
||||
"MIN_DELAY_BETWEEN_DOWNLOADS_COUNT", default=60 * 60 * 6
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
from dynamic_preferences import types
|
||||
from dynamic_preferences.registries import global_preferences_registry
|
||||
|
||||
from funkwhale_api.common import preferences
|
||||
|
||||
common = types.Section("common")
|
||||
|
||||
|
||||
@global_preferences_registry.register
|
||||
class APIAutenticationRequired(
|
||||
preferences.DefaultFromSettingMixin, types.BooleanPreference
|
||||
):
|
||||
class APIAutenticationRequired(types.BooleanPreference):
|
||||
section = common
|
||||
name = "api_authentication_required"
|
||||
verbose_name = "API Requires authentication"
|
||||
setting = "API_AUTHENTICATION_REQUIRED"
|
||||
default = True
|
||||
help_text = (
|
||||
"If disabled, anonymous users will be able to query the API"
|
||||
"and access music data (as well as other data exposed in the API "
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import django_filters
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from django.db import models
|
||||
|
||||
|
@ -40,7 +39,7 @@ class SearchFilter(django_filters.CharFilter):
|
|||
def filter(self, qs, value):
|
||||
if not value:
|
||||
return qs
|
||||
if settings.USE_FULL_TEXT_SEARCH and self.fts_search_fields:
|
||||
if self.fts_search_fields:
|
||||
query = search.get_fts_query(
|
||||
value, self.fts_search_fields, model=self.parent.Meta.model
|
||||
)
|
||||
|
|
|
@ -113,7 +113,7 @@ def get_spa_html(spa_url):
|
|||
|
||||
def get_spa_file(spa_url, name):
|
||||
if spa_url.startswith("/"):
|
||||
# XXX: spa_url is an absolute path to index.html, on the local disk.
|
||||
# spa_url is an absolute path to index.html, on the local disk.
|
||||
# However, we may want to access manifest.json or other files as well, so we
|
||||
# strip the filename
|
||||
path = os.path.join(os.path.dirname(spa_url), name)
|
||||
|
|
|
@ -299,20 +299,6 @@ class AttachmentSerializer(serializers.Serializer):
|
|||
urls["medium_square_crop"] = o.download_url_medium_square_crop
|
||||
return urls
|
||||
|
||||
def to_representation(self, o):
|
||||
repr = super().to_representation(o)
|
||||
# XXX: BACKWARD COMPATIBILITY
|
||||
# having the attachment urls in a nested JSON obj is better,
|
||||
# but we can't do this without breaking clients
|
||||
# So we extract the urls and include these in the parent payload
|
||||
repr.update({k: v for k, v in repr["urls"].items() if k != "source"})
|
||||
# also, our legacy images had lots of variations (400x400, 200x200, 50x50)
|
||||
# but we removed some of these, so we emulate these by hand (by redirecting)
|
||||
# to actual, existing attachment variations
|
||||
repr["square_crop"] = repr["medium_square_crop"]
|
||||
repr["small_square_crop"] = repr["medium_square_crop"]
|
||||
return repr
|
||||
|
||||
def create(self, validated_data):
|
||||
return models.Attachment.objects.create(
|
||||
file=validated_data["file"], actor=validated_data["actor"]
|
||||
|
|
|
@ -13,8 +13,7 @@ class TrackFavoriteFilter(moderation_filters.HiddenContentFilterSet):
|
|||
|
||||
class Meta:
|
||||
model = models.TrackFavorite
|
||||
# XXX: 1.0 remove the user filter, we have scope=me now
|
||||
fields = ["user"]
|
||||
fields = []
|
||||
hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG[
|
||||
"TRACK_FAVORITE"
|
||||
]
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
from dynamic_preferences import types
|
||||
from dynamic_preferences.registries import global_preferences_registry
|
||||
|
||||
from funkwhale_api.common import preferences
|
||||
|
||||
federation = types.Section("federation")
|
||||
|
||||
|
||||
|
@ -22,10 +20,10 @@ class MusicCacheDuration(types.IntPreference):
|
|||
|
||||
|
||||
@global_preferences_registry.register
|
||||
class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference):
|
||||
class Enabled(types.BooleanPreference):
|
||||
section = federation
|
||||
name = "enabled"
|
||||
setting = "FEDERATION_ENABLED"
|
||||
default = True
|
||||
verbose_name = "Federation enabled"
|
||||
help_text = (
|
||||
"Use this setting to enable or disable federation logic and API" " globally."
|
||||
|
@ -33,20 +31,20 @@ class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference):
|
|||
|
||||
|
||||
@global_preferences_registry.register
|
||||
class CollectionPageSize(preferences.DefaultFromSettingMixin, types.IntPreference):
|
||||
class CollectionPageSize(types.IntPreference):
|
||||
section = federation
|
||||
name = "collection_page_size"
|
||||
setting = "FEDERATION_COLLECTION_PAGE_SIZE"
|
||||
default = 50
|
||||
verbose_name = "Federation collection page size"
|
||||
help_text = "How many items to display in ActivityPub collections."
|
||||
field_kwargs = {"required": False}
|
||||
|
||||
|
||||
@global_preferences_registry.register
|
||||
class ActorFetchDelay(preferences.DefaultFromSettingMixin, types.IntPreference):
|
||||
class ActorFetchDelay(types.IntPreference):
|
||||
section = federation
|
||||
name = "actor_fetch_delay"
|
||||
setting = "FEDERATION_ACTOR_FETCH_DELAY"
|
||||
default = 60 * 12
|
||||
verbose_name = "Federation actor fetch delay"
|
||||
help_text = (
|
||||
"How many minutes to wait before refetching actors on "
|
||||
|
|
|
@ -938,8 +938,6 @@ class PaginatedCollectionSerializer(jsonld.JsonLdSerializer):
|
|||
last = common_utils.set_query_parameter(conf["id"], page=paginator.num_pages)
|
||||
d = {
|
||||
"id": conf["id"],
|
||||
# XXX Stable release: remove the obsolete actor field
|
||||
"actor": conf["actor"].fid,
|
||||
"attributedTo": conf["actor"].fid,
|
||||
"totalItems": paginator.count,
|
||||
"type": conf.get("type", "Collection"),
|
||||
|
@ -1004,9 +1002,8 @@ class LibrarySerializer(PaginatedCollectionSerializer):
|
|||
"name": library.name,
|
||||
"summary": library.description,
|
||||
"page_size": 100,
|
||||
# XXX Stable release: remove the obsolete actor field
|
||||
"actor": library.actor,
|
||||
"attributedTo": library.actor,
|
||||
"actor": library.actor,
|
||||
"items": library.uploads.for_federation(),
|
||||
"type": "Library",
|
||||
}
|
||||
|
@ -1108,8 +1105,6 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer):
|
|||
],
|
||||
}
|
||||
if conf["actor"]:
|
||||
# XXX Stable release: remove the obsolete actor field
|
||||
d["actor"] = conf["actor"].fid
|
||||
d["attributedTo"] = conf["actor"].fid
|
||||
|
||||
if page.has_previous():
|
||||
|
@ -1297,8 +1292,7 @@ class AlbumSerializer(MusicEntitySerializer):
|
|||
child=MultipleSerializer(allowed=[BasicActorSerializer, ArtistSerializer]),
|
||||
min_length=1,
|
||||
)
|
||||
# XXX: 1.0 rename to image
|
||||
cover = ImageSerializer(
|
||||
image = ImageSerializer(
|
||||
allowed_mimetypes=["image/*"],
|
||||
allow_null=True,
|
||||
required=False,
|
||||
|
@ -1306,7 +1300,7 @@ class AlbumSerializer(MusicEntitySerializer):
|
|||
)
|
||||
updateable_fields = [
|
||||
("name", "title"),
|
||||
("cover", "attachment_cover"),
|
||||
("image", "attachment_cover"),
|
||||
("musicbrainzId", "mbid"),
|
||||
("attributedTo", "attributed_to"),
|
||||
("released", "release_date"),
|
||||
|
@ -1320,7 +1314,7 @@ class AlbumSerializer(MusicEntitySerializer):
|
|||
{
|
||||
"released": jsonld.first_val(contexts.FW.released),
|
||||
"artists": jsonld.first_attr(contexts.FW.artists, "@list"),
|
||||
"cover": jsonld.first_obj(contexts.FW.cover),
|
||||
"image": jsonld.first_obj(contexts.AS.image),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -1354,11 +1348,6 @@ class AlbumSerializer(MusicEntitySerializer):
|
|||
]
|
||||
include_content(d, instance.description)
|
||||
if instance.attachment_cover:
|
||||
d["cover"] = {
|
||||
"type": "Link",
|
||||
"href": instance.attachment_cover.download_url_original,
|
||||
"mediaType": instance.attachment_cover.mimetype or "image/jpeg",
|
||||
}
|
||||
include_image(d, instance.attachment_cover)
|
||||
|
||||
if self.context.get("include_ap_context", self.parent is None):
|
||||
|
|
|
@ -218,7 +218,6 @@ def should_redirect_ap_to_html(accept_header, default=True):
|
|||
"text/html",
|
||||
]
|
||||
no_redirect_headers = [
|
||||
"*/*", # XXX backward compat with older Funkwhale instances that don't send the Accept header
|
||||
"application/json",
|
||||
"application/activity+json",
|
||||
"application/ld+json",
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 3.0.8 on 2020-08-03 12:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('moderation', '0005_auto_20200317_0820'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='userrequest',
|
||||
name='url',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userrequest',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('pending', 'Pending'), ('refused', 'Refused'), ('approved', 'Approved')], default='pending', max_length=40),
|
||||
),
|
||||
]
|
|
@ -20,7 +20,6 @@ from django.db.models.signals import post_save, pre_save
|
|||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from versatileimagefield.fields import VersatileImageField
|
||||
|
||||
from funkwhale_api import musicbrainz
|
||||
from funkwhale_api.common import fields
|
||||
|
@ -325,10 +324,6 @@ class Album(APIModelMixin):
|
|||
artist = models.ForeignKey(Artist, related_name="albums", on_delete=models.CASCADE)
|
||||
release_date = models.DateField(null=True, blank=True, db_index=True)
|
||||
release_group_id = models.UUIDField(null=True, blank=True)
|
||||
# XXX: 1.0 clean this uneeded field in favor of attachment_cover
|
||||
cover = VersatileImageField(
|
||||
upload_to="albums/covers/%Y/%m/%d", null=True, blank=True
|
||||
)
|
||||
attachment_cover = models.ForeignKey(
|
||||
"common.Attachment",
|
||||
null=True,
|
||||
|
|
|
@ -32,10 +32,7 @@ COVER_WRITE_FIELD = common_serializers.RelatedField(
|
|||
from funkwhale_api.audio import serializers as audio_serializers # NOQA
|
||||
|
||||
|
||||
class CoverField(
|
||||
common_serializers.NullToEmptDict, common_serializers.AttachmentSerializer
|
||||
):
|
||||
# XXX: BACKWARD COMPATIBILITY
|
||||
class CoverField(common_serializers.AttachmentSerializer):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ def federation_audio_track_to_metadata(payload, references):
|
|||
"mbid": str(payload["album"]["musicbrainzId"])
|
||||
if payload["album"].get("musicbrainzId")
|
||||
else None,
|
||||
"cover_data": get_cover(payload["album"], "cover"),
|
||||
"cover_data": get_cover(payload["album"], "image"),
|
||||
"release_date": payload["album"].get("released"),
|
||||
"tags": [t["name"] for t in payload["album"].get("tags", []) or []],
|
||||
"artists": [
|
||||
|
@ -896,8 +896,6 @@ UPDATE_CONFIG = {
|
|||
|
||||
@transaction.atomic
|
||||
def update_track_metadata(audio_metadata, track):
|
||||
# XXX: implement this to support updating metadata when an imported files
|
||||
# is updated by an outside tool (e.g beets).
|
||||
serializer = metadata.TrackMetadataSerializer(data=audio_metadata)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
new_data = serializer.validated_data
|
||||
|
|
|
@ -797,20 +797,11 @@ class Search(views.APIView):
|
|||
return Response(results, status=200)
|
||||
|
||||
def get_tracks(self, query):
|
||||
search_fields = [
|
||||
"mbid",
|
||||
"title__unaccent",
|
||||
"album__title__unaccent",
|
||||
"artist__name__unaccent",
|
||||
]
|
||||
if settings.USE_FULL_TEXT_SEARCH:
|
||||
query_obj = utils.get_fts_query(
|
||||
query,
|
||||
fts_fields=["body_text", "album__body_text", "artist__body_text"],
|
||||
model=models.Track,
|
||||
)
|
||||
else:
|
||||
query_obj = utils.get_query(query, search_fields)
|
||||
query_obj = utils.get_fts_query(
|
||||
query,
|
||||
fts_fields=["body_text", "album__body_text", "artist__body_text"],
|
||||
model=models.Track,
|
||||
)
|
||||
qs = (
|
||||
models.Track.objects.all()
|
||||
.filter(query_obj)
|
||||
|
@ -828,13 +819,9 @@ class Search(views.APIView):
|
|||
return common_utils.order_for_search(qs, "title")[: self.max_results]
|
||||
|
||||
def get_albums(self, query):
|
||||
search_fields = ["mbid", "title__unaccent", "artist__name__unaccent"]
|
||||
if settings.USE_FULL_TEXT_SEARCH:
|
||||
query_obj = utils.get_fts_query(
|
||||
query, fts_fields=["body_text", "artist__body_text"], model=models.Album
|
||||
)
|
||||
else:
|
||||
query_obj = utils.get_query(query, search_fields)
|
||||
query_obj = utils.get_fts_query(
|
||||
query, fts_fields=["body_text", "artist__body_text"], model=models.Album
|
||||
)
|
||||
qs = (
|
||||
models.Album.objects.all()
|
||||
.filter(query_obj)
|
||||
|
@ -844,11 +831,7 @@ class Search(views.APIView):
|
|||
return common_utils.order_for_search(qs, "title")[: self.max_results]
|
||||
|
||||
def get_artists(self, query):
|
||||
search_fields = ["mbid", "name__unaccent"]
|
||||
if settings.USE_FULL_TEXT_SEARCH:
|
||||
query_obj = utils.get_fts_query(query, model=models.Artist)
|
||||
else:
|
||||
query_obj = utils.get_query(query, search_fields)
|
||||
query_obj = utils.get_fts_query(query, model=models.Artist)
|
||||
qs = (
|
||||
models.Artist.objects.all()
|
||||
.filter(query_obj)
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
from dynamic_preferences import types
|
||||
from dynamic_preferences.registries import global_preferences_registry
|
||||
|
||||
from funkwhale_api.common import preferences
|
||||
|
||||
playlists = types.Section("playlists")
|
||||
|
||||
|
||||
@global_preferences_registry.register
|
||||
class MaxTracks(preferences.DefaultFromSettingMixin, types.IntegerPreference):
|
||||
class MaxTracks(types.IntegerPreference):
|
||||
show_in_api = True
|
||||
section = playlists
|
||||
name = "max_tracks"
|
||||
default = 250
|
||||
verbose_name = "Max tracks per playlist"
|
||||
setting = "PLAYLISTS_MAX_TRACKS"
|
||||
field_kwargs = {"required": False}
|
||||
|
|
|
@ -31,7 +31,6 @@ class PlaylistFilter(filters.FilterSet):
|
|||
class Meta:
|
||||
model = models.Playlist
|
||||
fields = {
|
||||
"user": ["exact"],
|
||||
"name": ["exact", "icontains"],
|
||||
}
|
||||
|
||||
|
|
|
@ -227,7 +227,6 @@ class PlaylistTrack(models.Model):
|
|||
|
||||
class Meta:
|
||||
ordering = ("-playlist", "index")
|
||||
unique_together = ("playlist", "index")
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
playlist = self.playlist
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.0.8 on 2020-08-03 12:22
|
||||
|
||||
import django.contrib.postgres.fields.jsonb
|
||||
import django.core.serializers.json
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('radios', '0004_auto_20180107_1813'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='radio',
|
||||
name='config',
|
||||
field=django.contrib.postgres.fields.jsonb.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.0.8 on 2020-08-03 12:22
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('tags', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='taggeditem',
|
||||
name='content_type',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='contenttypes.ContentType', verbose_name='Content type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='taggeditem',
|
||||
name='tag',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='tags.Tag'),
|
||||
),
|
||||
]
|
|
@ -1,30 +0,0 @@
|
|||
import pytest
|
||||
from rest_framework_jwt.settings import api_settings
|
||||
|
||||
from funkwhale_api.common.auth import TokenAuthMiddleware
|
||||
|
||||
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
|
||||
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
|
||||
|
||||
|
||||
@pytest.mark.parametrize("query_string", [b"token=wrong", b""])
|
||||
def test_header_anonymous(query_string, factories):
|
||||
def callback(scope):
|
||||
assert scope["user"].is_anonymous
|
||||
|
||||
scope = {"query_string": query_string}
|
||||
consumer = TokenAuthMiddleware(callback)
|
||||
consumer(scope)
|
||||
|
||||
|
||||
def test_header_correct_token(factories):
|
||||
user = factories["users.User"]()
|
||||
payload = jwt_payload_handler(user)
|
||||
token = jwt_encode_handler(payload)
|
||||
|
||||
def callback(scope):
|
||||
assert scope["user"] == user
|
||||
|
||||
scope = {"query_string": "token={}".format(token).encode("utf-8")}
|
||||
consumer = TokenAuthMiddleware(callback)
|
||||
consumer(scope)
|
|
@ -17,7 +17,7 @@ from django import urls
|
|||
"/api/v1/auth/registration/account-confirm-email/key",
|
||||
"/api/v1/history/listenings",
|
||||
"/api/v1/radios/sessions",
|
||||
"/api/v1/users/users/me",
|
||||
"/api/v1/users/me",
|
||||
"/api/v1/federation/follows/library",
|
||||
"/api/v1/manage/accounts",
|
||||
"/api/v1/oauth/apps",
|
||||
|
|
|
@ -201,15 +201,6 @@ def test_attachment_serializer_existing_file(factories, to_api_date):
|
|||
attachment.file.crop["200x200"].url
|
||||
),
|
||||
},
|
||||
# XXX: BACKWARD COMPATIBILITY
|
||||
"original": federation_utils.full_url(attachment.file.url),
|
||||
"medium_square_crop": federation_utils.full_url(
|
||||
attachment.file.crop["200x200"].url
|
||||
),
|
||||
"small_square_crop": federation_utils.full_url(
|
||||
attachment.file.crop["200x200"].url
|
||||
),
|
||||
"square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url),
|
||||
}
|
||||
|
||||
serializer = serializers.AttachmentSerializer(attachment)
|
||||
|
@ -237,17 +228,6 @@ def test_attachment_serializer_remote_file(factories, to_api_date):
|
|||
proxy_url + "?next=medium_square_crop"
|
||||
),
|
||||
},
|
||||
# XXX: BACKWARD COMPATIBILITY
|
||||
"original": federation_utils.full_url(proxy_url + "?next=original"),
|
||||
"medium_square_crop": federation_utils.full_url(
|
||||
proxy_url + "?next=medium_square_crop"
|
||||
),
|
||||
"square_crop": federation_utils.full_url(
|
||||
proxy_url + "?next=medium_square_crop"
|
||||
),
|
||||
"small_square_crop": federation_utils.full_url(
|
||||
proxy_url + "?next=medium_square_crop"
|
||||
),
|
||||
}
|
||||
|
||||
serializer = serializers.AttachmentSerializer(attachment)
|
||||
|
|
|
@ -20,10 +20,11 @@ def test_user_can_get_his_favorites(
|
|||
api_request, factories, logged_in_api_client, client
|
||||
):
|
||||
request = api_request.get("/")
|
||||
logged_in_api_client.user.create_actor()
|
||||
favorite = factories["favorites.TrackFavorite"](user=logged_in_api_client.user)
|
||||
factories["favorites.TrackFavorite"]()
|
||||
url = reverse("api:v1:favorites:tracks-list")
|
||||
response = logged_in_api_client.get(url, {"user": logged_in_api_client.user.pk})
|
||||
response = logged_in_api_client.get(url, {"scope": "me"})
|
||||
expected = [
|
||||
serializers.UserTrackFavoriteSerializer(
|
||||
favorite, context={"request": request}
|
||||
|
|
|
@ -388,7 +388,6 @@ def test_paginated_collection_serializer(factories):
|
|||
"@context": jsonld.get_default_context(),
|
||||
"type": "Collection",
|
||||
"id": conf["id"],
|
||||
"actor": actor.fid,
|
||||
"attributedTo": actor.fid,
|
||||
"totalItems": len(uploads),
|
||||
"current": conf["id"] + "?page=1",
|
||||
|
@ -486,7 +485,6 @@ def test_collection_page_serializer(factories):
|
|||
"@context": jsonld.get_default_context(),
|
||||
"type": "CollectionPage",
|
||||
"id": conf["id"] + "?page=2",
|
||||
"actor": actor.fid,
|
||||
"attributedTo": actor.fid,
|
||||
"totalItems": len(uploads),
|
||||
"partOf": conf["id"],
|
||||
|
@ -521,7 +519,6 @@ def test_music_library_serializer_to_ap(factories):
|
|||
"id": library.fid,
|
||||
"name": library.name,
|
||||
"summary": library.description,
|
||||
"actor": library.actor.fid,
|
||||
"attributedTo": library.actor.fid,
|
||||
"totalItems": 0,
|
||||
"current": library.fid + "?page=1",
|
||||
|
@ -764,11 +761,6 @@ def test_activity_pub_album_serializer_to_ap(factories):
|
|||
"type": "Album",
|
||||
"id": album.fid,
|
||||
"name": album.title,
|
||||
"cover": {
|
||||
"type": "Link",
|
||||
"mediaType": "image/jpeg",
|
||||
"href": utils.full_url(album.attachment_cover.file.url),
|
||||
},
|
||||
"image": {
|
||||
"type": "Image",
|
||||
"mediaType": "image/jpeg",
|
||||
|
@ -815,7 +807,7 @@ def test_activity_pub_album_serializer_from_ap_create(factories, faker, now):
|
|||
"type": "Album",
|
||||
"id": "https://album.example",
|
||||
"name": faker.sentence(),
|
||||
"cover": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
|
||||
"image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
|
||||
"musicbrainzId": faker.uuid4(),
|
||||
"published": now.isoformat(),
|
||||
"released": released.isoformat(),
|
||||
|
@ -839,8 +831,8 @@ def test_activity_pub_album_serializer_from_ap_create(factories, faker, now):
|
|||
assert str(album.mbid) == payload["musicbrainzId"]
|
||||
assert album.release_date == released
|
||||
assert album.artist == artist
|
||||
assert album.attachment_cover.url == payload["cover"]["href"]
|
||||
assert album.attachment_cover.mimetype == payload["cover"]["mediaType"]
|
||||
assert album.attachment_cover.url == payload["image"]["href"]
|
||||
assert album.attachment_cover.mimetype == payload["image"]["mediaType"]
|
||||
assert sorted(album.tagged_items.values_list("tag__name", flat=True)) == [
|
||||
"Punk",
|
||||
"Rock",
|
||||
|
@ -879,7 +871,7 @@ def test_activity_pub_album_serializer_from_ap_update(factories, faker):
|
|||
"type": "Album",
|
||||
"id": album.fid,
|
||||
"name": faker.sentence(),
|
||||
"cover": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
|
||||
"image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
|
||||
"musicbrainzId": faker.uuid4(),
|
||||
"published": album.creation_date.isoformat(),
|
||||
"released": released.isoformat(),
|
||||
|
@ -904,8 +896,8 @@ def test_activity_pub_album_serializer_from_ap_update(factories, faker):
|
|||
assert album.title == payload["name"]
|
||||
assert str(album.mbid) == payload["musicbrainzId"]
|
||||
assert album.release_date == released
|
||||
assert album.attachment_cover.url == payload["cover"]["href"]
|
||||
assert album.attachment_cover.mimetype == payload["cover"]["mediaType"]
|
||||
assert album.attachment_cover.url == payload["image"]["href"]
|
||||
assert album.attachment_cover.mimetype == payload["image"]["mediaType"]
|
||||
assert sorted(album.tagged_items.values_list("tag__name", flat=True)) == [
|
||||
"Punk",
|
||||
"Rock",
|
||||
|
@ -996,7 +988,7 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
|
|||
"content": "Album summary",
|
||||
"mediaType": "text/markdown",
|
||||
"attributedTo": album_attributed_to.fid,
|
||||
"cover": {
|
||||
"image": {
|
||||
"type": "Link",
|
||||
"href": "https://cover.image/test.png",
|
||||
"mediaType": "image/png",
|
||||
|
@ -1066,8 +1058,8 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
|
|||
assert track.attachment_cover.mimetype == data["image"]["mediaType"]
|
||||
|
||||
assert album.from_activity == activity
|
||||
assert album.attachment_cover.url == data["album"]["cover"]["href"]
|
||||
assert album.attachment_cover.mimetype == data["album"]["cover"]["mediaType"]
|
||||
assert album.attachment_cover.url == data["album"]["image"]["href"]
|
||||
assert album.attachment_cover.mimetype == data["album"]["image"]["mediaType"]
|
||||
assert album.title == data["album"]["name"]
|
||||
assert album.fid == data["album"]["id"]
|
||||
assert str(album.mbid) == data["album"]["musicbrainzId"]
|
||||
|
@ -1196,7 +1188,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock):
|
|||
"musicbrainzId": str(uuid.uuid4()),
|
||||
"published": published.isoformat(),
|
||||
"released": released.isoformat(),
|
||||
"cover": {
|
||||
"image": {
|
||||
"type": "Link",
|
||||
"href": "https://cover.image/test.png",
|
||||
"mediaType": "image/png",
|
||||
|
@ -1222,7 +1214,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock):
|
|||
],
|
||||
},
|
||||
}
|
||||
r_mock.get(data["track"]["album"]["cover"]["href"], body=io.BytesIO(b"coucou"))
|
||||
r_mock.get(data["track"]["album"]["image"]["href"], body=io.BytesIO(b"coucou"))
|
||||
|
||||
serializer = serializers.UploadSerializer(data=data, context={"activity": activity})
|
||||
assert serializer.is_valid(raise_exception=True)
|
||||
|
@ -1266,7 +1258,7 @@ def test_activity_pub_upload_serializer_from_ap_update(factories, mocker, now, r
|
|||
"library": library.fid,
|
||||
"track": serializers.TrackSerializer(upload.track).data,
|
||||
}
|
||||
r_mock.get(data["track"]["album"]["cover"]["href"], body=io.BytesIO(b"coucou"))
|
||||
r_mock.get(data["track"]["album"]["image"]["url"], body=io.BytesIO(b"coucou"))
|
||||
|
||||
serializer = serializers.UploadSerializer(upload, data=data)
|
||||
assert serializer.is_valid(raise_exception=True)
|
||||
|
@ -1628,7 +1620,6 @@ def test_channel_actor_outbox_serializer(factories):
|
|||
"@context": jsonld.get_default_context(),
|
||||
"type": "OrderedCollection",
|
||||
"id": channel.actor.outbox_url,
|
||||
"actor": channel.actor.fid,
|
||||
"attributedTo": channel.actor.fid,
|
||||
"totalItems": len(uploads),
|
||||
"first": channel.actor.outbox_url + "?page=1",
|
||||
|
|
|
@ -384,11 +384,6 @@ def test_music_upload_detail_private_approved_follow(
|
|||
("text/html,application/xhtml+xml", True, True),
|
||||
("text/html,application/json", True, True),
|
||||
("", True, False),
|
||||
(
|
||||
"*/*",
|
||||
True,
|
||||
False,
|
||||
), # XXX: compat with older versions of Funkwhale that miss the Accept header
|
||||
(None, True, False),
|
||||
("application/json", True, False),
|
||||
("application/activity+json", True, False),
|
||||
|
|
|
@ -196,15 +196,6 @@ def test_album_serializer(factories, to_api_date):
|
|||
assert serializer.data == expected
|
||||
|
||||
|
||||
def test_album_serializer_empty_cover(factories, to_api_date):
|
||||
# XXX: BACKWARD COMPATIBILITY
|
||||
album = factories["music.Album"](attachment_cover=None)
|
||||
|
||||
serializer = serializers.AlbumSerializer(album)
|
||||
|
||||
assert serializer.data["cover"] == {}
|
||||
|
||||
|
||||
def test_track_serializer(factories, to_api_date):
|
||||
actor = factories["federation.Actor"]()
|
||||
upload = factories["music.Upload"](
|
||||
|
|
|
@ -660,7 +660,7 @@ def test_federation_audio_track_to_metadata(now, mocker):
|
|||
},
|
||||
}
|
||||
],
|
||||
"cover": {
|
||||
"image": {
|
||||
"type": "Link",
|
||||
"href": "http://cover.test",
|
||||
"mediaType": "image/png",
|
||||
|
@ -713,8 +713,8 @@ def test_federation_audio_track_to_metadata(now, mocker):
|
|||
"tags": ["AlbumTag"],
|
||||
"description": {"content_type": "text/plain", "text": "album desc"},
|
||||
"cover_data": {
|
||||
"mimetype": serializer.validated_data["album"]["cover"]["mediaType"],
|
||||
"url": serializer.validated_data["album"]["cover"]["href"],
|
||||
"mimetype": serializer.validated_data["album"]["image"]["mediaType"],
|
||||
"url": serializer.validated_data["album"]["image"]["href"],
|
||||
},
|
||||
"artists": [
|
||||
{
|
||||
|
|
|
@ -1307,9 +1307,7 @@ def test_get_upload_audio_metadata(logged_in_api_client, factories):
|
|||
assert response.data == serializer.validated_data
|
||||
|
||||
|
||||
@pytest.mark.parametrize("use_fts", [True, False])
|
||||
def test_search_get(use_fts, settings, logged_in_api_client, factories):
|
||||
settings.USE_FULL_TEXT_SEARCH = use_fts
|
||||
def test_search_get(logged_in_api_client, factories):
|
||||
artist = factories["music.Artist"](name="Foo Fighters")
|
||||
album = factories["music.Album"](title="Foo Bar")
|
||||
track = factories["music.Track"](title="Foo Baz")
|
||||
|
@ -1332,8 +1330,7 @@ def test_search_get(use_fts, settings, logged_in_api_client, factories):
|
|||
assert response.data == expected
|
||||
|
||||
|
||||
def test_search_get_fts_advanced(settings, logged_in_api_client, factories):
|
||||
settings.USE_FULL_TEXT_SEARCH = True
|
||||
def test_search_get_fts_advanced(logged_in_api_client, factories):
|
||||
artist1 = factories["music.Artist"](name="Foo Bighters")
|
||||
artist2 = factories["music.Artist"](name="Bar Fighter")
|
||||
factories["music.Artist"]()
|
||||
|
@ -1353,8 +1350,7 @@ def test_search_get_fts_advanced(settings, logged_in_api_client, factories):
|
|||
assert response.data == expected
|
||||
|
||||
|
||||
def test_search_get_fts_stop_words(settings, logged_in_api_client, factories):
|
||||
settings.USE_FULL_TEXT_SEARCH = True
|
||||
def test_search_get_fts_stop_words(logged_in_api_client, factories):
|
||||
artist = factories["music.Artist"](name="she")
|
||||
factories["music.Artist"](name="something else")
|
||||
|
||||
|
|
|
@ -720,7 +720,7 @@ User:
|
|||
type: "string"
|
||||
example: "Alice Kingsley"
|
||||
avatar:
|
||||
$ref: "#/Avatar"
|
||||
$ref: "#/Attachment"
|
||||
|
||||
Me:
|
||||
type: "object"
|
||||
|
@ -767,30 +767,8 @@ Me:
|
|||
via request headers isn't possible.
|
||||
|
||||
The token expires after 3 days by default.
|
||||
Avatar:
|
||||
type: "object"
|
||||
properties:
|
||||
original:
|
||||
type: "string"
|
||||
format: "uri"
|
||||
description: "Original image URL"
|
||||
example: "http://yourinstance/media/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996.jpg"
|
||||
square_crop:
|
||||
type: "string"
|
||||
format: "uri"
|
||||
description: "400x400 thumbnail URL"
|
||||
example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-400x400-70.jpg"
|
||||
small_square_crop:
|
||||
type: "string"
|
||||
format: "uri"
|
||||
description: "50x50 thumbnail URL"
|
||||
example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-50x50-70.jpg"
|
||||
medium_square_crop:
|
||||
type: "string"
|
||||
format: "uri"
|
||||
description: "200x200 thumbnail URL"
|
||||
example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-200x200-70.jpg"
|
||||
QuotaStatus:
|
||||
|
||||
QuotaStatus:
|
||||
type: "object"
|
||||
properties:
|
||||
max:
|
||||
|
|
|
@ -296,7 +296,7 @@ paths:
|
|||
responses:
|
||||
200:
|
||||
$ref: "#/responses/200"
|
||||
/api/v1/users/users/me/:
|
||||
/api/v1/users/me/:
|
||||
get:
|
||||
summary: Retrive profile information
|
||||
description: |
|
||||
|
|
|
@ -337,7 +337,7 @@ export default {
|
|||
},
|
||||
getCover(albumCover) {
|
||||
if (albumCover) {
|
||||
return albumCover.medium_square_crop
|
||||
return albumCover.urls.medium_square_crop
|
||||
}
|
||||
},
|
||||
getSources (uploads) {
|
||||
|
|
|
@ -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.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)">
|
||||
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)">
|
||||
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)">
|
||||
<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.medium_square_crop)">
|
||||
<img class="ui image" alt="" v-else src="../assets/audio/default-cover.png">
|
||||
<h1 class="ui header">
|
||||
<div class="content ellipsis">
|
||||
|
@ -159,8 +159,8 @@
|
|||
<i class="grip lines icon"></i>
|
||||
</td>
|
||||
<td class="image-cell" @click="$store.dispatch('queue/currentIndex', index)">
|
||||
<img class="ui mini image" alt="" v-if="track.cover && track.cover.original" :src="$store.getters['instance/absoluteUrl'](track.cover.medium_square_crop)">
|
||||
<img class="ui mini image" alt="" v-else-if="track.album && track.album.cover && track.album.cover.original" :src="$store.getters['instance/absoluteUrl'](track.album.cover.medium_square_crop)">
|
||||
<img class="ui mini image" alt="" v-if="track.cover && track.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](track.cover.urls.medium_square_crop)">
|
||||
<img class="ui mini image" alt="" v-else-if="track.album && track.album.cover && track.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)">
|
||||
<img class="ui mini image" alt="" v-else src="../assets/audio/default-cover.png">
|
||||
</td>
|
||||
<td colspan="3" @click="$store.dispatch('queue/currentIndex', index)">
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
</router-link>
|
||||
<div class="item">
|
||||
<div class="ui user-dropdown dropdown" >
|
||||
<img class="ui avatar image" alt="" v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.square_crop" :src="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.square_crop)" />
|
||||
<img class="ui avatar image" alt="" v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.urls.square_crop" :src="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.urls.square_crop)" />
|
||||
<actor-avatar v-else :actor="{preferred_username: $store.state.auth.username, full_username: $store.state.auth.username}" />
|
||||
<div class="menu">
|
||||
<router-link class="item" :to="{name: 'profile.overview', params: {username: $store.state.auth.username}}"><translate translate-context="*/*/*/Noun">Profile</translate></router-link>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<router-link class="artist-label ui image label" :to="route">
|
||||
<img :class="[{circular: artist.content_category != 'podcast'}]" alt="" v-if="artist.cover && artist.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](artist.cover.small_square_crop)" />
|
||||
<img alt="" :class="[{circular: artist.content_category != 'podcast'}]" v-if="artist.cover && artist.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](artist.cover.urls.medium_square_crop)" />
|
||||
<i :class="[artist.content_category != 'podcast' ? 'circular' : 'bordered', 'inverted violet users icon']" v-else />
|
||||
{{ artist.name }}
|
||||
</router-link>
|
||||
|
|
|
@ -60,7 +60,7 @@ export default {
|
|||
computed: {
|
||||
imageUrl () {
|
||||
if (this.object.artist.cover) {
|
||||
return this.$store.getters['instance/absoluteUrl'](this.object.artist.cover.medium_square_crop)
|
||||
return this.$store.getters['instance/absoluteUrl'](this.object.artist.cover.urls.medium_square_crop)
|
||||
}
|
||||
},
|
||||
urlId () {
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
||||
alt=""
|
||||
class="channel-image image"
|
||||
v-if="cover && cover.original"
|
||||
v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
|
||||
v-if="cover && cover.urls.original"
|
||||
v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
|
||||
<span
|
||||
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
||||
class="channel-image image"
|
||||
|
@ -17,8 +17,8 @@
|
|||
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
||||
alt=""
|
||||
class="channel-image image"
|
||||
v-else-if="entry.album && entry.album.cover && entry.album.cover.original"
|
||||
v-lazy="$store.getters['instance/absoluteUrl'](entry.album.cover.square_crop)">
|
||||
v-else-if="entry.album && entry.album.cover && entry.album.cover.urls.original"
|
||||
v-lazy="$store.getters['instance/absoluteUrl'](entry.album.cover.urls.square_crop)">
|
||||
<img
|
||||
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
|
||||
alt=""
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<div class="channel-serie-card">
|
||||
<div class="two-images">
|
||||
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-if="cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
|
||||
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-if="cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
|
||||
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-if="cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
|
||||
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-else src="../../assets/audio/default-cover.png">
|
||||
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-if="cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
|
||||
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-else src="../../assets/audio/default-cover.png">
|
||||
</div>
|
||||
<div class="content ellipsis">
|
||||
<strong>
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
<div class="controls track-controls queue-not-focused desktop-and-up">
|
||||
<div class="ui tiny image" @click.stop.prevent="$router.push({name: 'library.tracks.detail', params: {id: currentTrack.id }})">
|
||||
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)">
|
||||
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)">
|
||||
<img v-else src="../../assets/audio/default-cover.png" alt="">
|
||||
<img alt="" ref="cover" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)">
|
||||
<img alt="" ref="cover" v-else-if="currentTrack.album && currentTrack.album.cover.urls && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)">
|
||||
<img alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
</div>
|
||||
<div @click.stop.prevent="" class="middle aligned content ellipsis">
|
||||
<strong>
|
||||
|
@ -30,9 +30,9 @@
|
|||
</div>
|
||||
<div class="controls track-controls queue-not-focused tablet-and-below">
|
||||
<div class="ui tiny image">
|
||||
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)">
|
||||
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)">
|
||||
<img v-else src="../../assets/audio/default-cover.png" alt="">
|
||||
<img alt="" ref="cover" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)">
|
||||
<img alt="" ref="cover" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)">
|
||||
<img alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
</div>
|
||||
<div class="middle aligned content ellipsis">
|
||||
<strong>
|
||||
|
@ -738,12 +738,12 @@ export default {
|
|||
if (this.currentTrack.album) {
|
||||
metadata.album = this.currentTrack.album.title
|
||||
metadata.artwork = [
|
||||
{ src: this.currentTrack.album.cover.original, sizes: '96x96', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.original, sizes: '128x128', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.original, sizes: '192x192', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.original, sizes: '256x256', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.original, sizes: '384x384', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.original, sizes: '512x512', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.urls.original, sizes: '96x96', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.urls.original, sizes: '128x128', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.urls.original, sizes: '192x192', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.urls.original, sizes: '256x256', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.urls.original, sizes: '384x384', type: 'image/png' },
|
||||
{ src: this.currentTrack.album.cover.urls.original, sizes: '512x512', type: 'image/png' },
|
||||
]
|
||||
}
|
||||
navigator.mediaSession.metadata = new MediaMetadata(metadata);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="card app-card component-album-card">
|
||||
<div
|
||||
@click="$router.push({name: 'library.albums.detail', params: {id: album.id}})"
|
||||
:class="['ui', 'head-image', 'image', {'default-cover': !album.cover.original}]" v-lazy:background-image="imageUrl">
|
||||
:class="['ui', 'head-image', 'image', {'default-cover': !album.cover || !album.cover.urls.original}]" v-lazy:background-image="imageUrl">
|
||||
<play-button :icon-only="true" :is-playable="album.is_playable" :button-classes="['ui', 'circular', 'large', 'vibrant', 'icon', 'button']" :album="album"></play-button>
|
||||
</div>
|
||||
<div class="content">
|
||||
|
@ -38,8 +38,8 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
imageUrl () {
|
||||
if (this.album.cover.original) {
|
||||
return this.$store.getters['instance/absoluteUrl'](this.album.cover.medium_square_crop)
|
||||
if (this.album.cover && this.album.cover.urls.original) {
|
||||
return this.$store.getters['instance/absoluteUrl'](this.album.cover.urls.medium_square_crop)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="app-card card">
|
||||
<div
|
||||
@click="$router.push({name: 'library.artists.detail', params: {id: artist.id}})"
|
||||
:class="['ui', 'head-image', 'circular', 'image', {'default-cover': !cover.original}]" v-lazy:background-image="imageUrl">
|
||||
:class="['ui', 'head-image', 'circular', 'image', {'default-cover': !cover || !cover.urls.original}]" v-lazy:background-image="imageUrl">
|
||||
<play-button :icon-only="true" :is-playable="artist.is_playable" :button-classes="['ui', 'circular', 'large', 'vibrant', 'icon', 'button']" :artist="artist"></play-button>
|
||||
</div>
|
||||
<div class="content">
|
||||
|
@ -40,19 +40,19 @@ export default {
|
|||
computed: {
|
||||
imageUrl () {
|
||||
let cover = this.cover
|
||||
if (cover.original) {
|
||||
return this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop)
|
||||
if (cover && cover.urls.original) {
|
||||
return this.$store.getters['instance/absoluteUrl'](cover.urls.medium_square_crop)
|
||||
}
|
||||
},
|
||||
cover () {
|
||||
if (this.artist.cover && this.artist.cover.original) {
|
||||
if (this.artist.cover && this.artist.cover.urls.original) {
|
||||
return this.artist.cover
|
||||
}
|
||||
return this.artist.albums.map((a) => {
|
||||
return a.cover
|
||||
}).filter((c) => {
|
||||
return c && c.original
|
||||
})[0] || {}
|
||||
return c && c.urls.original
|
||||
})[0]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<play-button :class="['basic', {vibrant: currentTrack && isPlaying && track.id === currentTrack.id}, 'icon']" :discrete="true" :is-playable="playable" :track="track"></play-button>
|
||||
</td>
|
||||
<td>
|
||||
<img class="ui mini image" alt="" v-if="track.album && track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.small_square_crop)">
|
||||
<img class="ui mini image" alt="" v-else src="../../../assets/audio/default-cover.png">
|
||||
<img alt="" class="ui mini image" v-if="track.album && track.album.cover && track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)">
|
||||
<img alt="" class="ui mini image" v-else src="../../../assets/audio/default-cover.png">
|
||||
</td>
|
||||
<td colspan="6">
|
||||
<router-link class="track" :to="{name: 'library.tracks.detail', params: {id: track.id }}">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div v-if="count > 0" class="ui divided unstackable items">
|
||||
<div :class="['item', itemClasses]" v-for="object in objects" :key="object.id">
|
||||
<div class="ui tiny image">
|
||||
<img alt="" v-if="object.track.album && object.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.medium_square_crop)">
|
||||
<img alt="" v-if="object.track.album && object.track.album.cover" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.urls.medium_square_crop)">
|
||||
<img alt="" v-else src="../../../assets/audio/default-cover.png">
|
||||
<play-button class="play-overlay" :icon-only="true" :button-classes="['ui', 'circular', 'tiny', 'vibrant', 'icon', 'button']" :track="object.track"></play-button>
|
||||
</div>
|
||||
|
|
|
@ -416,12 +416,12 @@ export default {
|
|||
this.settings.errors = []
|
||||
let self = this
|
||||
let payload = this.settingsValues
|
||||
let url = `users/users/${this.$store.state.auth.username}/`
|
||||
let url = `users/${this.$store.state.auth.username}/`
|
||||
return axios.patch(url, payload).then(
|
||||
response => {
|
||||
logger.default.info("Updated settings successfully")
|
||||
self.settings.success = true
|
||||
return axios.get("users/users/me/").then(response => {
|
||||
return axios.get("users/me/").then(response => {
|
||||
self.$store.dispatch("auth/updateProfile", response.data)
|
||||
})
|
||||
},
|
||||
|
@ -487,7 +487,7 @@ export default {
|
|||
this.avatarErrors = []
|
||||
let self = this
|
||||
axios
|
||||
.patch(`users/users/${this.$store.state.auth.username}/`, {avatar: uuid})
|
||||
.patch(`users/${this.$store.state.auth.username}/`, {avatar: uuid})
|
||||
.then(
|
||||
response => {
|
||||
this.isLoadingAvatar = false
|
||||
|
@ -538,7 +538,7 @@ export default {
|
|||
confirm: true,
|
||||
password: this.password,
|
||||
}
|
||||
axios.delete(`users/users/me/`, {data: payload})
|
||||
axios.delete(`users/me/`, {data: payload})
|
||||
.then(
|
||||
response => {
|
||||
self.isDeletingAccount = false
|
||||
|
|
|
@ -87,7 +87,7 @@ export default {
|
|||
this.errors = []
|
||||
this.isLoading = true
|
||||
let self = this
|
||||
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
let url = `users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
return axios.get(url).then(response => {
|
||||
self.token = response.data['subsonic_api_token']
|
||||
self.isLoading = false
|
||||
|
@ -102,7 +102,7 @@ export default {
|
|||
this.errors = []
|
||||
this.isLoading = true
|
||||
let self = this
|
||||
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
let url = `users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
return axios.post(url, {}).then(response => {
|
||||
self.showToken = true
|
||||
self.token = response.data['subsonic_api_token']
|
||||
|
@ -119,7 +119,7 @@ export default {
|
|||
this.errors = []
|
||||
this.isLoading = true
|
||||
let self = this
|
||||
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
let url = `users/${this.$store.state.auth.username}/subsonic-token/`
|
||||
return axios.delete(url).then(response => {
|
||||
self.isLoading = false
|
||||
self.token = null
|
||||
|
|
|
@ -347,7 +347,7 @@ export default {
|
|||
},
|
||||
fetchQuota () {
|
||||
let self = this
|
||||
axios.get('users/users/me/').then((response) => {
|
||||
axios.get('users/me/').then((response) => {
|
||||
self.quotaStatus = response.data.quota_status
|
||||
})
|
||||
},
|
||||
|
@ -391,8 +391,8 @@ export default {
|
|||
value: c.uuid,
|
||||
selected: self.channel && self.channel.uuid === c.uuid,
|
||||
}
|
||||
if (c.artist.cover && c.artist.cover.small_square_crop) {
|
||||
let coverUrl = self.$store.getters['instance/absoluteUrl'](c.artist.cover.small_square_crop)
|
||||
if (c.artist.cover && c.artist.cover.urls.medium_square_crop) {
|
||||
let coverUrl = self.$store.getters['instance/absoluteUrl'](c.artist.cover.urls.medium_square_crop)
|
||||
d.image = coverUrl
|
||||
if (c.artist.content_category === 'podcast') {
|
||||
d.imageClass = 'ui image'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<img alt="" v-if="actor.icon && actor.icon.original" :src="actor.icon.small_square_crop" class="ui avatar circular image" />
|
||||
<img alt="" v-if="actor.icon && actor.icon.urls.original" :src="actor.icon.urls.medium_square_crop" class="ui avatar circular image" />
|
||||
<span v-else :style="defaultAvatarStyle" class="ui avatar circular label">{{ actor.preferred_username[0]}}</span>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<img
|
||||
class="ui tiny circular avatar"
|
||||
alt=""
|
||||
v-if="user.avatar && user.avatar.small_square_crop"
|
||||
v-lazy="$store.getters['instance/absoluteUrl'](user.avatar.small_square_crop)" />
|
||||
v-if="user.avatar && user.avatar.urls.medium_square_crop"
|
||||
v-lazy="$store.getters['instance/absoluteUrl'](user.avatar.urls.medium_square_crop)" />
|
||||
<span v-else :style="defaultAvatarStyle" class="ui circular label">{{ user.username[0]}}</span>
|
||||
|
||||
</template>
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
<div class="ui two column grid" v-if="isSerie">
|
||||
<div class="column">
|
||||
<div class="large two-images">
|
||||
<img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
|
||||
<img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
<img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
|
||||
<img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
<img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
|
||||
<img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png">
|
||||
<img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
|
||||
<img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png">
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui column right aligned">
|
||||
|
@ -53,8 +53,8 @@
|
|||
</header>
|
||||
</div>
|
||||
<div v-else class="ui center aligned text padded basic segment">
|
||||
<img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
|
||||
<img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
<img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
|
||||
<img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png">
|
||||
<div class="ui hidden divider"></div>
|
||||
<header>
|
||||
<h2 class="ui header" :title="object.title">
|
||||
|
|
|
@ -235,12 +235,12 @@ export default {
|
|||
)
|
||||
},
|
||||
cover() {
|
||||
if (this.object.cover && this.object.cover.original) {
|
||||
if (this.object.cover && this.object.cover.urls.original) {
|
||||
return this.object.cover
|
||||
}
|
||||
return this.object.albums
|
||||
.filter(album => {
|
||||
return album.cover && album.cover.original
|
||||
return album.cover && album.cover.urls.original
|
||||
})
|
||||
.map(album => {
|
||||
return album.cover
|
||||
|
@ -253,12 +253,12 @@ export default {
|
|||
})
|
||||
},
|
||||
headerStyle() {
|
||||
if (!this.cover || !this.cover.original) {
|
||||
if (!this.cover || !this.cover.urls.original) {
|
||||
return ""
|
||||
}
|
||||
return (
|
||||
"background-image: url(" +
|
||||
this.$store.getters["instance/absoluteUrl"](this.cover.original) +
|
||||
this.$store.getters["instance/absoluteUrl"](this.cover.urls.original) +
|
||||
")"
|
||||
)
|
||||
},
|
||||
|
|
|
@ -274,7 +274,7 @@ export default {
|
|||
fetchQuota () {
|
||||
let self = this
|
||||
self.isLoadingQuota = true
|
||||
axios.get('users/users/me/').then((response) => {
|
||||
axios.get('users/me/').then((response) => {
|
||||
self.quotaStatus = response.data.quota_status
|
||||
self.isLoadingQuota = false
|
||||
})
|
||||
|
|
|
@ -264,12 +264,12 @@ export default {
|
|||
return route.href
|
||||
},
|
||||
headerStyle() {
|
||||
if (!this.cover || !this.cover.original) {
|
||||
if (!this.cover || !this.cover.urls.original) {
|
||||
return ""
|
||||
}
|
||||
return (
|
||||
"background-image: url(" +
|
||||
this.$store.getters["instance/absoluteUrl"](this.cover.original) +
|
||||
this.$store.getters["instance/absoluteUrl"](this.cover.urls.original) +
|
||||
")"
|
||||
)
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<section class="ui vertical stripe segment">
|
||||
<div class="ui stackable grid row container">
|
||||
<div class="six wide column">
|
||||
<img class="image" alt="" v-if="cover && cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
|
||||
<img alt="" class="image" v-if="cover && cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
|
||||
<template v-if="upload">
|
||||
<h3 class="ui header">
|
||||
<translate key="1" v-if="track.artist.content_category === 'music'" translate-context="Content/*/*">Track Details</translate>
|
||||
|
@ -223,7 +223,7 @@ export default {
|
|||
return this.licenseData
|
||||
},
|
||||
cover () {
|
||||
if (this.track.cover && this.track.cover.original) {
|
||||
if (this.track.cover && this.track.cover.urls.original) {
|
||||
return this.track.cover
|
||||
}
|
||||
if (this.track.album && this.track.album.cover) {
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<tr v-for="(plt, index) in plts" :key="`${index}-${plt.track.id}`">
|
||||
<td class="left aligned">{{ plt.index + 1}}</td>
|
||||
<td class="center aligned">
|
||||
<img alt="" class="ui mini image" v-if="plt.track.album && plt.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.small_square_crop)">
|
||||
<img alt="" class="ui mini image" v-if="plt.track.album && plt.track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.urls.medium_square_crop)">
|
||||
<img alt="" class="ui mini image" v-else src="../../assets/audio/default-cover.png">
|
||||
</td>
|
||||
<td colspan="4">
|
||||
|
|
|
@ -182,7 +182,7 @@ export default {
|
|||
fetchProfile ({commit, dispatch, state}) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.get('users/users/me/').then((response) => {
|
||||
axios.get('users/me/').then((response) => {
|
||||
logger.default.info('Successfully fetched user profile')
|
||||
dispatch('ui/initSettings', response.data.settings, { root: true })
|
||||
dispatch('updateProfile', response.data).then(() => {
|
||||
|
|
|
@ -33,7 +33,7 @@ export default {
|
|||
let playlists = []
|
||||
let url = 'playlists/'
|
||||
while (url != null) {
|
||||
let response = await axios.get(url, {params: {user: userId}})
|
||||
let response = await axios.get(url, {params: {scope: "me"}})
|
||||
playlists = [...playlists, ...response.data.results]
|
||||
url = response.data.next
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ export default {
|
|||
}
|
||||
payload[field] = newDisplayDate
|
||||
let self = this
|
||||
axios.patch(`users/users/${this.$store.state.auth.username}/`, payload).then((response) => {
|
||||
axios.patch(`users/${this.$store.state.auth.username}/`, payload).then((response) => {
|
||||
self.$store.commit('auth/profilePartialUpdate', response.data)
|
||||
})
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="ui column">
|
||||
<div class="segment-content">
|
||||
<h2 class="ui header">
|
||||
<img alt="" v-if="object.artist.cover && object.artist.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.artist.cover.square_crop)">
|
||||
<img alt="" v-if="object.artist.cover && object.artist.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.artist.cover.urls.square_crop)">
|
||||
<img alt="" v-else src="../../assets/audio/default-cover.png">
|
||||
<div class="content">
|
||||
{{ object.artist.name | truncate(100) }}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="ui column">
|
||||
<div class="segment-content">
|
||||
<h2 class="ui header">
|
||||
<img alt="" v-if="object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
|
||||
<img alt="" v-if="object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
|
||||
<img alt="" v-else src="../../../assets/audio/default-cover.png">
|
||||
<div class="content">
|
||||
{{ object.title | truncate(100) }}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="ui column">
|
||||
<div class="segment-content">
|
||||
<h2 class="ui header">
|
||||
<img alt="" v-if="object.cover && object.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
|
||||
<img alt="" v-if="object.cover && object.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
|
||||
<img alt="" v-else src="../../../assets/audio/default-cover.png">
|
||||
<div class="content">
|
||||
{{ object.name | truncate(100) }}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="ui column">
|
||||
<div class="segment-content">
|
||||
<h2 class="ui header">
|
||||
<img alt="" v-if="object.cover && object.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
|
||||
<img alt="" v-if="object.cover && object.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
|
||||
<img alt="" v-else src="../../../assets/audio/default-cover.png">
|
||||
<div class="content">
|
||||
{{ object.title | truncate(100) }}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</div>
|
||||
<h1 class="ui center aligned icon header">
|
||||
<i v-if="!object.icon" class="circular inverted user success icon"></i>
|
||||
<img alt="" class="ui big circular image" v-else v-lazy="$store.getters['instance/absoluteUrl'](object.icon.square_crop)" />
|
||||
<img alt="" class="ui big circular image" v-else v-lazy="$store.getters['instance/absoluteUrl'](object.icon.urls.square_crop)" />
|
||||
<div class="ellispsis content">
|
||||
<div class="ui very small hidden divider"></div>
|
||||
<span>{{ displayName }}</span>
|
||||
|
@ -49,7 +49,7 @@
|
|||
@updated="$emit('updated', $event)"
|
||||
:content="object.summary"
|
||||
:field-name="'summary'"
|
||||
:update-url="`users/users/${$store.state.auth.username}/`"
|
||||
:update-url="`users/${$store.state.auth.username}/`"
|
||||
:can-update="$store.state.auth.authenticated && object.full_username === $store.state.auth.fullUsername"></rendered-description>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
@updated="$emit('updated', $event)"
|
||||
:content="object.summary"
|
||||
:field-name="'summary'"
|
||||
:update-url="`users/users/${$store.state.auth.username}/`"
|
||||
:update-url="`users/${$store.state.auth.username}/`"
|
||||
:can-update="$store.state.auth.authenticated && object.full_username === $store.state.auth.fullUsername"></rendered-description>
|
||||
<div class="ui hidden divider"></div>
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="seven wide column">
|
||||
<div class="ui two column grid">
|
||||
<div class="column">
|
||||
<img alt="" class="huge channel-image" v-if="object.artist.cover" :src="$store.getters['instance/absoluteUrl'](object.artist.cover.medium_square_crop)">
|
||||
<img alt="" class="huge channel-image" v-if="object.artist.cover" :src="$store.getters['instance/absoluteUrl'](object.artist.cover.urls.medium_square_crop)">
|
||||
<i v-else class="huge circular inverted users violet icon"></i>
|
||||
</div>
|
||||
<div class="ui column right aligned">
|
||||
|
|
|
@ -114,7 +114,7 @@ export default {
|
|||
fetch () {
|
||||
let self = this
|
||||
self.isLoading = true
|
||||
axios.get('users/users/me/').then((response) => {
|
||||
axios.get('users/me/').then((response) => {
|
||||
self.quotaStatus = response.data.quota_status
|
||||
self.isLoading = false
|
||||
})
|
||||
|
|
|
@ -146,7 +146,7 @@ describe('store/auth', () => {
|
|||
admin: true
|
||||
}
|
||||
}
|
||||
moxios.stubRequest('users/users/me/', {
|
||||
moxios.stubRequest('users/me/', {
|
||||
status: 200,
|
||||
response: profile
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue