Merge branch 'cherry-pick-develop' into 'master'
Cherry pick develop See merge request funkwhale/funkwhale!680
This commit is contained in:
commit
12113c6ef2
|
@ -2203,7 +2203,7 @@ On both docker and non-docker setup, you'll also have to update your nginx
|
|||
configuration for websocket support. Ensure you have the following blocks
|
||||
included in your virtualhost file:
|
||||
|
||||
.. code-block:: txt
|
||||
.. code-block:: text
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
|
|
330
CONTRIBUTING.rst
330
CONTRIBUTING.rst
|
@ -353,9 +353,339 @@ Internationalization
|
|||
--------------------
|
||||
|
||||
We're using https://github.com/Polyconseil/vue-gettext to manage i18n in the project.
|
||||
<<<<<<< HEAD
|
||||
When working on the front-end, any end-user string should be translated
|
||||
using either ``<translate>yourstring</translate>`` or ``$gettext('yourstring')``
|
||||
function.
|
||||
||||||| parent of 21fb39dd... Update docs/developers/index.rst, docs/developers/subsonic.rst files
|
||||
When working on the front-end, any end-user string should be marked as a translatable string,
|
||||
with the proper context, as described below.
|
||||
|
||||
Translations in HTML
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Translations in HTML use the ``<translate>`` tag::
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1><translate translate-context="Content/Profile/Header">User profile</translate></h1>
|
||||
<p>
|
||||
<translate
|
||||
translate-context="Content/Profile/Paragraph"
|
||||
:translate-params="{username: 'alice'}">
|
||||
You are logged in as %{ username }
|
||||
</translate>
|
||||
</p>
|
||||
<p>
|
||||
<translate
|
||||
translate-context="Content/Profile/Paragraph"
|
||||
translate-plural="You have %{ count } new messages, that's a lot!"
|
||||
:translate-n="unreadMessagesCount"
|
||||
:translate-params="{count: unreadMessagesCount}">
|
||||
You have 1 new message
|
||||
</translate>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Anything between the `<translate>` and `</translate>` delimiters will be considered as a translatable string.
|
||||
You can use variables in the translated string via the ``:translate-params="{var: 'value'}"`` directive, and reference them like this:
|
||||
``val value is %{ value }``.
|
||||
|
||||
For pluralization, you need to use ``translate-params`` in conjunction with ``translate-plural`` and ``translate-n``:
|
||||
|
||||
- ``translate-params`` should contain the variable you're using for pluralization (which is usually shown to the user)
|
||||
- ``translate-n`` should match the same variable
|
||||
- The ``<translate>`` delimiters contain the non-pluralized version of your string
|
||||
- The ``translate-plural`` directive contains the pluralized version of your string
|
||||
|
||||
|
||||
Translations in javascript
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Translations in javascript work by calling the ``this.$*gettext`` functions::
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
strings () {
|
||||
let tracksCount = 42
|
||||
let playButton = this.$pgettext('Sidebar/Player/Button/Verb, Short', 'Play')
|
||||
let loginMessage = this.$pgettext('*/Login/Message', 'Welcome back %{ username }')
|
||||
let addedMessage = this.$npgettext('*/Player/Message', 'One track was queued', '%{ count } tracks were queued', tracksCount)
|
||||
console.log(this.$gettextInterpolate(addedMessage, {count: tracksCount}))
|
||||
console.log(this.$gettextInterpolate(loginMessage, {username: 'alice'}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The first argument of the ``$pgettext`` and ``$npgettext`` functions is the string context.
|
||||
|
||||
Contextualization
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Translation contexts provided via the ``translate-context`` directive and the ``$pgettext`` and ``$npgettext`` are never shown to end users
|
||||
but visible by Funkwhale translators. They help translators where and how the strings are used,
|
||||
especially with short or ambiguous strings, like ``May``, which can refer a month or a verb.
|
||||
|
||||
While we could in theory use free form context, like ``This string is inside a button, in the main page, and is a call to action``,
|
||||
Funkwhale use a hierarchical structure to write contexts and keep them short and consistents accross the app. The previous context,
|
||||
rewritten correctly would be: ``Content/Home/Button/Call to action``.
|
||||
|
||||
This hierarchical structure is made of several parts:
|
||||
|
||||
- The location part, which is required and refers to the big blocks found in Funkwhale UI where the translated string is displayed:
|
||||
- ``Content``
|
||||
- ``Footer``
|
||||
- ``Head``
|
||||
- ``Menu``
|
||||
- ``Popup``
|
||||
- ``Sidebar``
|
||||
- ``*`` for strings that are not tied to a specific location
|
||||
|
||||
- The feature part, which is required, and refers to the feature associated with the translated string:
|
||||
- ``About``
|
||||
- ``Admin``
|
||||
- ``Album``
|
||||
- ``Artist``
|
||||
- ``Embed``
|
||||
- ``Home``
|
||||
- ``Login``
|
||||
- ``Library``
|
||||
- ``Moderation``
|
||||
- ``Player``
|
||||
- ``Playlist``
|
||||
- ``Profile``
|
||||
- ``Favorites``
|
||||
- ``Notifications``
|
||||
- ``Radio``
|
||||
- ``Search``
|
||||
- ``Settings``
|
||||
- ``Signup``
|
||||
- ``Track``
|
||||
- ``Queue``
|
||||
- ``*`` for strings that are not tied to a specific feature
|
||||
|
||||
- The component part, which is required and refers to the type of element that contain the string:
|
||||
- ``Button``
|
||||
- ``Card``
|
||||
- ``Checkbox``
|
||||
- ``Dropdown``
|
||||
- ``Error message``
|
||||
- ``Form``
|
||||
- ``Header``
|
||||
- ``Help text``
|
||||
- ``Hidden text``
|
||||
- ``Icon``
|
||||
- ``Input``
|
||||
- ``Image``
|
||||
- ``Label``
|
||||
- ``Link``
|
||||
- ``List item``
|
||||
- ``Menu``
|
||||
- ``Message``
|
||||
- ``Paragraph``
|
||||
- ``Placeholder``
|
||||
- ``Tab``
|
||||
- ``Table``
|
||||
- ``Title``
|
||||
- ``Tooltip``
|
||||
- ``*`` for strings that are not tied to a specific component
|
||||
|
||||
The detail part, which is optional and refers to the contents of the string itself, such as:
|
||||
- ``Adjective``
|
||||
- ``Call to action``
|
||||
- ``Noun``
|
||||
- ``Short``
|
||||
- ``Unit``
|
||||
- ``Verb``
|
||||
|
||||
Here are a few examples of valid context hierarchies:
|
||||
|
||||
- ``Sidebar/Player/Button``
|
||||
- ``Content/Home/Button/Call to action``
|
||||
- ``Footer/*/Help text``
|
||||
- ``*/*/*/Verb, Short``
|
||||
- ``Popup/Playlist/Button``
|
||||
- ``Content/Admin/Table.Label/Short, Noun (Value is a date)``
|
||||
|
||||
It's possible to nest multiple component parts to reach a higher level of detail. The component parts are then separated by a dot:
|
||||
|
||||
- ``Sidebar/Queue/Tab.Title``
|
||||
- ``Content/*/Button.Title``
|
||||
- ``Content/*/Table.Header``
|
||||
- ``Footer/*/List item.Link``
|
||||
- ``Content/*/Form.Help text``
|
||||
|
||||
Collecting translatable strings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you want to ensure your translatable strings are correctly marked for translation,
|
||||
you can try to extract them.
|
||||
|
||||
When working on the front-end, any end-user string should be marked as a translatable string,
|
||||
with the proper context, as described below.
|
||||
|
||||
Translations in HTML
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Translations in HTML use the ``<translate>`` tag::
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1><translate translate-context="Content/Profile/Header">User profile</translate></h1>
|
||||
<p>
|
||||
<translate
|
||||
translate-context="Content/Profile/Paragraph"
|
||||
:translate-params="{username: 'alice'}">
|
||||
You are logged in as %{ username }
|
||||
</translate>
|
||||
</p>
|
||||
<p>
|
||||
<translate
|
||||
translate-context="Content/Profile/Paragraph"
|
||||
translate-plural="You have %{ count } new messages, that's a lot!"
|
||||
:translate-n="unreadMessagesCount"
|
||||
:translate-params="{count: unreadMessagesCount}">
|
||||
You have 1 new message
|
||||
</translate>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Anything between the `<translate>` and `</translate>` delimiters will be considered as a translatable string.
|
||||
You can use variables in the translated string via the ``:translate-params="{var: 'value'}"`` directive, and reference them like this:
|
||||
``val value is %{ value }``.
|
||||
|
||||
For pluralization, you need to use ``translate-params`` in conjunction with ``translate-plural`` and ``translate-n``:
|
||||
|
||||
- ``translate-params`` should contain the variable you're using for pluralization (which is usually shown to the user)
|
||||
- ``translate-n`` should match the same variable
|
||||
- The ``<translate>`` delimiters contain the non-pluralized version of your string
|
||||
- The ``translate-plural`` directive contains the pluralized version of your string
|
||||
|
||||
|
||||
Translations in javascript
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Translations in javascript work by calling the ``this.$*gettext`` functions::
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
strings () {
|
||||
let tracksCount = 42
|
||||
let playButton = this.$pgettext('Sidebar/Player/Button/Verb, Short', 'Play')
|
||||
let loginMessage = this.$pgettext('*/Login/Message', 'Welcome back %{ username }')
|
||||
let addedMessage = this.$npgettext('*/Player/Message', 'One track was queued', '%{ count } tracks were queued', tracksCount)
|
||||
console.log(this.$gettextInterpolate(addedMessage, {count: tracksCount}))
|
||||
console.log(this.$gettextInterpolate(loginMessage, {username: 'alice'}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The first argument of the ``$pgettext`` and ``$npgettext`` functions is the string context.
|
||||
|
||||
Contextualization
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Translation contexts provided via the ``translate-context`` directive and the ``$pgettext`` and ``$npgettext`` are never shown to end users
|
||||
but visible by Funkwhale translators. They help translators where and how the strings are used,
|
||||
especially with short or ambiguous strings, like ``May``, which can refer a month or a verb.
|
||||
|
||||
While we could in theory use free form context, like ``This string is inside a button, in the main page, and is a call to action``,
|
||||
Funkwhale use a hierarchical structure to write contexts and keep them short and consistents accross the app. The previous context,
|
||||
rewritten correctly would be: ``Content/Home/Button/Call to action``.
|
||||
|
||||
This hierarchical structure is made of several parts:
|
||||
|
||||
- The location part, which is required and refers to the big blocks found in Funkwhale UI where the translated string is displayed:
|
||||
- ``Content``
|
||||
- ``Footer``
|
||||
- ``Head``
|
||||
- ``Menu``
|
||||
- ``Popup``
|
||||
- ``Sidebar``
|
||||
- ``*`` for strings that are not tied to a specific location
|
||||
|
||||
- The feature part, which is required, and refers to the feature associated with the translated string:
|
||||
- ``About``
|
||||
- ``Admin``
|
||||
- ``Album``
|
||||
- ``Artist``
|
||||
- ``Embed``
|
||||
- ``Home``
|
||||
- ``Login``
|
||||
- ``Library``
|
||||
- ``Moderation``
|
||||
- ``Player``
|
||||
- ``Playlist``
|
||||
- ``Profile``
|
||||
- ``Favorites``
|
||||
- ``Notifications``
|
||||
- ``Radio``
|
||||
- ``Search``
|
||||
- ``Settings``
|
||||
- ``Signup``
|
||||
- ``Track``
|
||||
- ``Queue``
|
||||
- ``*`` for strings that are not tied to a specific feature
|
||||
|
||||
- The component part, which is required and refers to the type of element that contain the string:
|
||||
- ``Button``
|
||||
- ``Card``
|
||||
- ``Checkbox``
|
||||
- ``Dropdown``
|
||||
- ``Error message``
|
||||
- ``Form``
|
||||
- ``Header``
|
||||
- ``Help text``
|
||||
- ``Hidden text``
|
||||
- ``Icon``
|
||||
- ``Input``
|
||||
- ``Image``
|
||||
- ``Label``
|
||||
- ``Link``
|
||||
- ``List item``
|
||||
- ``Menu``
|
||||
- ``Message``
|
||||
- ``Paragraph``
|
||||
- ``Placeholder``
|
||||
- ``Tab``
|
||||
- ``Table``
|
||||
- ``Title``
|
||||
- ``Tooltip``
|
||||
- ``*`` for strings that are not tied to a specific component
|
||||
|
||||
The detail part, which is optional and refers to the contents of the string itself, such as:
|
||||
- ``Adjective``
|
||||
- ``Call to action``
|
||||
- ``Noun``
|
||||
- ``Short``
|
||||
- ``Unit``
|
||||
- ``Verb``
|
||||
|
||||
Here are a few examples of valid context hierarchies:
|
||||
|
||||
- ``Sidebar/Player/Button``
|
||||
- ``Content/Home/Button/Call to action``
|
||||
- ``Footer/*/Help text``
|
||||
- ``*/*/*/Verb, Short``
|
||||
- ``Popup/Playlist/Button``
|
||||
- ``Content/Admin/Table.Label/Short, Noun (Value is a date)``
|
||||
|
||||
It's possible to nest multiple component parts to reach a higher level of detail. The component parts are then separated by a dot:
|
||||
|
||||
- ``Sidebar/Queue/Tab.Title``
|
||||
- ``Content/*/Button.Title``
|
||||
- ``Content/*/Table.Header``
|
||||
- ``Footer/*/List item.Link``
|
||||
- ``Content/*/Form.Help text``
|
||||
|
||||
Collecting translatable strings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you want to ensure your translatable strings are correctly marked for translation,
|
||||
you can try to extract them.
|
||||
>>>>>>> 21fb39dd... Update docs/developers/index.rst, docs/developers/subsonic.rst files
|
||||
|
||||
Extraction is done by calling ``yarn run i18n-extract``, which
|
||||
will pull all the strings from source files and put them in a PO file.
|
||||
|
|
|
@ -173,70 +173,77 @@ class Router:
|
|||
|
||||
|
||||
class InboxRouter(Router):
|
||||
def get_matching_handlers(self, payload):
|
||||
return [
|
||||
handler for route, handler in self.routes if match_route(route, payload)
|
||||
]
|
||||
|
||||
@transaction.atomic
|
||||
def dispatch(self, payload, context):
|
||||
def dispatch(self, payload, context, call_handlers=True):
|
||||
"""
|
||||
Receives an Activity payload and some context and trigger our
|
||||
business logic
|
||||
business logic.
|
||||
|
||||
call_handlers should be False when are delivering a local activity, because
|
||||
we want only want to bind activities to their recipients, not reapply the changes.
|
||||
"""
|
||||
from . import api_serializers
|
||||
from . import models
|
||||
|
||||
for route, handler in self.routes:
|
||||
if match_route(route, payload):
|
||||
handlers = self.get_matching_handlers(payload)
|
||||
for handler in handlers:
|
||||
if call_handlers:
|
||||
r = handler(payload, context=context)
|
||||
activity_obj = context.get("activity")
|
||||
if activity_obj and r:
|
||||
# handler returned additional data we can use
|
||||
# to update the activity target
|
||||
for key, value in r.items():
|
||||
setattr(activity_obj, key, value)
|
||||
else:
|
||||
r = None
|
||||
activity_obj = context.get("activity")
|
||||
if activity_obj and r:
|
||||
# handler returned additional data we can use
|
||||
# to update the activity target
|
||||
for key, value in r.items():
|
||||
setattr(activity_obj, key, value)
|
||||
|
||||
update_fields = []
|
||||
for k in r.keys():
|
||||
if k in ["object", "target", "related_object"]:
|
||||
update_fields += [
|
||||
"{}_id".format(k),
|
||||
"{}_content_type".format(k),
|
||||
]
|
||||
else:
|
||||
update_fields.append(k)
|
||||
activity_obj.save(update_fields=update_fields)
|
||||
update_fields = []
|
||||
for k in r.keys():
|
||||
if k in ["object", "target", "related_object"]:
|
||||
update_fields += [
|
||||
"{}_id".format(k),
|
||||
"{}_content_type".format(k),
|
||||
]
|
||||
else:
|
||||
update_fields.append(k)
|
||||
activity_obj.save(update_fields=update_fields)
|
||||
|
||||
if payload["type"] not in BROADCAST_TO_USER_ACTIVITIES:
|
||||
return
|
||||
|
||||
inbox_items = context.get(
|
||||
"inbox_items", models.InboxItem.objects.none()
|
||||
)
|
||||
inbox_items = (
|
||||
inbox_items.select_related()
|
||||
.select_related("actor__user")
|
||||
.prefetch_related(
|
||||
"activity__object",
|
||||
"activity__target",
|
||||
"activity__related_object",
|
||||
)
|
||||
)
|
||||
|
||||
for ii in inbox_items:
|
||||
user = ii.actor.get_user()
|
||||
if not user:
|
||||
continue
|
||||
group = "user.{}.inbox".format(user.pk)
|
||||
channels.group_send(
|
||||
group,
|
||||
{
|
||||
"type": "event.send",
|
||||
"text": "",
|
||||
"data": {
|
||||
"type": "inbox.item_added",
|
||||
"item": api_serializers.InboxItemSerializer(ii).data,
|
||||
},
|
||||
},
|
||||
)
|
||||
if payload["type"] not in BROADCAST_TO_USER_ACTIVITIES:
|
||||
return
|
||||
|
||||
inbox_items = context.get("inbox_items", models.InboxItem.objects.none())
|
||||
inbox_items = (
|
||||
inbox_items.select_related()
|
||||
.select_related("actor__user")
|
||||
.prefetch_related(
|
||||
"activity__object", "activity__target", "activity__related_object"
|
||||
)
|
||||
)
|
||||
|
||||
for ii in inbox_items:
|
||||
user = ii.actor.get_user()
|
||||
if not user:
|
||||
continue
|
||||
group = "user.{}.inbox".format(user.pk)
|
||||
channels.group_send(
|
||||
group,
|
||||
{
|
||||
"type": "event.send",
|
||||
"text": "",
|
||||
"data": {
|
||||
"type": "inbox.item_added",
|
||||
"item": api_serializers.InboxItemSerializer(ii).data,
|
||||
},
|
||||
},
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
ACTOR_KEY_ROTATION_LOCK_CACHE_KEY = "federation:actor-key-rotation-lock:{}"
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ def get_files(storage, *parts):
|
|||
|
||||
@celery.app.task(name="federation.dispatch_inbox")
|
||||
@celery.require_instance(models.Activity.objects.select_related(), "activity")
|
||||
def dispatch_inbox(activity):
|
||||
def dispatch_inbox(activity, call_handlers=True):
|
||||
"""
|
||||
Given an activity instance, triggers our internal delivery logic (follow
|
||||
creation, etc.)
|
||||
|
@ -84,6 +84,7 @@ def dispatch_inbox(activity):
|
|||
"actor": activity.actor,
|
||||
"inbox_items": activity.inbox_items.filter(is_read=False),
|
||||
},
|
||||
call_handlers=call_handlers,
|
||||
)
|
||||
|
||||
|
||||
|
@ -96,7 +97,7 @@ def dispatch_outbox(activity):
|
|||
inbox_items = activity.inbox_items.filter(is_read=False).select_related()
|
||||
|
||||
if inbox_items.exists():
|
||||
dispatch_inbox.delay(activity_id=activity.pk)
|
||||
dispatch_inbox.delay(activity_id=activity.pk, call_handlers=False)
|
||||
|
||||
if not preferences.get("federation__enabled"):
|
||||
# federation is disabled, we only deliver to local recipients
|
||||
|
|
|
@ -190,6 +190,16 @@ def test_inbox_routing(factories, mocker):
|
|||
assert a.target == target
|
||||
|
||||
|
||||
def test_inbox_routing_no_handler(factories, mocker):
|
||||
router = activity.InboxRouter()
|
||||
a = factories["federation.Activity"](type="Follow")
|
||||
handler = mocker.Mock()
|
||||
router.connect({"type": "Follow"}, handler)
|
||||
|
||||
router.dispatch({"type": "Follow"}, context={"activity": a}, call_handlers=False)
|
||||
handler.assert_not_called()
|
||||
|
||||
|
||||
def test_inbox_routing_send_to_channel(factories, mocker):
|
||||
group_send = mocker.patch("funkwhale_api.common.channels.group_send")
|
||||
a = factories["federation.Activity"](type="Follow")
|
||||
|
|
|
@ -74,10 +74,12 @@ def test_handle_in(factories, mocker, now, queryset_equal_list):
|
|||
a = factories["federation.Activity"](payload={"hello": "world"})
|
||||
ii1 = factories["federation.InboxItem"](activity=a, actor=r1)
|
||||
ii2 = factories["federation.InboxItem"](activity=a, actor=r2)
|
||||
tasks.dispatch_inbox(activity_id=a.pk)
|
||||
tasks.dispatch_inbox(activity_id=a.pk, call_handlers=False)
|
||||
|
||||
mocked_dispatch.assert_called_once_with(
|
||||
a.payload, context={"actor": a.actor, "activity": a, "inbox_items": [ii1, ii2]}
|
||||
a.payload,
|
||||
context={"actor": a.actor, "activity": a, "inbox_items": [ii1, ii2]},
|
||||
call_handlers=False,
|
||||
)
|
||||
|
||||
|
||||
|
@ -90,7 +92,7 @@ def test_dispatch_outbox(factories, mocker):
|
|||
factories["federation.InboxItem"](activity=activity)
|
||||
delivery = factories["federation.Delivery"](activity=activity)
|
||||
tasks.dispatch_outbox(activity_id=activity.pk)
|
||||
mocked_inbox.assert_called_once_with(activity_id=activity.pk)
|
||||
mocked_inbox.assert_called_once_with(activity_id=activity.pk, call_handlers=False)
|
||||
mocked_deliver_to_remote.assert_called_once_with(delivery_id=delivery.pk)
|
||||
|
||||
|
||||
|
@ -104,7 +106,7 @@ def test_dispatch_outbox_disabled_federation(factories, mocker, preferences):
|
|||
factories["federation.InboxItem"](activity=activity)
|
||||
factories["federation.Delivery"](activity=activity)
|
||||
tasks.dispatch_outbox(activity_id=activity.pk)
|
||||
mocked_inbox.assert_called_once_with(activity_id=activity.pk)
|
||||
mocked_inbox.assert_called_once_with(activity_id=activity.pk, call_handlers=False)
|
||||
mocked_deliver_to_remote.assert_not_called()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
i18n: Update page title when changing the App's language. (#511)
|
|
@ -0,0 +1 @@
|
|||
Ask for confirmation before leaving upload page if there is a an upload in process (#630)
|
|
@ -0,0 +1 @@
|
|||
Truncate filename in library file table to ensure correct display of the table. (#735)
|
|
@ -0,0 +1 @@
|
|||
Fixed delivering of local activities causing unintended side effects, such as rollbacking changes (#737)
|
|
@ -38,7 +38,7 @@ to help you understand the scale of the changes:
|
|||
+----------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
From a shared, instance-wide library to users libraries
|
||||
------------------------------------------------------
|
||||
-------------------------------------------------------
|
||||
|
||||
As you can see, there is a big switch: in earlier versions, each instance had one big library,
|
||||
that was available to all its users. This model don't scale well (especially if you put
|
|
@ -14,7 +14,7 @@ and technical aspects of your instance, such as database credentials.
|
|||
|
||||
.. note::
|
||||
|
||||
You should restart all funkwhale processes when you change the values
|
||||
You should restart all Funkwhale processes when you change the values
|
||||
on environment variables.
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ settings in this interface.
|
|||
.. note::
|
||||
|
||||
If you have any issue with the web application, a management interface is also
|
||||
available for those settings from Django's administration interface. It's
|
||||
available for those settings from :doc:`Django's administration interface <django>`. It's
|
||||
less user friendly, though, and we recommend you use the web app interface
|
||||
whenever possible.
|
||||
|
||||
|
@ -110,7 +110,7 @@ for this value. For non-docker installation, you can use any absolute path.
|
|||
|
||||
Default: :ref:`setting-MUSIC_DIRECTORY_PATH`
|
||||
|
||||
When using Docker, the value of :ref:`MUSIC_DIRECTORY_PATH` in your containers
|
||||
When using Docker, the value of :ref:`setting-MUSIC_DIRECTORY_PATH` in your containers
|
||||
may differ from the real path on your host. Assuming you have the following directive
|
||||
in your :file:`docker-compose.yml` file::
|
||||
|
||||
|
@ -156,7 +156,7 @@ permissions are:
|
|||
other instances, and accept/deny federation requests from other instances
|
||||
|
||||
There is no dedicated interface to manage users permissions, but superusers
|
||||
can login on the Django's admin at ``/api/admin/`` and grant permissions
|
||||
can login on the :doc:`Django's admin <django>` at ``/api/admin/`` and grant permissions
|
||||
to users at ``/api/admin/users/user/``.
|
||||
|
||||
Front-end settings
|
|
@ -0,0 +1,79 @@
|
|||
Using the Django Administration Backend
|
||||
=======================================
|
||||
|
||||
Funkwhale is being actively developed, and new features are being added to the frontend all the time. However, there are some administrative tasks that can only be undertaken in the Django Administration backend.
|
||||
|
||||
.. Warning::
|
||||
Deleting items on the backend is **not** recommended. Deletions performed on the backend are permanent. If you remove something in the backend, you will need to re-add it from scratch.
|
||||
|
||||
Accessing the Django Backend
|
||||
----------------------------
|
||||
|
||||
To access your instance's backend, navigate to ``https://yourdomain/api/admin``. You will be prompted to log in. By default, the login details will be those of the priviliged user created during the setup process.
|
||||
|
||||
Deleting Items
|
||||
-------------------
|
||||
|
||||
By default, deleting items in the front end removes the file from the server but **does not** delete associated entities such as artists, albums, and track data, meaning that they will still be viewable but no longer playable. Items deleted in this way will also still count on the instance statistics. To remove them completely, it is necessary to remove them from the database entirely using the Django Administration backend.
|
||||
|
||||
.. Warning::
|
||||
Deleting tracks, albums, or artists will also remove them completely from any associated playlists, radios, or favorites lists. Before continuing, make sure other users on the instance are aware of the deletion(s).
|
||||
|
||||
Deleting a Track
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
* Navigate to ``https://yourdomain/api/admin/music/track``
|
||||
* Select the track(s) you wish to delete
|
||||
* In the ``Action`` dropdown menu, select "Delete Selected Items"
|
||||
* Click on "Go". You will be prompted to confirm the track's deletion
|
||||
|
||||
Deleting an Album
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
* Navigate to ``https://yourdomain/api/admin/music/album``
|
||||
* Select the album(s) you wish to delete
|
||||
* In the ``Action`` dropdown menu, select "Delete Selected Items"
|
||||
* Click on "Go". You will be prompted to confirm the album's deletion
|
||||
|
||||
.. note::
|
||||
|
||||
Deleting an album will remove all tracks associated with the album
|
||||
|
||||
Deleting an Artist
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* Navigate to ``https://yourdomain/api/admin/music/artist``
|
||||
* Select the artist(s) you wish to delete
|
||||
* In the ``Action`` dropdown menu, select "Delete Selected Items"
|
||||
* Click on "Go". You will be prompted to confirm the artist's deletion
|
||||
|
||||
.. note::
|
||||
|
||||
Deleting an artist will remove all tracks and albums associated with the artist
|
||||
|
||||
Removing a Followed Library
|
||||
---------------------------
|
||||
|
||||
In Funkwhale, unfollowing a library will leave the items in place but inaccessible. To completely remove them:
|
||||
|
||||
* Navigate to ``https://yourdomain/api/admin/music/library/``
|
||||
* Tick the box next to the library you wish to remove
|
||||
* In the ``Action`` dropdown menu, select "Delete Selected Items"
|
||||
* Click on "Go". You will be prompted to confirm the library's deletion
|
||||
|
||||
Adding Missing Album Art
|
||||
-------------------------
|
||||
|
||||
Sometimes album art can fail to appear despite music being properly tagged. When this happens, it is possible to replace the missing art.
|
||||
|
||||
* Navigate to ``https://yourdomain/api/admin/music/album``
|
||||
* Search for and select the album in question
|
||||
* Find the item marked "Cover"
|
||||
* Click "Browse" and select the file from your computer
|
||||
* Click "Save" to confirm the changes
|
||||
|
||||
The album art will now be present on the frontend.
|
||||
|
||||
.. note::
|
||||
|
||||
You can also clear currently loaded album art by checking the checkbox next to the current item and selecting "Clear"
|
|
@ -151,4 +151,4 @@ From other instances
|
|||
--------------------
|
||||
|
||||
Funkwhale also supports importing music from other instances. Please refer
|
||||
to :doc:`federation` for more details.
|
||||
to :doc:`../federation/index` for more details.
|
|
@ -0,0 +1,34 @@
|
|||
Administrator Documentation
|
||||
=====================================
|
||||
|
||||
This documentation is targeted at administrators of instances. This typically refers to
|
||||
the person(s) responsible for running the server and managing the software on a technical
|
||||
level.
|
||||
|
||||
Setup Guides
|
||||
------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
../installation/index
|
||||
configuration
|
||||
importing-music
|
||||
|
||||
Administration
|
||||
--------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
django
|
||||
url
|
||||
upgrading
|
||||
|
||||
Troubleshooting Issues
|
||||
----------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
troubleshooting
|
|
@ -14,7 +14,7 @@ Diagnose problems
|
|||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Funkwhale is made of several components, each one being a potential cause for failure. Having an even basic overview
|
||||
of Funkwhale's technical architecture can help you understand what is going on. You can refer to :doc:`the technical architecture </architecture>` for that.
|
||||
of Funkwhale's technical architecture can help you understand what is going on. You can refer to :doc:`the technical architecture <../developers/architecture>` for that.
|
||||
|
||||
Problems usually fall into one of those categories:
|
||||
|
||||
|
@ -28,54 +28,6 @@ Each category comes with its own set of diagnose tools and/or commands we will d
|
|||
steps for each type of problem. Please try those to see if it fix your issues. If none of those works, please report your issue on our
|
||||
issue tracker.
|
||||
|
||||
Frontend issues
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Diagnostic tools:
|
||||
|
||||
- Javascript and network logs from your browser console (see instructions on how to open it in `Chrome <https://developers.google.com/web/tools/chrome-devtools/console/>`_ and `Firefox <https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console>`_
|
||||
- Proxy and API access and error logs (see :ref:`access-logs`)
|
||||
- The same operation works from a different browser
|
||||
|
||||
Common problems
|
||||
***************
|
||||
|
||||
The front-end is completely blank
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You are visiting Funkwhale, but you don't see anything.
|
||||
|
||||
- Try from a different browser
|
||||
- Check network errors in your browser console. If you see responses with 40X or 50X statuses, there is probably an issue with the webserver configuration
|
||||
- If you don't see anything wrong in the network console, check the Javascript console
|
||||
- Disable your browser extensions (like adblockers)
|
||||
|
||||
Music is not playing
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You have some tracks in your queue that don't play, or the queue is jumping from one track to the next until
|
||||
there is no more track available:
|
||||
|
||||
- Try with other tracks. If it works with some tracks but not other tracks, this may means that the failing tracks are not probably imported
|
||||
or that your browser does not support a specific audio format
|
||||
- Check the network and javascript console for potential errors
|
||||
|
||||
Tracks are not appending to the queue
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When clicking on "Play", "Play all albums" or "Play all" buttons, some tracks are not appended to the queue. This is
|
||||
actually a feature of Funkwhale: those tracks have no file associated with them, so we cannot play them.
|
||||
|
||||
Specific pages are loading forever or blank
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When viewing a given page, the page load never ends (you continue to see the spinner), or nothing seems to appear at all:
|
||||
|
||||
- Ensure your internet connection is up and running
|
||||
- Ensure your instance is up and running
|
||||
- Check the network and javascript console for potential errors
|
||||
|
||||
|
||||
Backend issues
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -207,6 +159,6 @@ similar issues before doing that, and use the issue tracker only to report bugs,
|
|||
Improving this documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you feel like something should be improved in this document (and in the documentation in general), feel free to `edit
|
||||
it <https://dev.funkwhale.audio/funkwhale/funkwhale/tree/develop/docs>`_ and open a Merge Request. If you lack time or skills
|
||||
to do that, you can open an issue to discuss that, and someone else will do it.
|
||||
If you feel like something should be improved in this document (and in the documentation in general), feel free to :doc:`contribute to the documentation <../documentation/creating>`.
|
||||
If you're not comfortable contributing or would like to ask somebody else to do it, feel free to :doc:`request a change in documentation <../documentation/identifying>`.
|
||||
|
|
@ -13,7 +13,7 @@ Upgrading your Funkwhale instance to a newer version
|
|||
Reading the release notes
|
||||
-------------------------
|
||||
|
||||
Please take a few minutes to read the :doc:`changelog`: updates should work
|
||||
Please take a few minutes to read the :doc:`../changelog`: updates should work
|
||||
similarly from version to version, but some of them may require additional steps.
|
||||
Those steps would be described in the version release notes.
|
||||
|
||||
|
@ -33,7 +33,7 @@ when possible.
|
|||
Docker setup
|
||||
------------
|
||||
|
||||
If you've followed the setup instructions in :doc:`Docker`, upgrade path is
|
||||
If you've followed the setup instructions in :doc:`../installation/docker`, upgrade path is
|
||||
easy:
|
||||
|
||||
Mono-container installation
|
|
@ -0,0 +1,93 @@
|
|||
Changing Your Instance URL
|
||||
==========================
|
||||
|
||||
At some point, you may wish to change your instance URL. In order to
|
||||
do this, you will need to change the following:
|
||||
|
||||
- The instance URL in your .env file
|
||||
- The instance URL in your ``/etc/nginx/sites-enabled/funkwhale.conf`` or ``/etc/apache2/sites-enabled/funkwhale.conf`` depending on your web server setup
|
||||
- Any references to the old URL in your database
|
||||
|
||||
The changes to the database can be achieved with the ``fix_federation_ids`` script in the ``manage.py``
|
||||
file.
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# For Docker setups
|
||||
docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
|
||||
|
||||
# For non-Docker setups
|
||||
python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
|
||||
|
||||
# Output
|
||||
Will replace 108 found occurences of 'https://old-url' by 'https://new-url':
|
||||
|
||||
- 20 music.Artist
|
||||
- 13 music.Album
|
||||
- 39 music.Track
|
||||
- 31 music.Upload
|
||||
- 1 music.Library
|
||||
- 4 federation.Actor
|
||||
- 0 federation.Activity
|
||||
- 0 federation.Follow
|
||||
- 0 federation.LibraryFollow
|
||||
|
||||
Replacing on 20 music.Artist…
|
||||
Replacing on 13 music.Album…
|
||||
Replacing on 39 music.Track…
|
||||
Replacing on 31 music.Upload…
|
||||
Replacing on 1 music.Library…
|
||||
Replacing on 4 federation.Actor…
|
||||
Replacing on 0 federation.Activity…
|
||||
Replacing on 0 federation.Follow…
|
||||
Replacing on 0 federation.LibraryFollow…
|
||||
|
||||
On Docker Installations
|
||||
-----------------------
|
||||
|
||||
If you have followed the :doc:`Docker installation instructions <../installation/docker>`, you
|
||||
will need to do the following:
|
||||
|
||||
- Edit your .env file to change the ``FUNKWHALE_HOSTNAME`` and ``DJANGO_ALLOWED_HOSTS`` value to your new URL
|
||||
- Edit your ``/etc/nginx/sites-enabled/funkwhale.conf`` file to change the ``server_name`` values to your new URL
|
||||
- Run the following command to change all mentions of your old instance URL in the database:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker-compose run --rm api python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
|
||||
|
||||
- Restart Nginx or Apache to pick up the new changes
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# For Nginx
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# For Apache
|
||||
sudo systemctl restart apache2
|
||||
|
||||
On Non-Docker Installations
|
||||
---------------------------
|
||||
|
||||
If you have followed the :doc:`non-docker setup <../installation/debian>`, you will need to do the following:
|
||||
|
||||
- Edit your .env file to change the ``FUNKWHALE_HOSTNAME`` and ``DJANGO_ALLOWED_HOSTS`` value to your new URL
|
||||
- Edit your ``/etc/nginx/sites-enabled/funkwhale.conf`` file to change the ``server_name`` values to your new URL
|
||||
- Run the following command to change all mentions of your old instance URL in the database:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python manage.py fix_federation_ids https://old-url https://new-url --no-dry-run --no-input
|
||||
|
||||
- Restart Nginx or Apache to pick up the new changes
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# For Nginx
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# For Apache
|
||||
sudo systemctl restart apache2
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
Backup your Funkwhale instance
|
||||
==============================
|
||||
|
||||
.. note::
|
||||
|
||||
Before upgrading your instance, we strongly advise you to make at least a database backup. Ideally, you should make a full backup, including the database and the media files.
|
||||
|
||||
|
||||
Docker setup
|
||||
------------
|
||||
|
||||
If you've followed the setup instructions in :doc:`../installation/docker`, here is the backup path:
|
||||
|
||||
Multi-container installation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Backup the db
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
On docker setups, you have to ``pg_dumpall`` in container ``funkwhale_postgres_1``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker exec -t funkwhale_postgres_1 pg_dumpall -c -U postgres > dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql
|
||||
|
||||
Backup the media files
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To backup docker data volumes, as the volumes are bound mounted to the host, the ``rsync`` way would go like this:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
rsync -avzhP /srv/funkwhale/data/media /path/to/your/backup/media
|
||||
rsync -avzhP /srv/funkwhale/data/music /path/to/your/backup/music
|
||||
|
||||
|
||||
Backup the configuration files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
On docker setups, the configuration file is located at the root level:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
rsync -avzhP /srv/funkwhale/.env /path/to/your/backup/.env
|
||||
|
||||
|
||||
Non-docker setup
|
||||
----------------
|
||||
|
||||
Backup the db
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
On non-docker setups, you have to ``pg_dump`` as user ``postgres``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u postgres -H pg_dump funkwhale > /path/to/your/backup/dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql
|
||||
|
||||
Backup the media files
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A simple way to backup your media files is to use ``rsync``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
rsync -avzhP /srv/funkwhale/data/media /path/to/your/backup/media
|
||||
rsync -avzhP /srv/funkwhale/data/music /path/to/your/backup/music
|
||||
|
||||
Backup the configuration files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
rsync -avzhP /srv/funkwhale/config/.env /path/to/your/backup/.env
|
||||
|
||||
.. note::
|
||||
You may also want to backup your proxy configuration file.
|
||||
|
||||
For frequent backups, you may want to use deduplication and compression to keep the backup size low. In this case, a tool like ``borg`` will be more appropriate.
|
52
docs/conf.py
52
docs/conf.py
|
@ -19,6 +19,8 @@
|
|||
#
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
from shutil import copyfile
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../api"))
|
||||
|
||||
|
@ -48,8 +50,9 @@ source_suffix = ".rst"
|
|||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
year = datetime.datetime.now().year
|
||||
project = "funkwhale"
|
||||
copyright = "2017, Eliot Berriot"
|
||||
copyright = "{}, Eliot Berriot".format(year)
|
||||
author = "Eliot Berriot"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
|
@ -81,7 +84,6 @@ pygments_style = "sphinx"
|
|||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
|
@ -100,7 +102,6 @@ html_theme = "alabaster"
|
|||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
|
@ -155,3 +156,48 @@ texinfo_documents = [
|
|||
"Miscellaneous",
|
||||
)
|
||||
]
|
||||
|
||||
# -- Build legacy redirect files -------------------------------------------
|
||||
|
||||
# Define list of redirect files to be build in the Sphinx build process
|
||||
|
||||
redirect_files = [
|
||||
|
||||
('importing-music.html', 'admin/importing-music.html'),
|
||||
('architecture.html', 'developer/architecture.html'),
|
||||
('troubleshooting.html', 'admin/troubleshooting.html'),
|
||||
('configuration.html', 'admin/configuration.html'),
|
||||
('upgrading/index.html', '../admin/upgrading.html'),
|
||||
('upgrading/0.17.html', '../admin/0.17.html'),
|
||||
('users/django.html', '../admin/django.html'),
|
||||
|
||||
]
|
||||
|
||||
# Generate redirect template
|
||||
|
||||
redirect_template = """\
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="1; url={new}" />
|
||||
<script>
|
||||
window.location.href = "{new}"
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
"""
|
||||
|
||||
# Tell Sphinx to copy the files
|
||||
|
||||
def copy_legacy_redirects(app, docname):
|
||||
if app.builder.name == 'html':
|
||||
for html_src_path, new in redirect_files:
|
||||
page = redirect_template.format(new=new)
|
||||
target_path = app.outdir + '/' + html_src_path
|
||||
if not os.path.exists(os.path.dirname(target_path)):
|
||||
os.makedirs(os.path.dirname(target_path))
|
||||
with open(target_path, 'w') as f:
|
||||
f.write(page)
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.connect('build-finished', copy_legacy_redirects)
|
||||
|
|
|
@ -50,7 +50,7 @@ or persist data.
|
|||
Third-party apps
|
||||
----------------
|
||||
|
||||
Since Funkwhale implements a subset of the Subsonic API, it's compatible with existing apps such
|
||||
Since Funkwhale implements a subset of the Subsonic API, it's compatible with existing :doc:`apps <../users/apps>` such
|
||||
as DSub, Ultrasonic or Clementine that support this API. Those apps can be used as a replacement
|
||||
or in conjunction of the web interface, but the underlying data is the same.
|
||||
|
|
@ -10,6 +10,7 @@ Reference
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
architecture
|
||||
../api
|
||||
../federation/index
|
||||
subsonic
|
||||
|
|
|
@ -57,7 +57,6 @@ in our payload, which you can use to adapt your client behaviour if needed:
|
|||
|
||||
{
|
||||
"subsonic-response": {
|
||||
...
|
||||
"type": "funkwhale",
|
||||
"funkwhaleVersion": "0.17"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
Adding New Documents
|
||||
====================
|
||||
|
||||
Writing Documents
|
||||
-----------------
|
||||
|
||||
Before you start writing documents:
|
||||
|
||||
- Make sure you have all the necessary information and :doc:`tools you need <tools>` to get started
|
||||
- Check the `current documents <https://docs.funkwhale.audio>`_ carefully to make sure you're not repeating something somebody has already said
|
||||
- Familiarize yourself with :doc:`reStructuredText <restructured>` and :doc:`the recommended document style <style>`
|
||||
|
||||
Once you're ready to get started, you can start :ref:`working with Gitlab <work-with-gitlab>`
|
||||
|
||||
.. _work-with-gitlab:
|
||||
|
||||
Working With Gitlab
|
||||
-------------------
|
||||
|
||||
Documents are managed in the Funkwhale `Gitlab <https://dev.funkwhale.audio>`_ repository along with the code.
|
||||
In order to add new documents, you will need to follow this process:
|
||||
|
||||
- :ref:`Sign up to Gitlab <sign-up>`
|
||||
- :ref:`Fork the project <fork-project>`
|
||||
- :ref:`Clone the Repository <clone-repo>`
|
||||
- :ref:`Add documents to your branch <add-docs>`
|
||||
- :ref:`Create a Merge Request <merge-request>`
|
||||
|
||||
.. _sign-up:
|
||||
|
||||
Signing up to Gitlab
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Before you can contribute documents to Funkwhale, you will need to set up an account on the
|
||||
project's `Gitlab <https://dev.funkwhale.audio>`_. To do this:
|
||||
|
||||
- Navigate to the https://dev.funkwhale.audio
|
||||
- Click on "register" to bring up the registration form
|
||||
- Fill in the relevant details, or alternatively sign up with Github if you already have an account
|
||||
- [Optional]: You can then `set up an SSH key <https://docs.gitlab.com/ee/ssh/>`_ to enable easy management of your :ref:`repository <clone-repo>`
|
||||
|
||||
.. _fork-project:
|
||||
|
||||
Fork the project
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Once you have set up an account, you can `fork the project <https://help.github.com/en/articles/fork-a-repo>`_
|
||||
to create a copy of the repository that you can make changes to.
|
||||
|
||||
- Navigate to the `Funkwhale repository <https://dev.funkwhale.audio/funkwhale/funkwhale>`_
|
||||
- Click "Fork" at the top of the repository
|
||||
- You will be redirected to a new version of the project. This one's all yours!
|
||||
|
||||
.. _clone-repo:
|
||||
|
||||
Clone the Repository
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once you have successfully forked the project, you can safely download a copy of this to your local
|
||||
computer to create documents.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# If you're using an SSH key
|
||||
|
||||
git clone git@dev.funkwhale.audio:your-username/funkwhale.git
|
||||
|
||||
# If you're using a username/password
|
||||
|
||||
git clone https://dev.funkwhale.audio/your-username/funkwhale.git
|
||||
|
||||
Once you've cloned the repository, it's a good idea to create a new branch for your documents so that
|
||||
you can :ref:`merge it later <merge-request>`
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# Create a new branch to make changes to
|
||||
|
||||
git checkout -b [name_of_your_new_branch]
|
||||
|
||||
# Push the branch up to your forked repository
|
||||
|
||||
git push origin [name_of_your_new_branch]
|
||||
|
||||
.. _add-docs:
|
||||
|
||||
Add Documents to Your Branch
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When you've got your repository all set up, you can start writing your documents. Remember to keep in mind
|
||||
:doc:`who you are writing for <style>` when you are writing, and :doc:`check your syntax works <restructured>`.
|
||||
|
||||
Once you've written what you need to write, you can push these changes to your forked repository:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# Add new documents to your commit
|
||||
|
||||
git add [list your documents here]
|
||||
|
||||
# Commit these to the branch
|
||||
|
||||
git commit -m "Add a commit message here!"
|
||||
|
||||
# Push the changes to your branch
|
||||
|
||||
git push origin [name_of_your_new_branch]
|
||||
|
||||
.. _merge-request:
|
||||
|
||||
Create a Merge Request
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Once you've pushed all of your documents, you can create a `Merge Request <https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html>`_
|
||||
to request the documents be merged into the official Funkwhale develop branch.
|
||||
|
||||
- Navigate to the `Funkwhale repository <https://dev.funkwhale.audio/funkwhale/funkwhale>`_
|
||||
- Click "Merge Requests" on the left hand side
|
||||
- Click on the "New Merge Request"
|
||||
- Under the "Source Branch" select your forked repository and the branch to which you've pushed changes
|
||||
- Under "Target Branch", select the "develop" branch
|
||||
- Click "Compare Branches and Continue"
|
||||
- In the form that comes up, provide a title/description of the changes you've made
|
||||
- Click "Submit Merge Request" to submit
|
||||
|
||||
That's it! If your merge request is successful, you will get a notification from one of the maintainers letting
|
||||
you know your changes have been accepted. Sometimes, you may need to make minor corrections. Don't worry! We'll
|
||||
let you know what needs correcting.
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
Identifying Gaps in Funkwhale Documentation
|
||||
===========================================
|
||||
|
||||
As Funkwhale and its community continue to grow and develop, more and more processes and features
|
||||
will need to be documented. As users find interesting new ways to interact with the software,
|
||||
provide novel solutions to existing issues, and find information they need missing, the documents
|
||||
will need to be updated and added to.
|
||||
|
||||
If you are trying to do something in Funkwhale and can't find any
|
||||
resources to help, you can help out by contributing in one of the following ways:
|
||||
|
||||
Providing Documentation
|
||||
-----------------------
|
||||
|
||||
If you've identified a gap or mistake in the documentation and feel comfortable writing up new
|
||||
guides/correcting existing ones, please feel free to do so. The best way to do this is by following
|
||||
the :doc:`document creation guide <creating>` to make sure your documents get processed as quickly
|
||||
as possible.
|
||||
|
||||
Requesting Documentation
|
||||
------------------------
|
||||
|
||||
If you're not comfortable with writing documents or don't feel like you can, you can help out
|
||||
by requesting a document be written. There are three ways to request new documents:
|
||||
|
||||
- Open a new issue on `Gitlab <https://dev.funkwhale.audio/funkwhale/funkwhale/issues>`_, providing as much detail as possible
|
||||
- Start a new thread on `the forum <https://socialhub.network/c/funkwhale>`_ with more details about your requests
|
||||
- Ask somebody on our `chat room <https://riot.im/app/#/room/#funkwhale:matrix.org>`_
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
Contribute to Funkwhale's Documentation
|
||||
=======================================
|
||||
|
||||
Funkwhale is constantly growing and changing, so good documentation is essential.
|
||||
If you find a gap or mistake in existing documents, or you want to create new documents
|
||||
to cover something that isn't covered yet, you can follow this procedure to contribute
|
||||
to Funkwhale's documentation store.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
identifying
|
||||
tools
|
||||
restructured
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
style
|
||||
creating
|
||||
rearrange
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
Rearranging Files
|
||||
=================
|
||||
|
||||
Sometimes, rearranging the layout of documents in the docs folder can help to make
|
||||
things a bit clearer for users. However, this can present the following issues:
|
||||
|
||||
- :ref:`Orphaned document links <orphaned-doc>`
|
||||
- :ref:`Orphaned URLs <orphaned-url>`
|
||||
|
||||
.. _orphaned-doc:
|
||||
|
||||
Orphaned Document Links
|
||||
-----------------------
|
||||
|
||||
Documents frequently reference other documents to avoid repeating information. If you
|
||||
move a document, you need to be sure to update any orphaned references.
|
||||
|
||||
Running ``make html`` in the ``docs`` directory (assuming you have :doc:`Sphinx installed <tools>`)
|
||||
will generate a series of warnings letting you know if any links are orphaned.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
funkwhale/docs/documentation/rearrange.rst:17: WARNING: unknown document: setup
|
||||
|
||||
You can then go to the file/line in question and update the link to its new location.
|
||||
|
||||
.. _orphaned-url:
|
||||
|
||||
Orphaned URLs
|
||||
-------------
|
||||
|
||||
Once internal document links have been resolved, it is important to consider that the
|
||||
moved file may have also been linked externally elsewhere before. In order to ensure
|
||||
that anybody trying to access the file is properly redirected to its new location, we
|
||||
need to make use of the link redirector in the ``conf.py`` file.
|
||||
|
||||
The link redirector takes two arguments: the old location of the file (passed as a .html
|
||||
file at the relative path ``docs``), and the new location it should redirect to. For example,
|
||||
if a document was moved from ``docs/index.html`` to ``docs/admin/index.html``, we would add
|
||||
the following to the ``redirect_files`` section of ``conf.py``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# -- Build legacy redirect files -------------------------------------------
|
||||
|
||||
# Define list of redirect files to be build in the Sphinx build process
|
||||
|
||||
redirect_files = [
|
||||
|
||||
('index.html', 'admin/index.html')
|
||||
]
|
||||
|
||||
If you are moving something from one folder to another, you would need to tell the redirect
|
||||
to move to the correct level. For example, if a file is moving from ``docs/admin/index.html``
|
||||
to ``docs/users/index.html``, you will need to add the following to the ``redirect_files``
|
||||
section of ``conf.py``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# -- Build legacy redirect files -------------------------------------------
|
||||
|
||||
# Define list of redirect files to be build in the Sphinx build process
|
||||
|
||||
redirect_files = [
|
||||
|
||||
('admin/index.html', '../users/index.html') #The '..' tells the script to go up a level
|
||||
]
|
||||
|
||||
The script will then take these two arguments and create a redirect file in the original
|
||||
location so that anybody accessing the existing URL will be redirected.
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
Writing reStructuredText
|
||||
========================
|
||||
|
||||
Funkwhale's documentation is written using a standard markup language called
|
||||
`reStructuredText <http://docutils.sourceforge.net/rst.html>`_. It is similar to Markdown
|
||||
and other web-based markup languages, but is better suited to technical documentation
|
||||
due to its standardized nature. A full syntax breakdown can be found `here <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html>`_,
|
||||
but the following should be enough to get you started on writing docs for Funkwhale.
|
||||
|
||||
Headings
|
||||
--------
|
||||
|
||||
Headings are useful for splitting up text into relevant subsections. With `Sphinx <http://www.sphinx-doc.org/>`_,
|
||||
major headers and direct subheaders are rendered as navigation links on Index pages, which
|
||||
makes them ideal for sharing specific information quickly.
|
||||
|
||||
Headers are written like so:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
Header 1 //Equivalent to <h1>
|
||||
========
|
||||
|
||||
Header 2 //Equivalent to <h2>
|
||||
--------
|
||||
|
||||
Header 3 //Equivalent to <h3>
|
||||
^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Underlines should be **at least** as long as the words they underline
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
Links can be rendered in several different ways depending on where they link to:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
`external link <https://example-url/>`_
|
||||
|
||||
:doc:`link to document <../relative/doc/path>`
|
||||
|
||||
Inline references can also be generated using the following syntax:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
:ref:`This links to the text <link-ref>`
|
||||
|
||||
.. _link-ref:
|
||||
|
||||
The text you want to jump to
|
||||
|
||||
Lists
|
||||
-----
|
||||
|
||||
Bullet point lists are usually written using dashes like so:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Item 3
|
||||
|
||||
Blocks
|
||||
------
|
||||
|
||||
Blocks can be used to easily and concisely present information to a reader and are
|
||||
particularly useful when demonstrating technical steps. Blocks in reStructuredText can
|
||||
be written as follows:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
write terminal commands here
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
write Python code here
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
write text here
|
||||
|
||||
Other syntax highlighting is available. See the spec for full details.
|
||||
|
||||
.. note::
|
||||
|
||||
Content within code blocks should be indented by three spaces. You can end the code block by
|
||||
removing the indent.
|
||||
|
||||
Notes and Warnings
|
||||
------------------
|
||||
|
||||
Notes are great for presenting important information to users and providing additional context.
|
||||
Warnings can be very useful if a step you're writing about could potentially have adverse consequences.
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. note::
|
||||
|
||||
Your note goes here
|
||||
|
||||
.. warning::
|
||||
|
||||
Your warning goes here!
|
||||
|
||||
.. note::
|
||||
|
||||
Content within notes and warnings should be indented by three spaces. You can end the block by
|
||||
removing the indent.
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
Documentation Style Guide
|
||||
=========================
|
||||
|
||||
End-user Documentation
|
||||
----------------------
|
||||
|
||||
End-user documentation is often the most difficult to write as it requires striking the right balance
|
||||
between technical and non-technical instruction. Typically, writing a document should start
|
||||
with you asking yourself the following question:
|
||||
|
||||
Why is the user reading this document?
|
||||
|
||||
The answer will usually be one of the following:
|
||||
|
||||
- They are new to the project and are looking to learn more about it
|
||||
- They are trying to do something and are having difficulty
|
||||
|
||||
Documentation should be written with these two answers in mind. Information should be
|
||||
clearly laid out in small sections with plenty of clear examples and precise instructions.
|
||||
You should also try to pre-empt where the user might need to go next in order to ease their
|
||||
journey through the document by providing logical and relevant links to more documents.
|
||||
|
||||
Administrator Documentation
|
||||
---------------------------
|
||||
|
||||
Funkwhale is quite a technical project and is enjoyed by people who like setting up their own
|
||||
systems. These users can range from experienced server administrators to hobbyists, so administrator
|
||||
documentation should include plenty of technical instructions with an easy-to-read explanation of each
|
||||
step to cover both use-cases.
|
||||
|
||||
Developer Documentation
|
||||
-----------------------
|
||||
|
||||
Developer documentation should aim to be as technical and readable as possible. Since
|
||||
the reader is likely a developer themselves, providing as much technical detail as possible
|
||||
is the best course of action as it allows them to dive in to the project's internals with
|
||||
more confidence. It is safe to assume they are used to reading more technical work.
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
Documentation Requirements
|
||||
==========================
|
||||
|
||||
Funkwhale's documentation is written using :doc:`reStructuredText <restructured>` and is built using
|
||||
`Sphinx <http://www.sphinx-doc.org/>`_.
|
||||
|
||||
Text Editor
|
||||
-----------
|
||||
|
||||
As reStructuredText is a writing standard, any text editor can be used to modify documents depending on preference.
|
||||
User-friendly programs such as `Retext <https://github.com/retext-project/retext>`_ are good options for
|
||||
those just getting started with writing reStructuredText. Many other editors such as `Vim <https://www.vim.org/>`_,
|
||||
`Emacs <https://www.gnu.org/software/emacs/>`_, `VS Code <https://code.visualstudio.com/>`_, and
|
||||
`Atom <https://atom.io/>`_ have addons which can help with syntax highlighting and live previewing.
|
||||
|
||||
Sphinx
|
||||
------
|
||||
|
||||
Sphinx is used to generate a static site based on the ``.rst`` files in the ``docs`` directory. When writing
|
||||
documents, it can be useful to build the site to see how your changes will look in production. To do this:
|
||||
|
||||
- Install Sphinx using `pip <https://pypi.org/project/pip/>`_
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
pip install sphinx
|
||||
|
||||
- Navigate to your local ``funkwhale/docs`` directory
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cd funkwhale/docs
|
||||
|
||||
- Use the make file to build the site
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make html
|
||||
|
||||
- Sphinx will generate the site in your ``funkwhale/docs/_build`` directory unless otherwise stated
|
||||
|
||||
Once you have generated a local copy of the site, you can open it up by opening the index.html file in
|
||||
``funkwhale/docs/_build``.
|
||||
|
||||
.. note::
|
||||
|
||||
If you are familiar with `Docker <https://www.docker.com/>`_ and `docker-compose <https://docs.docker.com/compose/>`_,
|
||||
you can also hack on the documentation via a single command: ``docker-compose -f dev.yml up docs``.
|
||||
|
||||
This will make the documentation available at http://0.0.0.0:8001, with live-reloading enabled, so any change made in the
|
||||
``.rst`` files will be reflected immediately in your browser.
|
||||
|
||||
|
||||
Git
|
||||
---
|
||||
|
||||
In order to work on files on your computer, you will need to install `git <https://git-scm.com/>`_ for your
|
||||
operating system. Git is used to push and pull files to and from the Funkwhale repository and track changes
|
||||
made to documents/code alike.
|
||||
|
||||
Gitlab
|
||||
------
|
||||
|
||||
If you are only making minor changes to a document or don't wish to install anything, you can use
|
||||
`Gitlab's <https://dev.funkwhale.audio>`_ built-in IDE. Once you have made an account and :doc:`created
|
||||
a pull request <creating>`, you can click on the "Open in Web IDE" button to open up a fully-fledged
|
||||
editor in your web browser.
|
||||
|
|
@ -24,7 +24,7 @@ Funkwhale is not bundled with any music, and you'll have to import your own musi
|
|||
|
||||
At the moment, you can feed your existing music library to the server either by uploading it or by using :ref:`in-place-import` from a server-side directory. Assuming the files have the correct tags defined, they will be imported seamlessly.
|
||||
|
||||
You can also access music being made available by other Funkwhale instances using :doc:`federation`.
|
||||
You can also access music being made available by other Funkwhale instances using :doc:`/federation/index`.
|
||||
|
||||
Metadata
|
||||
---------
|
||||
|
|
|
@ -317,7 +317,7 @@ Supported on
|
|||
- :ref:`object-Library` objects
|
||||
|
||||
Example (on :ref:`object-Library`)
|
||||
************************
|
||||
**********************************
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
|
@ -339,7 +339,7 @@ Example (on :ref:`object-Library`)
|
|||
}
|
||||
|
||||
Example (on :ref:`object-audio`)
|
||||
**********************
|
||||
********************************
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
|
|
|
@ -11,16 +11,13 @@ Funkwhale is a self-hosted, modern free and open-source music server, heavily in
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
users/index
|
||||
features
|
||||
architecture
|
||||
installation/index
|
||||
upgrading/index
|
||||
configuration
|
||||
troubleshooting
|
||||
importing-music
|
||||
users/index
|
||||
moderator/index
|
||||
admin/index
|
||||
developers/index
|
||||
third-party
|
||||
documentation/index
|
||||
contributing
|
||||
translators
|
||||
changelog
|
||||
|
|
|
@ -207,6 +207,7 @@ You can then edit the file: the file is heavily commented, and the most relevant
|
|||
configuration options are mentioned at the top of the file.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
nano /srv/funkwhale/api/.env
|
||||
|
||||
Paste the secret key you generated earlier at the entry
|
||||
|
|
|
@ -196,4 +196,4 @@ Now, you just need to configure your :ref:`reverse-proxy <reverse-proxy-setup>`.
|
|||
About music acquisition
|
||||
-----------------------
|
||||
|
||||
If you want to :doc:`import music located on the server </importing-music>`, you can put it in the ``data/music`` directory and it will become readable by the importer.
|
||||
If you want to :doc:`import music located on the server <../admin/importing-music>`, you can put it in the ``data/music`` directory and it will become readable by the importer.
|
||||
|
|
|
@ -93,6 +93,6 @@ On Arch Linux and its derivatives:
|
|||
This should be enough to have your redis server set up.
|
||||
|
||||
External Authentication (LDAP)
|
||||
----------------------
|
||||
------------------------------
|
||||
|
||||
LDAP support requires some additional dependencies to enable. On the OS level both ``libldap2-dev`` and ``libsasl2-dev`` are required, and the Python modules ``python-ldap`` and ``python-django-auth-ldap`` must be installed. These dependencies are all included in the ``requirements.*`` files so deploying with those will install these dependencies by default. However, they are not required unless LDAP support is explicitly enabled. See :doc:`./ldap` for more details.
|
||||
|
|
|
@ -204,6 +204,7 @@ On non-docker deployments, run the following commands:
|
|||
Finally, enable the resulting configuration:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ln -s /etc/nginx/sites-available/funkwhale.conf /etc/nginx/sites-enabled/
|
||||
|
||||
.. warning::
|
||||
|
@ -212,8 +213,8 @@ Finally, enable the resulting configuration:
|
|||
in the ``_protected/music`` location matches your MUSIC_DIRECTORY_SERVE_PATH
|
||||
env var.
|
||||
|
||||
HTTS Configuration
|
||||
::::::::::::::::::
|
||||
HTTPS Configuration
|
||||
:::::::::::::::::::
|
||||
|
||||
At this point you will need a SSL certificate to enable HTTPS on your server.
|
||||
The default nginx configuration assumes you have those available at ``/etc/letsencrypt/live/${FUNKWHALE_HOSTNAME}/``, which
|
||||
|
@ -274,7 +275,7 @@ Check the configuration is valid with ``apache2ctl configtest``, and once you're
|
|||
done, load the new configuration with ``service apache2 restart``.
|
||||
|
||||
About internal locations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Music (and other static) files are never served by the app itself, but by the reverse
|
||||
proxy. This is needed because a webserver is way more efficient at serving
|
||||
|
|
|
@ -42,7 +42,7 @@ guide.
|
|||
|
||||
|
||||
Building the mono-container Docker image (funkwhale/funkwhale)
|
||||
-------------------------------------------------------------
|
||||
--------------------------------------------------------------
|
||||
|
||||
This image is intended to be used in conjunction with our :ref:`Mono-container installation guide <docker-mono-container>`.
|
||||
guide.
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
Moderating Domains
|
||||
==================
|
||||
|
||||
Moderation rules can be used to control how your instance interacts with other domains.
|
||||
They can be useful for keeping unwanted material and users out of your instance.
|
||||
|
||||
Managing Domains
|
||||
----------------
|
||||
|
||||
Add a Domain
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Adding a domain allows you to create rules pre-emptively and proactively moderate content on your
|
||||
instance. Domains with which users have already interacted will appear in the domains list.
|
||||
|
||||
To add a new domain:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Domains" along the top
|
||||
- In the top right, enter the URL of the domain you want to federate with in the "Add a domain" box and click "Add"
|
||||
- You will then be taken to an overview page showing details about the instance
|
||||
|
||||
Purge Domain Data
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
|
||||
Purging domain data will remove all tracks, libraries, and caches associated with
|
||||
the domain. This can have severe knock-on effects for users who have any of these
|
||||
in their favorites, playlists, or followed libraries. Be careful when performing
|
||||
this action.
|
||||
|
||||
Purging data from a domain can be useful if a domain is uploading offensive or illegal
|
||||
media you do not want served on your instance.
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Domains" along the top
|
||||
- Find the domain whose data you wish to purge and select the checkbox next to it
|
||||
- Select "Purge" from the "Actions" drop-down menu and click on "Go"
|
||||
- A pop up will appear warning you of the consequences. If you want to continue with the purge, click "Launch"
|
||||
|
||||
Moderation Rules
|
||||
----------------
|
||||
|
||||
Add a Moderation Rule to a Domain
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Moderation rules can be useful for managing interaction with domains.
|
||||
|
||||
To add a moderation rule:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Domains" along the top
|
||||
- Find the domain you wish to add a rule to and click on it
|
||||
- In the top right, select "Add a moderation policy"
|
||||
- Give a reason for your rule creation in the "Reason" box. This can help other moderators understand the action
|
||||
- To block all interaction with the domain **and purge all content**, select "Block Everything"
|
||||
- To only block media elements such as audio, avatars, and album art, select "Reject Media"
|
||||
- When you have finished creating your rule, click "Create" to save the rule
|
||||
|
||||
Edit a Moderation Rule
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sometimes a previously created moderation rule needs to be updated to lessen or increase
|
||||
its severity.
|
||||
|
||||
To update an existing moderation rule:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Domains" along the top
|
||||
- Find the domain whose rule you wish to edit and click on it
|
||||
- In the top right, select "Update" under your existing rule
|
||||
- Update the reason for your rule creation in the "Reason" box. This can help other moderators understand the action
|
||||
- To block all interaction with the domain **and purge all content**, select "Block Everything"
|
||||
- To only block media elements such as audio, avatars, and album art, select "Reject Media"
|
||||
- When you have finished editing your rule, click "Create" to save the rule
|
||||
|
||||
Remove a Moderation Rule From a Domain
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If a domain is no longer subject to moderation, you can remove existing rules to enable
|
||||
full federation with the instance again.
|
||||
|
||||
To remove a moderation rule from a domain:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Domains" along the top
|
||||
- Find the domain you wish to remove a rule from and click on it
|
||||
- In the top right, select "Update" under your existing rule
|
||||
- Click on "Delete"
|
||||
- A pop up will appear warning that the action is irreversible. If you want to continue, select "Delete moderation rule"
|
|
@ -0,0 +1,14 @@
|
|||
Moderator Documentation
|
||||
=========================
|
||||
|
||||
This documentation is targeted at instance moderators. Moderators have enhanced permissions
|
||||
which allow them to moderate federated accounts and domains.
|
||||
|
||||
Moderation Guides
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
domains
|
||||
users
|
|
@ -0,0 +1,82 @@
|
|||
Moderating Users
|
||||
==================
|
||||
|
||||
Moderation rules can be used to control how your instance interacts with accounts on other domains.
|
||||
They can be useful for keeping unwanted material and users out of your instance.
|
||||
|
||||
Managing Accounts
|
||||
-----------------
|
||||
|
||||
Purge Account Data
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. warning::
|
||||
|
||||
Purging account data will remove all tracks, libraries, and caches associated with
|
||||
the account. This can have severe knock-on effects for users who have any of these
|
||||
in their favorites, playlists, or followed libraries. Be careful when performing
|
||||
this action.
|
||||
|
||||
Purging data from an account can be useful if the account is uploading offensive or illegal
|
||||
media you do not want served on your instance.
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Accounts" along the top
|
||||
- Find the account whose data you wish to purge and select the checkbox next to it
|
||||
- Select "Purge" from the "Actions" drop-down menu and click on "Go"
|
||||
- A pop up will appear warning you of the consequences. If you want to continue with the purge, click "Launch"
|
||||
|
||||
Moderation Rules
|
||||
----------------
|
||||
|
||||
Add a Moderation Rule to an Account
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Moderation rules only apply to accounts on other instances
|
||||
|
||||
Moderation rules can be useful for managing interaction with Accounts.
|
||||
|
||||
To add a moderation rule:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Accounts" along the top
|
||||
- Find the Account you wish to add a rule to and click on it
|
||||
- In the top right, select "Add a moderation policy"
|
||||
- Give a reason for your rule creation in the "Reason" box. This can help other moderators understand the action
|
||||
- To block all interaction with the account **and purge all content**, select "Block Everything"
|
||||
- To only block media elements such as audio, avatars, and album art, select "Reject Media"
|
||||
- When you have finished creating your rule, click "Create" to save the rule
|
||||
|
||||
Edit a Moderation Rule
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Sometimes a previously created moderation rule needs to be updated to lessen or increase
|
||||
its severity.
|
||||
|
||||
To update an existing moderation rule:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Accounts" along the top
|
||||
- Find the account whose rule you wish to edit
|
||||
- In the top right, select "Update" under your existing rule
|
||||
- Update the reason for your rule creation in the "Reason" box. This can help other moderators understand the action
|
||||
- To block all interaction with the account **and purge all content**, select "Block Everything"
|
||||
- To only block media elements such as audio, avatars, and album art, select "Reject Media"
|
||||
- When you have finished editing your rule, click "Create" to save the rule
|
||||
|
||||
Remove a Moderation Rule From an Account
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If an account is no longer subject to moderation, you can remove existing rules to enable
|
||||
full federation with the instance again.
|
||||
|
||||
To remove a moderation rule from an Account:
|
||||
|
||||
- Navigate to the "Moderation" menu under "Administration"
|
||||
- Select "Accounts" along the top
|
||||
- Find the account you wish to remove a rule from and click on it
|
||||
- In the top right, select "Update" under your existing rule
|
||||
- Click on "Delete"
|
||||
- A pop up will appear warning that the action is irreversible. If you want to continue, select "Delete moderation rule"
|
|
@ -49,6 +49,12 @@ Those features as missing:
|
|||
Enabling Subsonic on your Funkwhale account
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Accessing Funkwhale from third party apps requires the instance administrator
|
||||
to enable the Subsonic API setting. If you are unable to use Subsonic, please
|
||||
contact your administrator.
|
||||
|
||||
To log-in on your Funkwhale account from Subsonic clients, you will need to
|
||||
set a separate Subsonic API password by visiting your settings page.
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
Creating a Funkwhale Account
|
||||
============================
|
||||
|
||||
Before you can start using Funkwhale, you will need to set up an account on an instance. While
|
||||
some instances allow you to listen to public music anonymously, you will need to create account
|
||||
to benefit from the full Funkwhale experience.
|
||||
|
||||
A list of instances along with other useful information such as version and enabled features can be found
|
||||
`here <https://network.funkwhale.audio/dashboards/d/overview/network-overview>`_. Servers marked with
|
||||
"Open registrations" are available to sign up to.
|
||||
|
||||
Signing up to an Instance
|
||||
-------------------------
|
||||
|
||||
Once you have chosen the instance you would like to sign up to, creating an account is easy.
|
||||
|
||||
1. Click on the "Create an account" option on the left-hand side
|
||||
2. Enter your preferred username, email address, and password
|
||||
3. [Optional] enter an Invitation code if you received an invite from an existing user
|
||||
4. Click on "Create my Account"
|
||||
5. Once you have created your account, you will be required to log in.
|
||||
|
||||
Now that you've created your account, you can go ahead and :doc:`start uploading content to your library <upload>`.
|
|
@ -0,0 +1,41 @@
|
|||
Managing Favorites
|
||||
==================
|
||||
|
||||
Like any media player, Funkwhale allows you to favorite tracks to keep tabs on
|
||||
the tracks you've enjoyed
|
||||
|
||||
Adding Favorites
|
||||
----------------
|
||||
|
||||
From a Library
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
To add a track to your favorites from your library:
|
||||
|
||||
- Search for the song or navigate to its album page
|
||||
- Click on the gray heart icon next to the track
|
||||
- Once the gray heart has turned pink, the song will be in your favorites list
|
||||
|
||||
From Currently Playing
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add the currently playing track to your favorites
|
||||
|
||||
- Click on the white heart icon underneath the track title in the player window
|
||||
- Once the white heart has turned pink, the song will be in your favorites list
|
||||
|
||||
Removing Favorites
|
||||
------------------
|
||||
|
||||
If you no longer want a track to appear in your favorites list:
|
||||
|
||||
- Search for the song or navigate to its album page
|
||||
- Click on the pink heart icon next to the song
|
||||
- Once clicked, the heart will disappear and the track will no longer be in your favorites
|
||||
|
||||
Viewing Favorites
|
||||
-----------------
|
||||
|
||||
Once you've favorited some tracks, you can view them any time by clicking on
|
||||
"Favorites" under the "Music" menu on the left-hand side. From here you'll be
|
||||
able to :doc:`add your favorite tracks to playlists <playlists>` or :doc:`start a radio of your favorite tracks <radios>`.
|
|
@ -0,0 +1,60 @@
|
|||
Following Libraries
|
||||
====================
|
||||
|
||||
Funkwhale's major strength is its focus on federated sharing of music. Users can share
|
||||
music with one another through the network using library links.
|
||||
|
||||
Library Permissions
|
||||
-------------------
|
||||
|
||||
Libraries are set up with specific permissions that determine their visibility to users on the local instance
|
||||
and wider federated network. These permissions also determine whether or not follow requests need to be accepted
|
||||
by the library owner. These permissions are as follows:
|
||||
|
||||
- **Everyone, across all instances** - the library will automatically accept follows from all users
|
||||
- **Everyone on this instance** - the library will automatically accept follows from users on the same instance, but external users will need to be accepted by the library owner
|
||||
- **Nobody Except Me** - all follows will need to be approved by the library owner
|
||||
|
||||
Getting Library Links
|
||||
---------------------
|
||||
|
||||
The first step to following a library is getting a valid library link. These links typically look like
|
||||
``https://instance-url/federation/music/libraries/a-random-string-of-numbers-and-letters``. Users can
|
||||
share their library links with you directly, or you can find the library links for public libraries by
|
||||
visiting their instance. To do this:
|
||||
|
||||
- Visit the instance containing the library you wish to follow
|
||||
- Select an item contained within the library
|
||||
- Scroll down to the "User libraries" section. You should see the name of the library in question
|
||||
- The library link will be under "Sharing link". Click on "Copy" to copy the link to your clipboard
|
||||
|
||||
Following Other Libraries
|
||||
--------------------------
|
||||
|
||||
Once you've got the library link, you can start following the library by doing the following:
|
||||
|
||||
- Click on the "Add content" menu under "Music" on the left-hand side
|
||||
- Under "Follow Remote Libraries", select "Get Started"
|
||||
- In the search bar that appears, paste the library link of the library you wish to follow
|
||||
- If the URL is valid, the name of the library will appear. Click "Follow" to start following the library
|
||||
- Once your follow request is approved, the library will be scanned for content (this will be automatic for public libraries)
|
||||
- Click on "Browse library" under "Music" on the left-hand side to return to the library overview
|
||||
- The library content should now be visible and playable on your instance
|
||||
|
||||
If another user on your instance has followed a library, you can follow it as well in case the user
|
||||
leaves or stops following it. To do this:
|
||||
|
||||
- Select an item contained within the library on your instance
|
||||
- Scroll down to the "User libraries" section. You should see the name of the library in question
|
||||
- Click on "Follow"
|
||||
|
||||
Sharing Your Libraries
|
||||
----------------------
|
||||
|
||||
As well as being able to follow other users, you can also share your libraries with friends, family, and
|
||||
the network at large. To find your library link:
|
||||
|
||||
- Navigate to ``https://your-instance/content/libraries`` or click "Add Content" under the "Music" menu, select "Upload audio content", and click "Detail" under the library you want the code for
|
||||
- Under the "Followers" tab, you will be able to see information about followers this library currently has. The sharing link will also be visible
|
||||
- Click on "Copy" to copy the sharing link to your clipboard
|
||||
- Depending on the visibility settings you have chosen for the library, you will need to approve follow requests for those with whom you share the link
|
|
@ -1,17 +1,38 @@
|
|||
.. funkwhale documentation master file, created by
|
||||
sphinx-quickstart on Sun Jun 25 18:49:23 2017.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Funkwhale's users documentation
|
||||
User Documentation
|
||||
=====================================
|
||||
|
||||
.. note::
|
||||
This documentation is targeted at Funkwhale users. In here you'll find guides for interacting with
|
||||
Funkwhale, uploading your music, and building a musical social network.
|
||||
|
||||
This documentation is meant for end-users of the platform.
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
apps
|
||||
create
|
||||
tagging
|
||||
upload
|
||||
|
||||
|
||||
Using Funkwhale
|
||||
---------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
queue
|
||||
managing
|
||||
playlists
|
||||
favorites
|
||||
radios
|
||||
follow
|
||||
apps
|
||||
|
||||
Troubleshooting Issues
|
||||
----------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
troubleshooting
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
Managing Content and Libraries
|
||||
==============================
|
||||
|
||||
Managing your music libraries is an important part of using Funkwhale. In addition to :doc:`uploading new music <upload>`, you may also want to :ref:`edit your library's details <edit_library>`, :ref:`delete a library <delete_library>`, or :ref:`remove content from a library <remove_content>`.
|
||||
|
||||
.. _edit_library:
|
||||
|
||||
Editing a Library
|
||||
--------------------
|
||||
|
||||
To change details about a library:
|
||||
|
||||
- Navigate to ``https://your-instance/content/libraries`` or click "Add Content" under the "Music" menu, select "Upload audio content", and click "Detail" under the library you wish to edit
|
||||
- Select "Edit" from the menu that appears
|
||||
- In the edit menu, you will be able to change the name, description, and visibility of your library
|
||||
- Make the changes you wish to make, then select "Update library" to save the changes
|
||||
|
||||
.. _delete_library:
|
||||
|
||||
Deleting a Library
|
||||
------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
Deleting a library will also delete any content within the library. Make sure that content is backed up before continuing.
|
||||
|
||||
To delete a library:
|
||||
|
||||
- Navigate to ``https://your-instance/content/libraries`` or click "Add Content" under the "Music" menu, select "Upload audio content", and click "Detail" under the library you wish to edit
|
||||
- Select "Edit" from the menu that appears
|
||||
- Select "Delete" from the bottom of the menu. A pop up will appear warning of the consequences of deleting the library. If you want to continue, click "Delete library"
|
||||
|
||||
.. _remove_content:
|
||||
|
||||
Removing Content From a Library
|
||||
-------------------------------
|
||||
|
||||
.. warning::
|
||||
|
||||
Removing content from your library deletes the file from the server. Make sure you have a backup of any files you want to keep.
|
||||
|
||||
To delete content from a library:
|
||||
|
||||
- Navigate to ``https://your-instance/content/libraries`` or click "Add Content" under the "Music" menu, select "Upload audio content", and click "Detail" under the library you wish to edit
|
||||
- Select "Tracks" from the menu that appears
|
||||
- Select all tracks you wish to remove by selecting the checkboxes next to them
|
||||
- In the "Actions" drop down menu, select "Delete" and click "Go". A pop up will appear warning of the consequences of deleting the library. If you want to continue, click "Launch"
|
|
@ -0,0 +1,121 @@
|
|||
Creating and Managing Playlists
|
||||
===============================
|
||||
|
||||
Playlists are an important part of any music collection, and Funkwhale is no different. Funkwhale
|
||||
allows you to create playlists for yourself, for other users on your server, or for the entire federated
|
||||
network.
|
||||
|
||||
Creating a New Playlist
|
||||
-----------------------
|
||||
|
||||
Once you've :doc:`uploaded some content to your instance <upload>`, or have
|
||||
:doc:`followed some public libraries of your choosing <follow>`, you can get
|
||||
started creating new playlists.
|
||||
|
||||
To create a playlist:
|
||||
|
||||
- Click on "Playlists" under the "Music" section on the left-hand side
|
||||
- A pop-up will appear listing any of your existing playlists
|
||||
- Enter a name for your playlist under the "Playlist name" section
|
||||
- Choose a visibility setting:
|
||||
- **Nobody except me**: The playlist will be hidden from all users of the instance
|
||||
- **Everyone on this instance**: The playlist will be visible to local accounts, but not to external users
|
||||
- **Everyone**: The playlist will be public
|
||||
- Click "Create Playlist" to commit your changes
|
||||
|
||||
.. note::
|
||||
|
||||
If you create a public library with non-public content, users will be able to see all tracks but
|
||||
will only be able to play those that are accessible by them.
|
||||
|
||||
Add Content to Playlist
|
||||
-----------------------
|
||||
|
||||
Now that you've created your playlist, you need to put some music in it. Music can be added in a
|
||||
few different ways:
|
||||
|
||||
Add Currently Playing Song
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add the currently playing song to a playlist:
|
||||
|
||||
- On the player at the bottom left of the screen, select the list icon to bring up the playlists pop-up
|
||||
- Find the playlist you would like to add the song to and click "Add track"
|
||||
- The changes will be saved automatically. Click "End Edition" to stop editing the playlist
|
||||
|
||||
Add Music From Library
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add tracks from anywhere in Funkwhale:
|
||||
|
||||
- Search for the song or album you want to add to the playlist in the Search menu
|
||||
- Next to the song in question, you will see a list icon. Click on this to bring up the playlists pop-up
|
||||
- Find the playlist you would like to add the song to
|
||||
- The changes will be saved automatically. Click "End Edition" to stop editing the playlist
|
||||
|
||||
Add Music From Queue
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To store the music that is currently in your queue:
|
||||
|
||||
- Click on "Playlists" under the "Music" section on the left-hand side
|
||||
- A pop-up will appear listing any of your existing playlists
|
||||
- Click on the playlist you want to add your content to
|
||||
- In the window that appears, select "Edit" to start a new edition
|
||||
- In the "Playlist editor" that appears, select "Insert from Queue" to add all content
|
||||
- The changes will be saved automatically. Click "End Edition" to stop editing the playlist
|
||||
|
||||
Edit Playlist Contents
|
||||
----------------------
|
||||
|
||||
Delete Music From Playlist
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To remove a song or songs from a playlist:
|
||||
|
||||
- Click on "Playlists" under the "Music" section on the left-hand side
|
||||
- A pop-up will appear listing any of your existing playlists
|
||||
- Click on the playlist you want to remove content from
|
||||
- In the window that appears, select "Edit" to start a new edition
|
||||
- For any track you want to remove, click on the red trash can icon on the right-hand side
|
||||
- To remove all tracks at once, click "Clear Playlist"
|
||||
- The changes will save automatically. Click "End Edition" to stop editing the playlist
|
||||
|
||||
Reorder Music in a Playlist
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To change the order of songs in a playlist:
|
||||
|
||||
- Click on "Playlists" under the "Music" section on the left-hand side
|
||||
- A pop-up will appear listing any of your existing playlists
|
||||
- Click on the playlist you want to reorder
|
||||
- In the window that appears, select "Edit" to start a new edition
|
||||
- Drag the songs into the new order you want to store them in
|
||||
- The changes will save automatically. Click "End Edition" to stop editing the playlist
|
||||
|
||||
Edit Playlist Settings
|
||||
----------------------
|
||||
|
||||
If you want to change the name or visibility of a playlist, you will need to edit the playlist's settings.
|
||||
|
||||
- Click on "Playlists" under the "Music" section on the left-hand side
|
||||
- A pop-up will appear listing any of your existing playlists
|
||||
- Click on the playlist you want to add your content to
|
||||
- In the window that appears, select "Edit" to start a new edition
|
||||
- Change the "Playlist name" or "Playlist visibility" to their new values
|
||||
- Click "Update playlist" to commit your changes
|
||||
- Click "End Edition" to stop editing the playlist
|
||||
|
||||
Delete a Playlist
|
||||
-----------------
|
||||
|
||||
.. warning::
|
||||
|
||||
Deleting a playlist is permanent and will remove access for all other users. Only do this if you're sure you want to!
|
||||
|
||||
To delete a playlist:
|
||||
|
||||
- Click on "Playlists" under the "Music" section on the left-hand side
|
||||
- A pop-up will appear listing any of your existing playlists
|
||||
- Click on the playlist you want to delete
|
||||
- Click on "Delete". A pop-up will appear warning you that this action is permanent. If you wish to continue, select "Delete playlist"
|
|
@ -0,0 +1,64 @@
|
|||
Managing Your Queue
|
||||
===================
|
||||
Your queue is where you can add tracks to queue them up for listening, arrange music to create a curated list,
|
||||
and even :doc:`save a list as a playlist <playlists>`.
|
||||
|
||||
Add Tracks to Your Queue
|
||||
------------------------
|
||||
|
||||
There are four options to choose from when adding music to a queue:
|
||||
|
||||
- Play - this will start playing the selected item(s) immediately, stopping any currently playing tracks
|
||||
- Add to queue - this adds the selected item(s) to the bottom of the queue. If the queue is empty, it will add them but not start playing
|
||||
- Play next - this adds the selected item(s) just underneath the currently selected track in the queue
|
||||
- Play now - this acts the same as "Play"
|
||||
|
||||
Add a Song to the Queue
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add an individual track to the queue:
|
||||
|
||||
- Search for a track, or navigate to its album page in the library
|
||||
- Click on the track you want to add to bring up its information page
|
||||
- Click on the down arrow next to "Play" and select "Add to Queue", "Play Next", or "Play Now"
|
||||
|
||||
Add an Album to the Queue
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add a whole album to the queue:
|
||||
|
||||
- Navigate to ``https://your-instance/library/playlists`` or click on "Browse" in the "Music" library on the left-hand side then select "Playlists" along the top
|
||||
- Find the playlist you wish to add
|
||||
- Click on the three dot menu to "Play" and select "Add to Queue", "Play Next", or "Play Now"
|
||||
|
||||
Add a Playlist to the Queue
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To add a playlist to the queue:
|
||||
|
||||
- Search for an album, or navigate to its album page in the library
|
||||
- Click on the down arrow next to "Play" and select "Add to Queue", "Play Next", or "Play Now"
|
||||
|
||||
|
||||
Rearrange Tracks in Your Queue
|
||||
------------------------------
|
||||
|
||||
To change the order of tracks in a queue
|
||||
|
||||
- Open your queue by clicking on "Queue" underneath the search bar
|
||||
- Find the track you want to move and click on the number on the left hand side
|
||||
- Hold and drag the track to the position you want it in
|
||||
- Release the mouse button to drop the track in place
|
||||
|
||||
Remove Tracks From Your Queue
|
||||
-----------------------------
|
||||
|
||||
.. note::
|
||||
|
||||
If you remove the currently playing track from your queue, Funkwhale will automatically start playing the next
|
||||
item in the queue
|
||||
|
||||
To remove tracks from your queue:
|
||||
|
||||
- Open your queue by clicking on "Queue" underneath the search bar
|
||||
- Find the item you want to remove and click on the trash can icon to remove it
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
Using Radios
|
||||
============
|
||||
|
||||
.. note::
|
||||
|
||||
Currently, Funkwhale does not implement tags for use in radios. There is a lot of active disucssion
|
||||
around how to implement them, but in the meantime it is only possible to create artist radios.
|
||||
|
||||
Radios are a great way to discover new music, or even just create a dynamic playlist of songs you like.
|
||||
By default, all users have access to three build-in radios:
|
||||
|
||||
- Favorites - this plays through your :doc:`favorite tracks <favorites>`
|
||||
- Random - plays random songs from your :doc:`libraries <upload>` or :doc:`libraries you follow <follow>`
|
||||
- Less Listened - plays songs you listen to less frequently
|
||||
|
||||
Creating a New Radio
|
||||
--------------------
|
||||
|
||||
.. note::
|
||||
|
||||
Any music that is in a private collection will appear in public radios but will not be playable unless the user has access to
|
||||
the containing library
|
||||
|
||||
In addition to the built-in radios, Funkwhale offers users the ability to create their own specific radios.
|
||||
These radios can be shared with other users on your instance or kept entirely to yourself.
|
||||
|
||||
To create a new radio:
|
||||
|
||||
- Navigate to ``https://your-instance/library/radios`` or click "Browse Library" and select "Radios" along the top of the screen
|
||||
- Under "User Radios", click "Create your own radio"
|
||||
- Give your radio a name and description
|
||||
- If you want to share your radio on your instance, check the "Display publicly" box. Otherwise, uncheck this to keep the radio private
|
||||
- To set up the filters for your radio, click on "Select a filter" and select "Artist" from the drop-down menu. Click "Add Filter" to activate the filter
|
||||
- To exclude certain artists, toggle the "Exclude" switch so it turns blue and then select the artists from the "Select artists" drop-down menu
|
||||
- To only include certain artists, toggle the "Exclude" switch so it turns gray and then select the artists from the "Select artists" drop-down menu
|
||||
- Click "Save" to save your radio
|
||||
|
||||
Listening to a Radio
|
||||
--------------------
|
||||
|
||||
To start listening to a radio:
|
||||
|
||||
- Navigate to ``https://your-instance/library/radios`` or click "Browse Library" and select "Radios" along the top of the screen
|
||||
- Find the radio you want to listen to and click on "Start radio"
|
||||
- Your queue will be populated with the **currently playing** song and the **next song on the radio**
|
||||
|
||||
To stop listening to a radio:
|
||||
|
||||
- Open your :doc:`queue`
|
||||
- Select "Stop Radio" at the bottom of the queue
|
||||
- The songs that were queued will stay in your queue, but the radio will stop queueing new songs
|
|
@ -0,0 +1,107 @@
|
|||
End-User Troubleshooting
|
||||
========================
|
||||
|
||||
Various errors and issues can arise on your Funkwhale instance, caused by configuration errors,
|
||||
deployment/environment specific issues, or bugs in the software itself.
|
||||
|
||||
On this document, you'll find:
|
||||
|
||||
- Tools and commands you can use to better understand the issues
|
||||
- A list of common pitfalls and errors and how to solve them
|
||||
- A collection of links and advice to get help from the community and report new issues
|
||||
|
||||
Diagnose problems
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Funkwhale is made of several components, each one being a potential cause for failure. Having an even basic overview
|
||||
of Funkwhale's technical architecture can help you understand what is going on. You can refer to :doc:`the technical architecture <../developers/architecture>` for that.
|
||||
|
||||
Problems usually fall into one of those categories:
|
||||
|
||||
- **Frontend**: Funkwhale's interface is not loading, not behaving as expected, music is not playing
|
||||
- **API**: the interface do not display any data or show errors
|
||||
- **Import**: uploaded/imported tracks are not imported correctly or at all
|
||||
- **Federation**: you cannot contact other Funkwhale servers, access their library, play federated tracks
|
||||
- **Everything else**
|
||||
|
||||
Each category comes with its own set of diagnose tools and/or commands we will detail below. We'll also give you simple
|
||||
steps for each type of problem. Please try those to see if it fix your issues. If none of those works, please report your issue on our
|
||||
issue tracker.
|
||||
|
||||
Frontend issues
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Diagnostic tools:
|
||||
|
||||
- Javascript and network logs from your browser console (see instructions on how to open it in `Chrome <https://developers.google.com/web/tools/chrome-devtools/console/>`_ and `Firefox <https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console>`_
|
||||
- Proxy and API access and error logs
|
||||
- The same operation works from a different browser
|
||||
|
||||
Common problems
|
||||
***************
|
||||
|
||||
The front-end is completely blank
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You are visiting Funkwhale, but you don't see anything.
|
||||
|
||||
- Try from a different browser
|
||||
- Check network errors in your browser console. If you see responses with 40X or 50X statuses, there is probably an issue with the webserver configuration
|
||||
- If you don't see anything wrong in the network console, check the Javascript console
|
||||
- Disable your browser extensions (like adblockers)
|
||||
|
||||
Music is not playing
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You have some tracks in your queue that don't play, or the queue is jumping from one track to the next until
|
||||
there is no more track available:
|
||||
|
||||
- Try with other tracks. If it works with some tracks but not other tracks, this may means that the failing tracks are not probably imported
|
||||
or that your browser does not support a specific audio format
|
||||
- Check the network and javascript console for potential errors
|
||||
|
||||
Tracks are not appending to the queue
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When clicking on "Play", "Play all albums" or "Play all" buttons, some tracks are not appended to the queue. This is
|
||||
actually a feature of Funkwhale: those tracks have no file associated with them, so we cannot play them.
|
||||
|
||||
Specific pages are loading forever or blank
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When viewing a given page, the page load never ends (you continue to see the spinner), or nothing seems to appear at all:
|
||||
|
||||
- Ensure your internet connection is up and running
|
||||
- Ensure your instance is up and running
|
||||
- Check the network and javascript console for potential errors
|
||||
|
||||
Report an issue or get help
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Well be more than happy to help you to debug installation and configuration issues. The main channel
|
||||
for receiving support about your Funkwhale installation is the `#funkwhale-troubleshooting:matrix.org <https://riot.im/app/#/room/#funkwhale-troubleshooting:matrix.org>`_ Matrix channel.
|
||||
|
||||
Before asking for help, we'd really appreciate if you took the time to go through this document and try to diagnose the problem yourself. But if you don't find
|
||||
anything relevant or don't have the time, we'll be there for you!
|
||||
|
||||
Here are a few recommendations on how to structure and what to include in your help requests:
|
||||
|
||||
- Give us as much context as possible about your installation (OS, version, Docker/non-docker, reverse-proxy type, relevant logs and errors, etc.)
|
||||
- Including screenshots or small gifs or videos can help us considerably when debugging front-end issues
|
||||
|
||||
You can also open issues on our `issue tracker <https://dev.funkwhale.audio/funkwhale/funkwhale/issues>`_. Please have a quick look for
|
||||
similar issues before doing that, and use the issue tracker only to report bugs, suggest enhancements (both in the software and the documentation) or new features.
|
||||
|
||||
.. warning::
|
||||
|
||||
If you ever need to share screenshots or urls with someone else, ensure those do not include your personal token.
|
||||
This token is binded to your account and can be used to connect and use your account.
|
||||
|
||||
Urls that includes your token looks like: ``https://your.instance/api/v1/uploads/42/serve/?jwt=yoursecrettoken``
|
||||
|
||||
Improving this documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you feel like something should be improved in this document (and in the documentation in general), feel free to :doc:`contribute to the documentation <../documentation/creating>`.
|
||||
If you're not comfortable contributing or would like to ask somebody else to do it, feel free to :doc:`request a change in documentation <../documentation/identifying>`.
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
Uploading content on Funkwhale
|
||||
Uploading Content To Funkwhale
|
||||
==============================
|
||||
|
||||
To upload content on any Funkwhale instance, you need:
|
||||
To upload content to any Funkwhale instance, you need:
|
||||
|
||||
1. An account on that instance
|
||||
1. :doc:`An account on that instance <create>`
|
||||
2. :ref:`Storage space <upload-storage>`
|
||||
3. :ref:`A library <upload-library>`
|
||||
4. :ref:`Properly tagged files <upload-tagging>`
|
||||
5. :ref:`To upload your files <upload-upload>`
|
||||
|
||||
In this document, we'll guide you through steps 2 to 5.
|
||||
|
||||
.. _upload-storage:
|
||||
|
||||
Storage space
|
||||
|
@ -20,7 +18,7 @@ Once you have an account on a Funkwhale instance, as a user, you are granted the
|
|||
default upload quota (1GB by default). This default quota can be increased,
|
||||
reduced or completely removed by your instance admins depending on their policy.
|
||||
|
||||
Additionnaly, instance admins can grant you storage space manually. Get in touch with them
|
||||
Additionally, instance admins can grant you storage space manually. Get in touch with them
|
||||
if you'd like some additional storage space.
|
||||
|
||||
You can view your current quota and usage at any time by visiting ``/content/libraries/`` on your instance,
|
||||
|
@ -125,7 +123,8 @@ However, Funkwhale can understand and use additional tags to enhance user experi
|
|||
|
||||
The easiest way to inspect and edit file tags is with `MusicBrainz Picard <https://picard.musicbrainz.org/>`_, a free
|
||||
software, that works on Windows, MacOS and Linux. Picard is able to automatically tag many files,
|
||||
and include non-necessary but nice to have information, such as album covers.
|
||||
and include non-necessary but nice to have information, such as album covers. For a guide on tagging content with Picard,
|
||||
see :doc:`tagging`.
|
||||
|
||||
.. _upload-upload:
|
||||
|
||||
|
@ -144,3 +143,14 @@ by instance admins.
|
|||
|
||||
Once uploaded, your files should be processed shortly. It's usually a matter of seconds, but
|
||||
can vary depending on server load.
|
||||
|
||||
.. _upload-remove:
|
||||
|
||||
Removing files
|
||||
--------------
|
||||
|
||||
If you want to remove some of the files you have uploaded, visit ``/content/libraries/tracks/`` or click "Add content" in the sidebar then "Tracks" in the top menu.
|
||||
Then select the files you want to delete using the checkboxes on the left ; you can filter the list of files using a search pattern.
|
||||
Finally, select "Delete" in the "Action" menu and click "Go".
|
||||
|
||||
This operation does *not* remove metadata, meaning that deleted tracks will remain visible in your library. They just won't be playable anymore.
|
||||
|
|
|
@ -162,7 +162,7 @@ export default {
|
|||
.stripe p {
|
||||
font-size: 120%;
|
||||
}
|
||||
.list.icon {
|
||||
.ui.list .list.icon {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -166,14 +166,24 @@ export default {
|
|||
id: "fileUpload",
|
||||
handler: this.handleImportEvent
|
||||
});
|
||||
window.onbeforeunload = e => this.onBeforeUnload(e);
|
||||
},
|
||||
destroyed() {
|
||||
this.$store.commit("ui/removeWebsocketEventHandler", {
|
||||
eventName: "import.status_updated",
|
||||
id: "fileUpload"
|
||||
});
|
||||
window.onbeforeunload = null;
|
||||
},
|
||||
methods: {
|
||||
onBeforeUnload(e = {}) {
|
||||
const returnValue = ('This page is asking you to confirm that you want to leave - data you have entered may not be saved.');
|
||||
if (!this.hasActiveUploads) return null;
|
||||
Object.assign(e, {
|
||||
returnValue,
|
||||
});
|
||||
return returnValue;
|
||||
},
|
||||
inputFile(newFile, oldFile) {
|
||||
this.$refs.upload.active = true;
|
||||
},
|
||||
|
@ -291,6 +301,9 @@ export default {
|
|||
f.statusIndex = statusIndex
|
||||
return f
|
||||
}), ['statusIndex', 'name'])
|
||||
},
|
||||
hasActiveUploads () {
|
||||
return this.sortedFiles.filter((f) => { return f.active }).length > 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="ui section hidden divider"></div>
|
||||
<div class="ui grid">
|
||||
<div class="ui row">
|
||||
<div class="ui stackable one column grid">
|
||||
<div class="column">
|
||||
<album-widget :filters="{playable: true, ordering: '-creation_date'}">
|
||||
<template slot="title"><translate>Recently added</translate></template>
|
||||
</album-widget>
|
||||
|
|
|
@ -17,7 +17,15 @@ export function ago (date, locale) {
|
|||
locale = locale || 'en'
|
||||
const m = moment(date)
|
||||
m.locale(locale)
|
||||
return m.fromNow()
|
||||
return m.calendar(null, {
|
||||
sameDay: 'LT',
|
||||
nextDay: 'L',
|
||||
nextWeek: 'L',
|
||||
lastDay: 'L',
|
||||
lastWeek: 'L',
|
||||
sameElse: 'L'
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
Vue.filter('ago', ago)
|
||||
|
|
|
@ -57,28 +57,17 @@ Vue.use(GetTextPlugin, {
|
|||
Vue.use(VueMasonryPlugin)
|
||||
Vue.use(VueLazyload)
|
||||
Vue.config.productionTip = false
|
||||
Vue.directive('title', {
|
||||
inserted: (el, binding) => {
|
||||
let parts = []
|
||||
let instanceName = store.state.instance.settings.instance.name.value
|
||||
if (instanceName.length === 0) {
|
||||
instanceName = 'Funkwhale'
|
||||
}
|
||||
parts.unshift(instanceName)
|
||||
parts.unshift(binding.value)
|
||||
document.title = parts.join(' - ')
|
||||
},
|
||||
updated: (el, binding) => {
|
||||
let parts = []
|
||||
let instanceName = store.state.instance.settings.instance.name.value
|
||||
if (instanceName.length === 0) {
|
||||
instanceName = 'Funkwhale'
|
||||
}
|
||||
parts.unshift(instanceName)
|
||||
parts.unshift(binding.value)
|
||||
document.title = parts.join(' - ')
|
||||
Vue.directive('title', function (el, binding) {
|
||||
let parts = []
|
||||
let instanceName = store.state.instance.settings.instance.name.value
|
||||
if (instanceName.length === 0) {
|
||||
instanceName = 'Funkwhale'
|
||||
}
|
||||
})
|
||||
parts.unshift(instanceName)
|
||||
parts.unshift(binding.value)
|
||||
document.title = parts.join(' - ')
|
||||
}
|
||||
)
|
||||
axios.interceptors.request.use(function (config) {
|
||||
// Do something before request is sent
|
||||
if (store.state.auth.token) {
|
||||
|
|
|
@ -75,6 +75,9 @@
|
|||
// see https://github.com/webpack/webpack/issues/215
|
||||
@import "./vendor/media";
|
||||
|
||||
$desktop-sidebar-width: 300px;
|
||||
$widedesktop-sidebar-width: 350px;
|
||||
|
||||
html,
|
||||
body {
|
||||
@include media("<desktop") {
|
||||
|
@ -91,12 +94,25 @@ body {
|
|||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.ui.wide.left.sidebar {
|
||||
@include media(">desktop") {
|
||||
width: $desktop-sidebar-width;
|
||||
}
|
||||
|
||||
@include media(">widedesktop") {
|
||||
width: $widedesktop-sidebar-width;
|
||||
}
|
||||
}
|
||||
.main.pusher,
|
||||
.footer {
|
||||
@include media(">desktop") {
|
||||
margin-left: 350px !important;
|
||||
margin-left: $desktop-sidebar-width !important;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
@include media(">widedesktop") {
|
||||
margin-left: $widedesktop-sidebar-width !important;;
|
||||
}
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
|
@ -118,11 +134,14 @@ body {
|
|||
}
|
||||
@include media(">desktop") {
|
||||
position: fixed;
|
||||
left: 350px;
|
||||
left: $desktop-sidebar-width;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
z-index: 99;
|
||||
}
|
||||
@include media(">widedesktop") {
|
||||
left: $widedesktop-sidebar-width;
|
||||
}
|
||||
background-color: white;
|
||||
.item {
|
||||
padding-top: 1.5em;
|
||||
|
@ -135,7 +154,10 @@ body {
|
|||
bottom: 1em;
|
||||
left: 1em;
|
||||
@include media(">desktop") {
|
||||
left: 350px;
|
||||
left: $desktop-sidebar-width;
|
||||
}
|
||||
@include media(">widedesktop") {
|
||||
left: $widedesktop-sidebar-width;
|
||||
}
|
||||
}
|
||||
.main-pusher {
|
||||
|
@ -143,9 +165,12 @@ body {
|
|||
}
|
||||
.ui.stripe.segment,
|
||||
#footer {
|
||||
padding: 2em;
|
||||
padding: 1em;
|
||||
@include media(">tablet") {
|
||||
padding: 4em;
|
||||
padding: 2em;
|
||||
}
|
||||
@include media(">widedesktop") {
|
||||
padding: 3em;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
$breakpoints: (
|
||||
'phone': 320px,
|
||||
'tablet': 768px,
|
||||
'desktop': 1024px
|
||||
'desktop': 1024px,
|
||||
'widedesktop': 1200px
|
||||
) !default;
|
||||
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
</td>
|
||||
</template>
|
||||
<template v-else>
|
||||
<td>{{ scope.obj.source }}</td>
|
||||
<td :title="scope.obj.source">{{ scope.obj.source | truncate(25) }}</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</template>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div class="ui text loader"><translate>Loading library data…</translate></div>
|
||||
</div>
|
||||
<detail-area v-else :library="library">
|
||||
<file-upload :default-import-reference="defaultImportReference" :library="library" />
|
||||
<file-upload ref="fileupload" :default-import-reference="defaultImportReference" :library="library" />
|
||||
</detail-area>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -20,6 +20,19 @@ export default {
|
|||
components: {
|
||||
DetailArea,
|
||||
FileUpload
|
||||
},
|
||||
beforeRouteLeave (to, from, next){
|
||||
if (this.$refs.fileupload.hasActiveUploads){
|
||||
const answer = window.confirm('This page is asking you to confirm that you want to leave - data you have entered may not be saved.')
|
||||
if (answer) {
|
||||
next()
|
||||
} else {
|
||||
next(false)
|
||||
}
|
||||
}
|
||||
else{
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {expect} from 'chai'
|
||||
|
||||
import moment from 'moment'
|
||||
import {truncate, ago, capitalize, year} from '@/filters'
|
||||
|
||||
describe('filters', () => {
|
||||
|
@ -24,7 +24,15 @@ describe('filters', () => {
|
|||
it('works', () => {
|
||||
const input = new Date()
|
||||
let output = ago(input)
|
||||
expect(output).to.equal('a few seconds ago')
|
||||
let expected = moment(input).calendar(input, {
|
||||
sameDay: 'LT',
|
||||
nextDay: 'L',
|
||||
nextWeek: 'L',
|
||||
lastDay: 'L',
|
||||
lastWeek: 'L',
|
||||
sameElse: 'L'
|
||||
})
|
||||
expect(output).to.equal(expected)
|
||||
})
|
||||
})
|
||||
describe('year', () => {
|
||||
|
|
Loading…
Reference in New Issue