diff --git a/api/funkwhale_api/common/schema.yml b/api/funkwhale_api/common/schema.yml
index 38d2fc03c..f82be8df5 100644
--- a/api/funkwhale_api/common/schema.yml
+++ b/api/funkwhale_api/common/schema.yml
@@ -24846,6 +24846,9 @@ components:
type: string
format: uri
readOnly: true
+ library_followed:
+ type: boolean
+ readOnly: true
required:
- actor
- album_covers
@@ -24854,6 +24857,7 @@ components:
- fid
- is_playable
- library
+ - library_followed
- modification_date
- name
- tracks_count
diff --git a/api/funkwhale_api/playlists/serializers.py b/api/funkwhale_api/playlists/serializers.py
index db68ed3c5..f61e0ffad 100644
--- a/api/funkwhale_api/playlists/serializers.py
+++ b/api/funkwhale_api/playlists/serializers.py
@@ -35,6 +35,7 @@ class PlaylistSerializer(serializers.ModelSerializer):
is_playable = serializers.SerializerMethodField()
actor = APIActorSerializer(read_only=True)
library = serializers.SerializerMethodField()
+ library_followed = serializers.SerializerMethodField()
class Meta:
model = models.Playlist
@@ -53,6 +54,7 @@ class PlaylistSerializer(serializers.ModelSerializer):
"actor",
"description",
"library",
+ "library_followed",
)
read_only_fields = ["uuid", "fid", "modification_date", "creation_date"]
@@ -63,6 +65,15 @@ class PlaylistSerializer(serializers.ModelSerializer):
else:
return None
+ @extend_schema_field(OpenApiTypes.BOOL)
+ def get_library_followed(self, obj):
+ if lib_follow := obj.library.received_follows.filter(
+ actor=self.context["request"].user.actor
+ ):
+ return lib_follow.approved
+ else:
+ return None
+
@extend_schema_field(OpenApiTypes.BOOL)
def get_is_playable(self, obj):
return getattr(obj, "is_playable_by_actor", False)
diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue
index 936ba1215..47def808b 100644
--- a/front/src/components/audio/PlayButton.vue
+++ b/front/src/components/audio/PlayButton.vue
@@ -72,7 +72,8 @@ const {
enqueue,
enqueueNext,
replacePlay,
- isLoading
+ isLoading,
+ requestPlaylistUploadsAccess
} = usePlayOptions(props)
const { report, getReportableObjects } = useReport()
@@ -98,10 +99,50 @@ const labels = computed(() => ({
? t('components.audio.PlayButton.button.playArtist')
: props.playlist
? t('components.audio.PlayButton.button.playPlaylist')
- : t('components.audio.PlayButton.button.playTracks')
-}))
+ : t('components.audio.PlayButton.button.playTracks'),
+ PlaylistUploadAlreadyFollowed: t('components.audio.PlayButton.button.playPlaylist'),
+ PlaylistUploadPending:t('components.audio.PlayButton.button.PlaylistUploadPending'),
+ PlaylistUploadAccess: t('components.audio.PlayButton.button.PlaylistUploadAccess'),
+ PlaylistUploadTooltip: t('components.audio.PlayButton.button.PlaylistUploadTooltip')
+ }))
const isOpen = ref(false)
+
+const playlistFollowInfo = computed(() => {
+ const playlist = props.playlist;
+ if (!playlist) return null;
+
+ const followed = playlist.library_followed;
+
+ if (followed === true) {
+ return {
+ label: labels.value.PlaylistUploadAlreadyFollowed,
+ tooltip: labels.value.PlaylistUploadTooltip,
+ icon: 'bi-check-circle',
+ disabled: true
+ };
+ }
+
+ if (followed === false) {
+ return {
+ label: labels.value.PlaylistUploadPending,
+ tooltip: labels.value.PlaylistUploadTooltip,
+ icon: 'bi-hourglass-split',
+ disabled: true
+ };
+ }
+
+ // Assume null/undefined means not yet requested
+ return {
+ label: labels.value.PlaylistUploadAccess,
+ tooltip: labels.value.PlaylistUploadTooltip,
+ icon: 'bi-eye-slash',
+ disabled: false,
+ action: requestPlaylistUploadsAccess
+ };
+});
+
+
@@ -226,6 +267,15 @@ const isOpen = ref(false)
>
{{ obj.label }}
+
+ {{ playlistFollowInfo.label }}
+