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 + }; +}); + +