diff --git a/api/funkwhale_api/favorites/serializers.py b/api/funkwhale_api/favorites/serializers.py
index 16171aa34bd05eea4991969de09d46f5b76a0508..66e10a1b49275781fc5b68d785b613b6b46a2079 100644
--- a/api/funkwhale_api/favorites/serializers.py
+++ b/api/funkwhale_api/favorites/serializers.py
@@ -1,4 +1,3 @@
-
 from rest_framework import serializers
 
 from funkwhale_api.activity import serializers as activity_serializers
diff --git a/api/funkwhale_api/federation/dynamic_preferences_registry.py b/api/funkwhale_api/federation/dynamic_preferences_registry.py
index 5119d2596fab750b6312d5afbdc3c6d2447b80d0..01bfdf72744b51d6d9c86638c2a40004cbc6171f 100644
--- a/api/funkwhale_api/federation/dynamic_preferences_registry.py
+++ b/api/funkwhale_api/federation/dynamic_preferences_registry.py
@@ -1,4 +1,3 @@
-
 from dynamic_preferences import types
 from dynamic_preferences.registries import global_preferences_registry
 
diff --git a/api/funkwhale_api/playlists/models.py b/api/funkwhale_api/playlists/models.py
index 3616c8821805d8247440264c4e54833860d517bf..5106203341168e4c3200c80f8bca39ff118c3b4b 100644
--- a/api/funkwhale_api/playlists/models.py
+++ b/api/funkwhale_api/playlists/models.py
@@ -38,6 +38,23 @@ class PlaylistQuerySet(models.QuerySet):
         )
         return self.prefetch_related(plt_prefetch)
 
+    def annotate_playable_by_actor(self, actor):
+        plts = (
+            PlaylistTrack.objects.playable_by(actor)
+            .filter(playlist=models.OuterRef("id"))
+            .order_by("id")
+            .values("id")[:1]
+        )
+        subquery = models.Subquery(plts)
+        return self.annotate(is_playable_by_actor=subquery)
+
+    def playable_by(self, actor, include=True):
+        plts = PlaylistTrack.objects.playable_by(actor, include)
+        if include:
+            return self.filter(playlist_tracks__in=plts)
+        else:
+            return self.exclude(playlist_tracks__in=plts)
+
 
 class Playlist(models.Model):
     name = models.CharField(max_length=50)
@@ -139,6 +156,23 @@ class PlaylistTrackQuerySet(models.QuerySet):
             )
         )
 
+    def annotate_playable_by_actor(self, actor):
+        tracks = (
+            music_models.Track.objects.playable_by(actor)
+            .filter(pk=models.OuterRef("track"))
+            .order_by("id")
+            .values("id")[:1]
+        )
+        subquery = models.Subquery(tracks)
+        return self.annotate(is_playable_by_actor=subquery)
+
+    def playable_by(self, actor, include=True):
+        tracks = music_models.Track.objects.playable_by(actor, include)
+        if include:
+            return self.filter(track__pk__in=tracks)
+        else:
+            return self.exclude(track__pk__in=tracks)
+
 
 class PlaylistTrack(models.Model):
     track = models.ForeignKey(
diff --git a/api/funkwhale_api/playlists/serializers.py b/api/funkwhale_api/playlists/serializers.py
index a60a349387020a2dd110c9f101fef0bdfce0510a..40a1c62b5115a375f37a1d402a066794c08ef59d 100644
--- a/api/funkwhale_api/playlists/serializers.py
+++ b/api/funkwhale_api/playlists/serializers.py
@@ -11,10 +11,17 @@ from . import models
 
 class PlaylistTrackSerializer(serializers.ModelSerializer):
     track = TrackSerializer()
+    is_playable = serializers.SerializerMethodField()
 
     class Meta:
         model = models.PlaylistTrack
-        fields = ("id", "track", "playlist", "index", "creation_date")
+        fields = ("id", "track", "playlist", "index", "creation_date", "is_playable")
+
+    def get_is_playable(self, obj):
+        try:
+            return bool(obj.is_playable_by_actor)
+        except AttributeError:
+            return None
 
 
 class PlaylistTrackWriteSerializer(serializers.ModelSerializer):
@@ -68,6 +75,7 @@ class PlaylistSerializer(serializers.ModelSerializer):
     duration = serializers.SerializerMethodField(read_only=True)
     album_covers = serializers.SerializerMethodField(read_only=True)
     user = UserBasicSerializer(read_only=True)
+    is_playable = serializers.SerializerMethodField()
 
     class Meta:
         model = models.Playlist
@@ -81,9 +89,16 @@ class PlaylistSerializer(serializers.ModelSerializer):
             "tracks_count",
             "album_covers",
             "duration",
+            "is_playable",
         )
         read_only_fields = ["id", "modification_date", "creation_date"]
 
