One of Funkwhale’s primary use-cases is content management. Users expect to be able to upload, manage, and share their content easily using the Funkwhale web app or other apps that use the Funkwhale API.
We have identified the following key focus areas:
Users need to be able to share content easily
Users need to be able to follow collections of content easily
Users should have the option to upload content without needing to organize it explicitly
Users need to be able to easily move content between different collections
Users need to be able to assign content to multiple collections
Users need to be able to see all of their content and how it is organized within apps
A collection is conceptually a container of content. Users can associate content with multiple collections and share collections with other users. When a user follows a collection, they have access to its content.
Collections resolve the following issues:
Users can organize their content exactly how they want to
Users can associate content to multiple collections or no collections at all
Users can share individual objects (tracks, albums, artists, playlists) using sharing links
Users can easily view all collections they have created and followed
This specification outlines the behaviors and workflows used in collections.
Collections enable users to group content they have uploaded. Users can create as many collections as they want and can share collections with other users. Users cannot add remote content to their own collections as this content may be revoked by other users and this would break the user experience.
The library is the container that holds all content a user has access to. This includes all content the user uploads and follows. The library can contain as many collections as the user wants to create or follow.
This diagram demonstrates how the user’s content library is organized on a conceptual level.
When a user uploads new content to Funkwhale, the uploaded file is associated to track, album, and artist metadata. The upload is associated to an automatically created upload collection that is invisible to the user. The user can select individual items or a list of items and assign them to one or more collections.
In addition to user collections, we propose the following automatic collections:
- Uploaded content
A collection containing all content the user uploads
- Followed content
A collection containing all content the user has followed in external collections
- Private content
A collection containing all content the user has not shared with anyone
- Public content
A collection containing all content the user has shared publicly
A collection containing all content the user has favorited
These collections are managed by Funkwhale and can’t be modified directly by the user. The user can use these collections get an overview of what content is local and what is being shared.
A collection is stored as a model in the database. This model contains the relevant identifying information for the collection, including:
The owning actor
The visibility level
Uploaded items can be linked to collections using a
Funkwhale-compatible apps can communicate with the Funkwhale API to retrieve and modify collection data. The following actions must be facilitated by API endpoints:
Create a new collection
Delete a collection
Modify a collection’s details (description, name, visibility level)
Add uploads to a collection
Remove uploads from a collection
List content contained in collections
In the frontend, the user has the ability to create, modify, and delete collections stored in their library. The user can assign content to collections during the upload process or by using the object’s context menu after upload.
When the user adds a containing object such as an artist discography, album, or playlist, all tracks currently associated with the object are added. The collection does not update if new content is associated to the object.
The content of each collection can be viewed in a Collection page. This page offers an overview of content in the collection, organized by content type (track, album, artist, playlist). This page can be used to highlight content such as recently favorited tracks or a variable random selection.
Users can see all of their collections in the User library page. This page clearly shows users all of their collections as well as information such whether the collections are shared or private.
In this section we detail the workflows behind some of the actions users are able to take using collections.
The user should be able to choose exactly where their content should go during the upload process. They should be able to choose to associate the upload with multiple collections or no collections. This process is outlined in the flowchart below:
Users must be able to delete content from their own library easily at any time. Deleting the uploaded content must remove it from any associated collections.
Creating a collection
The user should be able to create a collection in one of two ways:
By selecting a page that contains collections and selecting the “Add collection” option
By selecting the “Create new collection” from an object’s context menu
In each case, the user should be given a form to fill out with information including:
The collection name
The collection description
The collection’s visibility level
Deleting a collection
If a user decides to delete a collection it must not delete the content contained in the collection. When the user selects delete a warning must communicate the following:
The collection will no longer be available in the user library page or search results
Users with whom the collection is currently shared will lose access to the collection’s content
Adding content to a collection
Users should be able to select collections during the upload process to add the content immediately.
Users should also be able to select an object’s context menu and choose collections from the “Organize and share” submenu. Upon ticking the checkbox, an API call should fire to associate the upload(s) with the collection(s).
Removing content from a collection
Users should be able to remove content from collections by visiting the collection’s page, selecting the items, and selecting “Remove from collection”.
Users should also be able to select an object’s context menu and choose collections from the “Organize and share” submenu. Upon deselecting the checkbox, an API call should fire to break the association between the upload(s) and the collection(s).
Unsharing a collection
Users must be able to revoke sharing for collections. Once a collection is unshared, the content must not be accessible to past recipients.
The process for this changes based on the visibility level of the collection:
If the user wants to unshare a Public collection, they can change the visibility level to Private or Local
If the user wants to unshare a Local collection, they can change the visibility level to Private
If the user wants to unshare a Private collection, they must be able to select the recipient with whom they shared the collection and invalidate their sharing URL. When the user’s server receives this invalidation request, the content must be made unavailable to the user
When a user revokes collection access, the metadata entry for the content remains in the recipient’s library but is disabled. The UI should display a message informing the recipient that they no longer have access to the containing collection. The recipient can hide or remove the metadata entry by selecting “Forget” from the entry’s content menu.
Users must be able to follow remote content and collections so that the content appears in their library. This content must be clearly marked as external and should not contain the option to add to user collections.
Users must be able to unfollow collections by visiting the collection’s page and selecting “Unfollow”. The content in the collection should not be accessible to the user after they unfollow the collection.
Create new models and API endpoints to support collections
Formulate a migration path for existing libraries
Create a compatibility layer for calls between pods with collections and pods with libraries
Design group: Create designs for the different ares of the app in which collections are to be shown:
The collection page
The user library page
Sharing menus for content
Create UX copy for all designs (in collaboration with design group)
Document the behavior of collections for end users
Document the behavior of collections for admins
Document the structure of the data/API for developers
Create new collection page in line with designs
Create new user library page in line with designs
Update search results page to show collections
Add new context menus for collection management
Terminology: Does “following” a collection make sense? Would “add to library” be better?
Minimum viable product
On the backend, we must:
Create the new models for collections
Create endpoints to satisfy the requirements laid out in the feature behavior section
Create a migration path and demonstrate successful migration of libraries to collections
Create a translation layer between APIv1 library APIs and APIv2 collection APIs
On the frontend, we must:
Update the user profile page to show the user’s collections
Update the user’s library page to show the user’s collections
Create the new collection page with separate tabs for artists, albums, playlists, and tracks
Add collection management options to the upload form
Add collection management options to the object context menus
Mockups for these pages are available here
The MVP must allow users to perform the following actions:
Add or delete content from their library
Create and delete collections
Add content to and remove content from collections
Share and unshare collections
After the core mechanics are implemented, we can add the following to the frontend:
User library page: Automatic collections
Collection page: overview tab
Replace user favorites page with a browsable collection