+    def get_is_playable(self, obj):
+        try:
+            return bool(obj.is_playable_by_actor)
+        except AttributeError:
+            return None
+
     def get_tracks_count(self, obj):
         try:
             return obj.tracks_count
diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py
index 8db076a8608fa388d8a8fedda646836c2df20ef5..0c90335a927e1f4f98b1ee72475f03b5c8edfb91 100644
--- a/api/funkwhale_api/playlists/views.py
+++ b/api/funkwhale_api/playlists/views.py
@@ -6,7 +6,7 @@ from rest_framework.permissions import IsAuthenticatedOrReadOnly
 from rest_framework.response import Response
 
 from funkwhale_api.common import fields, permissions
-
+from funkwhale_api.music import utils as music_utils
 from . import filters, models, serializers
 
 
@@ -74,7 +74,9 @@ class PlaylistViewSet(
         return Response(status=204)
 
     def get_queryset(self):
-        return self.queryset.filter(fields.privacy_level_query(self.request.user))
+        return self.queryset.filter(
+            fields.privacy_level_query(self.request.user)
+        ).annotate_playable_by_actor(music_utils.get_actor_from_request(self.request))
 
     def perform_create(self, serializer):
         return serializer.save(
@@ -116,7 +118,7 @@ class PlaylistTrackViewSet(
                 lookup_field="playlist__privacy_level",
                 user_field="playlist__user",
             )
-        )
+        ).annotate_playable_by_actor(music_utils.get_actor_from_request(self.request))
 
     def perform_destroy(self, instance):
         instance.delete(update_indexes=True)
diff --git a/api/funkwhale_api/taskapp/celery.py b/api/funkwhale_api/taskapp/celery.py
index bf7d4da697d0fb541a65a277fcc87b3d7b11c565..92fb2a0d9abad41e1b8810bc7515bb1e691aeaef 100644
--- a/api/funkwhale_api/taskapp/celery.py
+++ b/api/funkwhale_api/taskapp/celery.py
@@ -1,4 +1,3 @@
-
 from __future__ import absolute_import
 
 import functools
diff --git a/api/tests/activity/test_record.py b/api/tests/activity/test_record.py
index 69d3a28cfa5ec0b325025a0d1bfcf5548a6bfaf5..5b18a81ec67367df48592779ccf5e2c833cbffe8 100644
--- a/api/tests/activity/test_record.py
+++ b/api/tests/activity/test_record.py
@@ -1,4 +1,3 @@
-
 from django.db import models
 from rest_framework import serializers
 
diff --git a/api/tests/federation/test_activity.py b/api/tests/federation/test_activity.py
index 5f60b37cde321b88e8d903f97f4687eb01cc31db..9604582e562ac80ce98afc6087f5d30389b5f144 100644
--- a/api/tests/federation/test_activity.py
+++ b/api/tests/federation/test_activity.py
@@ -1,4 +1,3 @@
-
 import pytest
 import uuid
 
diff --git a/api/tests/instance/test_nodeinfo.py b/api/tests/instance/test_nodeinfo.py
index 181ddf2772f3af2cb838e84ebf7718c8cb82eddd..0fa1b4fc3a5bf24122bb9aaf0c413fbbfbb4e60f 100644
--- a/api/tests/instance/test_nodeinfo.py
+++ b/api/tests/instance/test_nodeinfo.py
@@ -1,4 +1,3 @@
-
 import funkwhale_api
 from funkwhale_api.instance import nodeinfo
 
diff --git a/api/tests/playlists/test_models.py b/api/tests/playlists/test_models.py
index 25c40d5573ea9c67e4a3926ddfd7024032c8ab78..46c14d11c7f34ab7088840a60e5e57eb726b2a95 100644
--- a/api/tests/playlists/test_models.py
+++ b/api/tests/playlists/test_models.py
@@ -122,3 +122,38 @@ def test_insert_many_honor_max_tracks(preferences, factories):
     track = factories["music.Track"]()
     with pytest.raises(exceptions.ValidationError):
         playlist.insert_many([track, track, track])
+
+
+@pytest.mark.parametrize(
+    "privacy_level,expected", [("me", False), ("instance", False), ("everyone", True)]
+)
+def test_playlist_track_playable_by_anonymous(privacy_level, expected, factories):
+    plt = factories["playlists.PlaylistTrack"]()
+    track = plt.track
+    factories["music.Upload"](
+        track=track, library__privacy_level=privacy_level, import_status="finished"
+    )
+    queryset = plt.__class__.objects.playable_by(None).annotate_playable_by_actor(None)
+    match = plt in list(queryset)
+    assert match is expected
+    if expected:
+        assert bool(queryset.first().is_playable_by_actor) is expected
+
+
+@pytest.mark.parametrize(
+    "privacy_level,expected", [("me", False), ("instance", False), ("everyone", True)]
+)
+def test_playlist_playable_by_anonymous(privacy_level, expected, factories):
+    plt = factories["playlists.PlaylistTrack"]()
+    playlist = plt.playlist
+    track = plt.track
+    factories["music.Upload"](
+        track=track, library__privacy_level=privacy_level, import_status="finished"
+    )
+    queryset = playlist.__class__.objects.playable_by(None).annotate_playable_by_actor(
+        None
+    )
+    match = playlist in list(queryset)
+    assert match is expected
+    if expected:
+        assert bool(queryset.first().is_playable_by_actor) is expected
diff --git a/api/tests/playlists/test_views.py b/api/tests/playlists/test_views.py
index e7b47c7a2d924032e55d324b4bdc05d2e8f8341d..1c2b0f19eea43fce59dcf0ed166badd8e5603265 100644
--- a/api/tests/playlists/test_views.py
+++ b/api/tests/playlists/test_views.py
@@ -25,6 +25,16 @@ def test_serializer_includes_tracks_count(factories, logged_in_api_client):
     assert response.data["tracks_count"] == 1
 
 
+def test_serializer_includes_is_playable(factories, logged_in_api_client):
+    playlist = factories["playlists.Playlist"]()
+    factories["playlists.PlaylistTrack"](playlist=playlist)
+
+    url = reverse("api:v1:playlists-detail", kwargs={"pk": playlist.pk})
+    response = logged_in_api_client.get(url)
+
+    assert response.data["is_playable"] is False
+
+
 def test_playlist_inherits_user_privacy(logged_in_api_client):
     url = reverse("api:v1:playlists-list")
     user = logged_in_api_client.user
diff --git a/front/src/components/library/Library.vue b/front/src/components/library/Library.vue
index db2ac27b4aced81c3450a38e41b458b149429166..01a357724990ed107cffd4d3d7f50e06d9fb4e4d 100644
--- a/front/src/components/library/Library.vue
+++ b/front/src/components/library/Library.vue
@@ -13,14 +13,6 @@
       <router-link class="ui item" to="/library/playlists" exact>
         <translate>Playlists</translate>
       </router-link>
-      <div class="ui secondary right menu">
-        <router-link v-if="showImports" class="ui item" to="/library/import/launch" exact>
-          <translate>Import</translate>
-        </router-link>
-        <router-link v-if="showImports" class="ui item" to="/library/import/batches">
-          <translate>Import batches</translate>
-        </router-link>
-      </div>
     </div>
     <router-view :key="$route.fullPath"></router-view>
   </div>
diff --git a/front/src/components/playlists/Card.vue b/front/src/components/playlists/Card.vue
index 956a543a6cf66165c6808f3a4d2ffbf5b2c87959..344eb5fbf9ecbc17e7d744d85cdb4efdf2b3d17e 100644
--- a/front/src/components/playlists/Card.vue
+++ b/front/src/components/playlists/Card.vue
@@ -5,8 +5,8 @@
     <div class="content">
       <div class="header">
         <div class="right floated">
-          <play-button :icon-only="true" class="ui inline" :button-classes="['ui', 'circular', 'large', {orange: playlist.tracks_count > 0}, 'icon', 'button', {disabled: playlist.tracks_count === 0}]" :playlist="playlist"></play-button>
-          <play-button class="basic inline icon" :dropdown-only="true" :dropdown-icon-classes="['ellipsis', 'vertical', 'large', {disabled: playlist.tracks_count === 0}, 'grey']" :playlist="playlist"></play-button>
+          <play-button :is-playable="playlist.is_playable" :icon-only="true" class="ui inline" :button-classes="['ui', 'circular', 'large', {orange: playlist.tracks_count > 0}, 'icon', 'button', {disabled: playlist.tracks_count === 0}]" :playlist="playlist"></play-button>
+          <play-button :is-playable="playlist.is_playable" class="basic inline icon" :dropdown-only="true" :dropdown-icon-classes="['ellipsis', 'vertical', 'large', {disabled: playlist.tracks_count === 0}, 'grey']" :playlist="playlist"></play-button>
         </div>
         <router-link :title="playlist.name" class="discrete link" :to="{name: 'library.playlists.detail', params: {id: playlist.id }}">
           {{ playlist.name | truncate(30) }}
diff --git a/front/src/views/content/libraries/Quota.vue b/front/src/views/content/libraries/Quota.vue
index e9c4738e1240fed76e891a7c729d0cc5085ba9f4..92e5ad634ed51fc65480f50fac3bf0e7cfc136b4 100644
--- a/front/src/views/content/libraries/Quota.vue
+++ b/front/src/views/content/libraries/Quota.vue
@@ -5,7 +5,7 @@
       <div class="ui text loader"><translate>Loading usage data...</translate></div>
     </div>
     <div :class="['ui', {'success': progress < 60}, {'yellow': progress >= 60 && progress < 96}, {'error': progress >= 95}, 'progress']">
-      <div class="bar">
+      <div class="bar" :style="{width: `${progress}%`}">
         <div class="progress">{{ progress }}%</div>
       </div>
       <div class="label" v-if="quotaStatus">
@@ -98,7 +98,6 @@
 </template>
 <script>
 import axios from 'axios'
-import $ from 'jquery'
 import {humanSize} from '@/filters'
 import {compileTokens} from '@/search'
 
@@ -145,12 +144,6 @@ export default {
     purgeErroredFiles () {
       this.purge('errored')
     },
-    updateProgressBar () {
-      $(this.$el).find('.ui.progress').progress({
-        percent: this.progress,
-        showActivity: false
-      })
-    }
   },
   computed: {
     progress () {
@@ -159,11 +152,6 @@ export default {
       }
       return Math.min(parseInt(this.quotaStatus.current * 100 / this.quotaStatus.max), 100)
     }
-  },
-  watch: {
-    progress () {
-      this.updateProgressBar()
-    }
   }
 }
 </script>