Merge branch 'pre-release/1.3.0' into develop

environments/review-docs-2127-ugzpoc/deployments/17481
Georg Krause 2023-05-12 09:21:47 +02:00
commit c48b62da94
41 zmienionych plików z 2514 dodań i 1697 usunięć

108
.vscode/markdown.code-snippets vendored 100644
Wyświetl plik

@ -0,0 +1,108 @@
{
"Callout": {
"prefix": "callout",
"description": "Add a callout to highlight information",
"body": [
":::{${1|attention,caution,danger,error,hint,important,note,seealso,tip,warning|}} ${2:Optional title}",
"${0:${TM_SELECTED_TEXT}}",
":::"
],
},
"Code tabs": {
"prefix": "code-tabs",
"description": "Insert a set of code tabs",
"body": [
":::{tab-set-code}",
"",
"$0",
"",
":::"
]
},
"Tab set": {
"prefix": "tab-set",
"description": "Insert a group of generic tabs",
"body": [
"::::{tab-set}",
":::{tab-item} ${1:Tab title}",
"$2",
":::",
"",
":::{tab-item} ${3:Tab title}",
"$0",
":::",
"",
"::::"
]
},
"Insert fragment": {
"prefix": "insert fragment",
"description": "Insert reusable text from another file",
"body": [
":::{include} ${1:full path to file}",
":start-after: ${2:the text to start after}",
":end-before: ${0:the text to end before}",
":::"
]
},
"Dropdown": {
"prefix": "insert dropdown",
"description": "Insert a dropdown (accordion)",
"body": [
":::{dropdown} ${1:title}",
"${0:${TM_SELECTED_TEXT}}",
":::"
]
},
"Versioning": {
"prefix": "version change",
"description": "Specify when a feature was added, changed, or deprecated",
"body": [
":::{${1|versionadded,versionchanged,deprecated|}} ${2:v4.32.0}",
"${0:${TM_SELECTED_TEXT}}",
":::"
]
},
"List table": {
"prefix": "list table",
"description": "Insert a table defined as a set of lists",
"body": [
":::{list-table} ${1:Optional title}",
":header-rows: ${2:Number of header rows}",
"",
"* - ${3: First row column 1}",
" - ${4: First row column 2}",
"* - ${5: Second row column 1}",
" - ${0: Second row column 2}",
":::"
]
},
"Guilabel": {
"prefix": "guilabel",
"description": "Format text as a GUI label (e.g. a button label or interface label",
"body": [
"{guilabel}`${0:${TM_SELECTED_TEXT}}`"
]
},
"File": {
"prefix": "file",
"description": "Format text as a file name or path",
"body": [
"{file}`${0:${TM_SELECTED_TEXT}}`"
]
},
"Increase indent": {
"prefix": "increase indent",
"description": "Increase the indentation of all selected colon or backtick fences",
"body": [
"${TM_SELECTED_TEXT/((?<c>[`:])\\k<c>{2,})/$1$2/gm}"
]
},
"Deprecation warning": {
"prefix": "insert deprecation warning",
"description": "Inserts an inline deprecation badge. Useful in tables of parameters",
"body": [
"{bdg-warning}`Deprecated`"
]
}
}

Wyświetl plik

@ -9,6 +9,22 @@ This changelog is viewable on the web at https://docs.funkwhale.audio/changelog.
<!-- towncrier --> <!-- towncrier -->
## 1.3.0-rc6 (2023-05-12)
Updates since 1.3.0-rc5
- Add systemd update instructions to Debian upgrade instructions (#1966)
- Fix broken links in CHANGELOG (#1976)
- Add generic upgrade instructions to Docker postgres documentation (#2049)
- Added Nginx regeneration instructions to Debian update guide (#2050)
- Fixed mobile player element widths (#2054)
- Allow summary field of actors to be blank. This leaves actors valid that have a blank (`""`) summary field and allows follows from those.
- Fix front album tracks count translation
- Prefer str over dict for the CACHE_URL api setting\
This fix the ability to reuse the CACHE_URL with other settings such as\
CELERY_BROKER_URL.\
Move api docker hardcoded env vars in the settings module\
## 1.3.0-rc5 (2023-03-26) ## 1.3.0-rc5 (2023-03-26)
Updates since 1.3.0-rc4 Updates since 1.3.0-rc4
@ -98,7 +114,7 @@ Update instructions:
After this you can continue to use the **docker compose** syntax for all Docker management tasks. After this you can continue to use the **docker compose** syntax for all Docker management tasks.
- Upgrade Postgres to version 15. [Make sure to migrate!](https://docs.funkwhale.audio/administrator_documentation/upgrade_docs/docker.html#upgrade-the-postgres-container) - Upgrade Postgres to version 15. [Make sure to migrate!](https://docs.funkwhale.audio/administrator/upgrade/docker.html#upgrade-the-postgres-container)
- With this update Funkwhale starts using poetry to maintain its dependencies. We therefore recommend - With this update Funkwhale starts using poetry to maintain its dependencies. We therefore recommend
removing the old virtualenv by running `rm -rf /srv/funkwhale/virtualenv`. removing the old virtualenv by running `rm -rf /srv/funkwhale/virtualenv`.
@ -685,9 +701,7 @@ Committers:
Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html Upgrade instructions are available at https://docs.funkwhale.audio/admin/upgrading.html
Due to a bug in our CI Pipeline frontend artifacts are not available at Due to a bug in our CI Pipeline, you need to download the frontend artifact here: https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/81069/artifacts/download
https://dev.funkwhale.audio/funkwhale/funkwhale/builds/artifacts/1.2.0/download?job=build_front as they would usually.
Please use this URL to get your frontend build: https://dev.funkwhale.audio/funkwhale/funkwhale/-/jobs/81069/artifacts/download
If you are running the All-in-One-Container since a longer time, you probably need to manually migrate your database information. If that's the case, you will get a message like this: If you are running the All-in-One-Container since a longer time, you probably need to manually migrate your database information. If that's the case, you will get a message like this:

Wyświetl plik

@ -114,8 +114,6 @@ WORKDIR /app
RUN set -eux; \ RUN set -eux; \
pip3 install --no-deps --editable . pip3 install --no-deps --editable .
ENV CACHE_URL="redis://redis:6379/0"
ENV CELERY_BROKER_URL="redis://redis:6379/0"
ENV IS_DOCKER_SETUP=true ENV IS_DOCKER_SETUP=true
CMD ["./docker/server.sh"] CMD ["./docker/server.sh"]

Wyświetl plik

@ -14,6 +14,7 @@ APPS_DIR = ROOT_DIR.path("funkwhale_api")
env = environ.Env() env = environ.Env()
ENV = env ENV = env
LOGLEVEL = env("LOGLEVEL", default="info").upper() LOGLEVEL = env("LOGLEVEL", default="info").upper()
IS_DOCKER_SETUP = env.bool("IS_DOCKER_SETUP", False)
if env("FUNKWHALE_SENTRY_DSN", default=None) is not None: if env("FUNKWHALE_SENTRY_DSN", default=None) is not None:
@ -374,7 +375,7 @@ vars().update(EMAIL_CONFIG)
# The `_database_url_docker` variable will only by used as default for DATABASE_URL # The `_database_url_docker` variable will only by used as default for DATABASE_URL
# in the context of a docker deployment. # in the context of a docker deployment.
_database_url_docker = None _database_url_docker = None
if env.bool("IS_DOCKER_SETUP", False) and env.str("DATABASE_URL", None) is None: if IS_DOCKER_SETUP and env.str("DATABASE_URL", None) is None:
warnings.warn( warnings.warn(
DeprecationWarning( DeprecationWarning(
"the automatically generated 'DATABASE_URL' configuration in the docker " "the automatically generated 'DATABASE_URL' configuration in the docker "
@ -803,8 +804,11 @@ if AUTH_LDAP_ENABLED:
# SLUGLIFIER # SLUGLIFIER
AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify" AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify"
CACHE_DEFAULT = "redis://127.0.0.1:6379/0" CACHE_URL_DEFAULT = "redis://127.0.0.1:6379/0"
CACHE_URL = env.cache_url("CACHE_URL", default=CACHE_DEFAULT) if IS_DOCKER_SETUP:
CACHE_URL_DEFAULT = "redis://redis:6379/0"
CACHE_URL = env.str("CACHE_URL", default=CACHE_URL_DEFAULT)
""" """
The URL of your redis server. For example: The URL of your redis server. For example:
@ -818,17 +822,25 @@ If you're using password auth (the extra slash is important)
.. note:: .. note::
If you want to use Redis over unix sockets, you also need to update If you want to use Redis over unix sockets, you also need to update
:attr:`CELERY_BROKER_URL` :attr:`CELERY_BROKER_URL`, because the scheme differ from the one used by
:attr:`CACHE_URL`.
""" """
CACHES = { CACHES = {
"default": CACHE_URL, "default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": CACHE_URL,
"OPTIONS": {
"CLIENT_CLASS": "funkwhale_api.common.cache.RedisClient",
"IGNORE_EXCEPTIONS": True, # mimics memcache behavior.
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
},
},
"local": { "local": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache", "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
"LOCATION": "local-cache", "LOCATION": "local-cache",
}, },
} }
CACHES["default"]["BACKEND"] = "django_redis.cache.RedisCache"
CHANNEL_LAYERS = { CHANNEL_LAYERS = {
"default": { "default": {
@ -837,17 +849,12 @@ CHANNEL_LAYERS = {
} }
} }
CACHES["default"]["OPTIONS"] = {
"CLIENT_CLASS": "funkwhale_api.common.cache.RedisClient",
"IGNORE_EXCEPTIONS": True, # mimics memcache behavior.
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
}
CACHEOPS_DURATION = env("CACHEOPS_DURATION", default=0) CACHEOPS_DURATION = env("CACHEOPS_DURATION", default=0)
CACHEOPS_ENABLED = bool(CACHEOPS_DURATION) CACHEOPS_ENABLED = bool(CACHEOPS_DURATION)
if CACHEOPS_ENABLED: if CACHEOPS_ENABLED:
INSTALLED_APPS += ("cacheops",) INSTALLED_APPS += ("cacheops",)
CACHEOPS_REDIS = env("CACHE_URL", default=CACHE_DEFAULT) CACHEOPS_REDIS = CACHE_URL
CACHEOPS_PREFIX = lambda _: "cacheops" # noqa CACHEOPS_PREFIX = lambda _: "cacheops" # noqa
CACHEOPS_DEFAULTS = {"timeout": CACHEOPS_DURATION} CACHEOPS_DEFAULTS = {"timeout": CACHEOPS_DURATION}
CACHEOPS = { CACHEOPS = {
@ -858,9 +865,7 @@ if CACHEOPS_ENABLED:
# CELERY # CELERY
INSTALLED_APPS += ("funkwhale_api.taskapp.celery.CeleryConfig",) INSTALLED_APPS += ("funkwhale_api.taskapp.celery.CeleryConfig",)
CELERY_BROKER_URL = env( CELERY_BROKER_URL = env.str("CELERY_BROKER_URL", default=CACHE_URL)
"CELERY_BROKER_URL", default=env("CACHE_URL", default=CACHE_DEFAULT)
)
""" """
The celery task broker URL. Defaults to :attr:`CACHE_URL`. The celery task broker URL. Defaults to :attr:`CACHE_URL`.
You don't need to tweak this unless you want You don't need to tweak this unless you want

1333
api/poetry.lock wygenerowano

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1 @@
Add systemd update instructions to Debian upgrade instructions (#1966)

Wyświetl plik

@ -0,0 +1 @@
Fix broken links in CHANGELOG (#1976)

Wyświetl plik

@ -0,0 +1 @@
Add generic upgrade instructions to Docker postgres documentation (#2049)

Wyświetl plik

@ -0,0 +1 @@
Added Nginx regeneration instructions to Debian update guide (#2050)

Wyświetl plik

@ -0,0 +1 @@
Fixed mobile player element widths (#2054)

Wyświetl plik

@ -0,0 +1 @@
Fix front album tracks count translation

Wyświetl plik

@ -0,0 +1,4 @@
Prefer str over dict for the CACHE_URL api setting
This fix the ability to reuse the CACHE_URL with other settings such as
CELERY_BROKER_URL.

Wyświetl plik

@ -0,0 +1 @@
Move api docker hardcoded env vars in the settings module

Wyświetl plik

@ -1,5 +1,5 @@
FROM python:3.11 FROM python:3.11
RUN apt-get update && apt-get install -y graphviz RUN apt-get update && apt-get install -y graphviz
RUN pip install sphinx livereload sphinx_rtd_theme django-environ django myst-parser sphinx-design sphinxcontrib-mermaid RUN pip install sphinx livereload sphinx_rtd_theme django-environ django myst-parser sphinx-design sphinx-multiversion sphinxcontrib-mermaid sphinx-copybutton
WORKDIR /app/docs WORKDIR /app/docs

Wyświetl plik

@ -316,48 +316,61 @@ That's it! systemd keeps these services running and starts them up in the correc
Funkwhale uses a reverse proxy to serve content to users. We use [Nginx](https://nginx.com) to serve this proxy. Follow this guide to install an Nginx configuration using details from your `.env` file. Funkwhale uses a reverse proxy to serve content to users. We use [Nginx](https://nginx.com) to serve this proxy. Follow this guide to install an Nginx configuration using details from your `.env` file.
1. Install Nginx. :::{note} Before you begin
Nginx isn't preinstalled on Debian. You can install it by running the following commands:
```{code-block} sh ```console
sudo apt-get update $ sudo apt update
sudo apt-get install nginx $ sudo apt install nginx
```
:::
% Nginx update instructions
1. Log in to a root shell to make changes to the config files
```console
$ sudo su
``` ```
2. Download the Nginx templates from Funkwhale. 2. Download the new Nginx templates from Funkwhale
```{code-block} sh ```console
sudo curl -L -o /etc/nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale_proxy.conf" # curl -L -o /etc/nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale_proxy.conf"
sudo curl -L -o /etc/nginx/sites-available/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/nginx.template" # curl -L -o /etc/nginx/sites-available/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/nginx.template"
``` ```
3. Create an Nginx template with details from your `.env` file. 3. Update the Nginx configuration with details from your {file}`.env` file
```{code-block} sh ```console
# Log in to a root shell. # set -a && source /srv/funkwhale/config/.env && set +a
sudo su
# Create an Nginx configuration using the Funkwhale template with details from your `.env` file.
set -a && source /srv/funkwhale/config/.env && set +a
envsubst "`env | awk -F = '{printf \" $%s\", $$1}'`" \ envsubst "`env | awk -F = '{printf \" $%s\", $$1}'`" \
< /etc/nginx/sites-available/funkwhale.template \ < /etc/nginx/sites-available/funkwhale.template \
> /etc/nginx/sites-available/funkwhale.conf > /etc/nginx/sites-available/funkwhale.conf
# Enable the configuration so that Nginx serves it.
ln -s /etc/nginx/sites-available/funkwhale.conf /etc/nginx/sites-enabled/
# Exit the root shell.
exit
``` ```
That's it! You've created your Nginx file. Run the following command to check the `.env` details populated correctly. 4. Check the configuration file to make sure the template values have been updated properly
```{code-block} sh ```console
grep '${' /etc/nginx/sites-enabled/funkwhale.conf # grep '${' /etc/nginx/sites-available/funkwhale.conf
``` ```
% Instructions end
5. Create a symbolic link to the {file}`sites-enabled` directory to enable your configuration
```console
# ln -s /etc/nginx/sites-available/funkwhale.conf /etc/nginx/sites-enabled/
```
6. Reload Nginx
```console
# systemctl reload nginx
```
That's it! You've created your Nginx file.
## 10. Set up TLS ## 10. Set up TLS

Wyświetl plik

@ -167,50 +167,63 @@ That's it! Your Funkwhale pod is now up and running.
## 5. Set up your reverse proxy ## 5. Set up your reverse proxy
Funkwhale requires a reverse proxy to serve content to users. We recommend using [Nginx](https://nginx.com) to handle requests to your container. To do this: Funkwhale requires a reverse proxy to serve content to users. We recommend using [Nginx](https://nginx.com) to handle requests to your container. Follow this guide to install an Nginx configuration using details from your `.env` file.
1. Install Nginx. :::{note} Before you begin
Nginx isn't preinstalled on Debian. You can install it by running the following commands:
```{code-block} sh ```console
sudo apt-get update $ sudo apt update
sudo apt-get install nginx $ sudo apt install nginx
```
:::
% Nginx update instructions
1. Log in to a root shell to make changes to the config files
```console
$ sudo su
``` ```
2. Download the Nginx templates from Funkwhale. 2. Download the new Nginx templates from Funkwhale
```{code-block} sh ```console
sudo curl -L -o /etc/nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale_proxy.conf" # curl -L -o /etc/nginx/funkwhale_proxy.conf "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale_proxy.conf"
sudo curl -L -o /etc/nginx/sites-available/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/docker.proxy.template" # curl -L -o /etc/nginx/sites-available/funkwhale.template "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/docker.proxy.template"
``` ```
3. Create an Nginx template with details from your `.env` file. 3. Update the Nginx configuration with details from your {file}`.env` file
```{code-block} sh ```console
# Log in to a root shell. # set -a && source /srv/funkwhale/config/.env && set +a
sudo su
# Create an Nginx configuration using the Funkwhale template with details from your `.env` file.
set -a && source /srv/funkwhale/.env && set +a
envsubst "`env | awk -F = '{printf \" $%s\", $$1}'`" \ envsubst "`env | awk -F = '{printf \" $%s\", $$1}'`" \
< /etc/nginx/sites-available/funkwhale.template \ < /etc/nginx/sites-available/funkwhale.template \
> /etc/nginx/sites-available/funkwhale.conf > /etc/nginx/sites-available/funkwhale.conf
# Enable the configuration so that Nginx serves it.
ln -s /etc/nginx/sites-available/funkwhale.conf /etc/nginx/sites-enabled/
# Exit the root shell.
exit
``` ```
That's it! You've created your Nginx file. Run the following command to check the `.env` details populated correctly. 4. Check the configuration file to make sure the template values have been updated properly
```{code-block} sh ```console
grep '${' /etc/nginx/sites-enabled/funkwhale.conf # grep '${' /etc/nginx/sites-available/funkwhale.conf
``` ```
% Instructions end
5. Create a symbolic link to the {file}`sites-enabled` directory to enable your configuration
```console
# ln -s /etc/nginx/sites-available/funkwhale.conf /etc/nginx/sites-enabled/
```
6. Reload Nginx
```console
# systemctl reload nginx
```
That's it! You've created your Nginx file.
### Override default Nginx templates ### Override default Nginx templates

Wyświetl plik

@ -112,20 +112,20 @@ Check the file and remove any duplicated settings after copying.
1. Start up your new database container. 1. Start up your new database container.
```{code-block} sh ```console
sudo docker compose up -d postgres # docker compose up -d postgres
``` ```
2. Import your database dump into the new container. 2. Import your database dump into the new container.
```{code-block} sh ```console
cat db_dump.sql | sudo docker compose exec -T postgres psql -U postgres # cat db_dump.sql | docker compose exec -T postgres psql -U postgres
``` ```
3. Run the database migrations. 3. Run the database migrations.
```{code-block} sh ```console
sudo docker compose run --rm api funkwhale-manage migrate # docker compose run --rm api funkwhale-manage migrate
``` ```
## Start your Funkwhale instance ## Start your Funkwhale instance

Wyświetl plik

@ -6,20 +6,20 @@ If you installed Funkwhale following the [Debian guide](../installation/debian.m
1. Stop the Funkwhale services. 1. Stop the Funkwhale services.
```{code-block} sh ```console
sudo systemctl stop funkwhale.target # systemctl stop funkwhale.target
``` ```
2. Navigate to your Funkwhale directory. 2. Navigate to your Funkwhale directory.
```{code-block} sh ```console
cd /srv/funkwhale # cd /srv/funkwhale
``` ```
3. Remove the old files. 3. Remove the old files.
```{code-block} sh ```console
sudo rm -Rf api/* front/* venv # rm -Rf api/* front/* venv
``` ```
## Download Funkwhale ## Download Funkwhale
@ -31,35 +31,60 @@ If you installed Funkwhale following the [Debian guide](../installation/debian.m
``` ```
2. Follow the [Download Funkwhale](../installation/debian.md#3-download-funkwhale) instructions in the installation guide. 2. Follow the [Download Funkwhale](../installation/debian.md#3-download-funkwhale) instructions in the installation guide.
3. Follow the [Install the Funkwhale API](../installation/debian.md#4-install-the-funkwhale-api) instructions in the installation guide. 3. Follow the [Install the Funkwhale API](../installation/debian.md#4-install-the-funkwhale-api) instructions in the installation guide.
## Upgrade your systemd unit files
To make sure you receive any updates made to unit files, download the latest versions from the repo.
```console
# curl -L -o "/etc/systemd/system/funkwhale.target" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale.target"
# curl -L -o "/etc/systemd/system/funkwhale-server.service" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-server.service"
# curl -L -o "/etc/systemd/system/funkwhale-worker.service" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-worker.service"
# curl -L -o "/etc/systemd/system/funkwhale-beat.service" "https://dev.funkwhale.audio/funkwhale/funkwhale/raw/$FUNKWHALE_VERSION/deploy/funkwhale-beat.service"
```
## Update your reverse proxy configuration
To ensure your reverse proxy is up-to-date with changes, you should regenerate your Nginx configuration with each upgrade. To do this:
:::{include} /administrator/installation/debian.md
:start-after: Nginx update instructions
:end-before: Instructions end
:::
Once you've updated your configuration, reload Nginx.
```console
# systemctl reload nginx
```
## Update your Funkwhale instance ## Update your Funkwhale instance
Once you have downloaded the new files, you can update your Funkwhale instance. To do this: Once you have downloaded the new files, you can update your Funkwhale instance. To do this:
1. Install or upgrade all OS dependencies using the dependencies script. 1. Install or upgrade all OS dependencies using the dependencies script.
```{code-block} sh ```console
sudo api/install_os_dependencies.sh install # api/install_os_dependencies.sh install
``` ```
2. Collect the new static files to serve. 2. Collect the new static files to serve.
```{code-block} sh ```console
sudo venv/bin/funkwhale-manage collectstatic --no-input # venv/bin/funkwhale-manage collectstatic --no-input
``` ```
3. Apply new database migrations. 3. Apply new database migrations.
```{code-block} sh ```console
sudo -u funkwhale venv/bin/funkwhale-manage migrate # sudo -u funkwhale venv/bin/funkwhale-manage migrate
``` ```
4. Restart the Funkwhale services. 4. Restart the Funkwhale services.
```{code-block} sh ```console
sudo systemctl start funkwhale.target # systemctl start funkwhale.target
``` ```
That's it! You've updated your Funkwhale pod. You should now see the new version running in your web browser. That's it! You've updated your Funkwhale pod. You should now see the new version running in your web browser.

Wyświetl plik

@ -62,62 +62,86 @@ exit
Thats it! Youve updated your Funkwhale pod. You should now see the new version running in your web browser. Thats it! Youve updated your Funkwhale pod. You should now see the new version running in your web browser.
## Upgrade the postgres container ## Update your reverse proxy configuration
Funkwhale depends on postgres for its database container. To upgrade postgres, you need to export your database and import it into the new container. To ensure your reverse proxy is up-to-date with changes, you should regenerate your Nginx configuration with each upgrade. To do this:
To upgrade postgres on Docker we use the [`postgres-upgrade`](https://hub.docker.com/r/tianon/postgres-upgrade/) container. This Docker container automates the process of upgrading between major versions of postgres. Use these commands to upgrade your postgres container: :::{include} /administrator/installation/docker.md
:start-after: Nginx update instructions
:end-before: Instructions end
:::
1. Export your current postgres version number. You can find this in your `docker-compose.yml` file. Once you've updated your configuration, reload Nginx.
```{code-block} sh ```console
export OLD_POSTGRES=13 # systemctl reload nginx
```
## Upgrade the Postgres container
Funkwhale depends on Postgres for its database container. To upgrade Postgres, you need to export your database and import it into a new container to update the schema.
To update your Postgres container, follow these steps:
1. Stop all Funkwhale services
```console
# docker compose down
``` ```
2. Export the major version number you want to upgrade to. 2. Create a backup of your Funkwhale database. We will import this into the new postgres container later.
```{code-block} sh ```console
export NEW_POSTGRES=14 # docker compose exec -i postgres pg_dump -U postgres postgres > db_dump.sql
``` ```
3. Stop the postgres container. This means no data changes while you are upgrading. 3. Move the {file}`data/postgres` directory to another location to back it up
```{code-block} sh ```console
sudo docker compose stop postgres $ mv data/postgres data/postgres.bak
``` ```
4. Run the migration using the `postgres-upgrade` container. This creates a new version of the database in the `/srv/funkwhale/data/postgres-new` directory. 4. Create a new {file}`data/postgres` directory to house your data
```{code-block} sh ```console
sudo -E docker run --rm \ $ mkdir data/postgres
-v $(pwd)/data/postgres:/var/lib/postgresql/${OLD_POSTGRES}/data \
-v $(pwd)/data/postgres-new:/var/lib/postgresql/${NEW_POSTGRES}/data \
tianon/postgres-upgrade:${OLD_POSTGRES}-to-${NEW_POSTGRES}
``` ```
5. Re-add the access control rules required by Funkwhale. 5. Edit the {file}`docker-compose.yml` file in an editor of your choice.
```{code-block} sh ```console
echo "host all all all trust" | sudo tee -a ./data/postgres-new/pg_hba.conf $ nano docker-compose.yml
``` ```
6. Swap your old database out with your new database. 6. Update the version number in the `image` section of the `postgres` service to the major version you want to use. In this example, Postgres version `15` is used.
```{code-block} sh {emphasize-lines="9"}
mv ./data/postgres ./data/postgres-old
mv ./data/postgres-new ./data/postgres ```yaml
version: "3"
services:
postgres:
restart: unless-stopped
env_file: .env
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
image: postgres:15-alpine
volumes:
- ./data/postgres:/var/lib/postgresql/data
``` ```
7. Pull the new postgres version. 7. Save the file and close your editor
```{code-block} sh Once you've updated your Postgres containers, you need to migrate your database. To do this:
sudo docker compose pull
```
8. Restart your containers. :::{include} /administrator/migration.md
:start-line: 112
:end-line: 129
:::
```{code-block} sh :::{seealso}
sudo docker compose up -d You can use the [`postgres-upgrade` container](https://hub.docker.com/r/tianon/postgres-upgrade/) to automate some of the upgrade procedure on **AMD64** Docker deployments.
``` :::
That's it! Your Funkwhale pod is now running the new version of postgres. The old database is available in `/srv/funkwhale/data/postgres-old`. You can back this up and remove it from your server once you've confirmed everything is working. That's it! Your Funkwhale pod is now running the new version of Postgres. The old database is available in `/srv/funkwhale/data/postgres-old`. You can back this up and remove it from your server once you've confirmed everything is working.

Wyświetl plik

@ -51,6 +51,7 @@ extensions = [
"myst_parser", "myst_parser",
"sphinx_design", "sphinx_design",
"sphinxcontrib.mermaid", "sphinxcontrib.mermaid",
"sphinx_copybutton",
] ]
autodoc_mock_imports = [ autodoc_mock_imports = [
"celery", "celery",
@ -74,7 +75,7 @@ source_suffix = ".rst"
root_doc = "index" root_doc = "index"
# Enable colon fences # Enable colon fences
myst_enable_extensions = ["colon_fence"] myst_enable_extensions = ["colon_fence", "attrs_block"]
# Autogenerate anchors # Autogenerate anchors
@ -249,3 +250,7 @@ def setup(app):
# Internationalization settings # Internationalization settings
locale_dirs = ["locales/"] locale_dirs = ["locales/"]
gettext_compact = False gettext_compact = False
# Don't copy prompts with copybutton
copybutton_exclude = ".linenos, .gp"

520
docs/poetry.lock wygenerowano
Wyświetl plik

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. # This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
[[package]] [[package]]
name = "aiohttp" name = "aiohttp"
@ -228,22 +228,22 @@ files = [
[[package]] [[package]]
name = "attrs" name = "attrs"
version = "22.2.0" version = "23.1.0"
description = "Classes Without Boilerplate" description = "Classes Without Boilerplate"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.7"
files = [ files = [
{file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
{file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
] ]
[package.extras] [package.extras]
cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[docs,tests]"] dev = ["attrs[docs,tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope.interface"] tests = ["attrs[tests-no-zope]", "zope-interface"]
tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
[[package]] [[package]]
name = "autobahn" name = "autobahn"
@ -383,18 +383,18 @@ dev = ["Sphinx (==4.3.2)", "black (==22.3.0)", "build (==0.8.0)", "flake8 (==4.0
[[package]] [[package]]
name = "boto3" name = "boto3"
version = "1.26.99" version = "1.26.108"
description = "The AWS SDK for Python" description = "The AWS SDK for Python"
category = "main" category = "main"
optional = false optional = false
python-versions = ">= 3.7" python-versions = ">= 3.7"
files = [ files = [
{file = "boto3-1.26.99-py3-none-any.whl", hash = "sha256:536d9e7a074f4f16cc87b426f91b3079edd5c6927541a04f7e3fa28c53293532"}, {file = "boto3-1.26.108-py3-none-any.whl", hash = "sha256:27fd0fedfdcab0bbb672b0dd18844049b86de15dccf042488c6420f1101e8a10"},
{file = "boto3-1.26.99.tar.gz", hash = "sha256:d9fd57d6e98fd919cdbd613428f685e05b48c71477fda1aa7fbf51867262c7d1"}, {file = "boto3-1.26.108.tar.gz", hash = "sha256:22bb45185eaf0e4548a08d35ec11b910d55fa14f5ccd1048d1b95c8615afcc53"},
] ]
[package.dependencies] [package.dependencies]
botocore = ">=1.29.99,<1.30.0" botocore = ">=1.29.108,<1.30.0"
jmespath = ">=0.7.1,<2.0.0" jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.6.0,<0.7.0" s3transfer = ">=0.6.0,<0.7.0"
@ -403,14 +403,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]] [[package]]
name = "botocore" name = "botocore"
version = "1.29.106" version = "1.29.133"
description = "Low-level, data-driven core of boto 3." description = "Low-level, data-driven core of boto 3."
category = "main" category = "main"
optional = false optional = false
python-versions = ">= 3.7" python-versions = ">= 3.7"
files = [ files = [
{file = "botocore-1.29.106-py3-none-any.whl", hash = "sha256:d50df9a39da1b0e475727c6c2ba141b44d9df527d3dc1936b264ee4cb1525ab7"}, {file = "botocore-1.29.133-py3-none-any.whl", hash = "sha256:b266185d7414a559952569005009a400de50af91fd3da44f05cf05b00946c4a7"},
{file = "botocore-1.29.106.tar.gz", hash = "sha256:eaaa669fe33a0ef2e9d345a98ed0befac1ea33395d63620913c1bb738c387d4d"}, {file = "botocore-1.29.133.tar.gz", hash = "sha256:7b38e540f73c921d8cb0ac72794072000af9e10758c04ba7f53d5629cc52fa87"},
] ]
[package.dependencies] [package.dependencies]
@ -490,14 +490,14 @@ zstd = ["zstandard"]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2022.12.7" version = "2023.5.7"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
] ]
[[package]] [[package]]
@ -600,25 +600,25 @@ tests = ["async-timeout", "coverage (>=4.5,<5.0)", "pytest", "pytest-asyncio", "
[[package]] [[package]]
name = "channels-redis" name = "channels-redis"
version = "4.0.0" version = "4.1.0"
description = "Redis-backed ASGI channel layer implementation" description = "Redis-backed ASGI channel layer implementation"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "channels_redis-4.0.0-py3-none-any.whl", hash = "sha256:81b59d68f53313e1aa891f23591841b684abb936b42e4d1a966d9e4dc63a95ec"}, {file = "channels_redis-4.1.0-py3-none-any.whl", hash = "sha256:3696f5b9fe367ea495d402ba83d7c3c99e8ca0e1354ff8d913535976ed0abf73"},
{file = "channels_redis-4.0.0.tar.gz", hash = "sha256:122414f29f525f7b9e0c9d59cdcfc4dc1b0eecba16fbb6a1c23f1d9b58f49dcb"}, {file = "channels_redis-4.1.0.tar.gz", hash = "sha256:6bd4f75f4ab4a7db17cee495593ace886d7e914c66f8214a1f247ff6659c073a"},
] ]
[package.dependencies] [package.dependencies]
asgiref = ">=3.2.10,<4" asgiref = ">=3.2.10,<4"
channels = "*" channels = "*"
msgpack = ">=1.0,<2.0" msgpack = ">=1.0,<2.0"
redis = ">=4.2.0" redis = ">=4.5.3"
[package.extras] [package.extras]
cryptography = ["cryptography (>=1.3.0)"] cryptography = ["cryptography (>=1.3.0)"]
tests = ["async-timeout", "cryptography (>=1.3.0)", "pytest", "pytest-asyncio"] tests = ["async-timeout", "cryptography (>=1.3.0)", "pytest", "pytest-asyncio", "pytest-timeout"]
[[package]] [[package]]
name = "charset-normalizer" name = "charset-normalizer"
@ -1053,14 +1053,14 @@ six = "*"
[[package]] [[package]]
name = "django-environ" name = "django-environ"
version = "0.9.0" version = "0.10.0"
description = "A package that allows you to utilize 12factor inspired environment variables to configure your Django application." description = "A package that allows you to utilize 12factor inspired environment variables to configure your Django application."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.4,<4" python-versions = ">=3.5,<4"
files = [ files = [
{file = "django-environ-0.9.0.tar.gz", hash = "sha256:bff5381533056328c9ac02f71790bd5bf1cea81b1beeb648f28b81c9e83e0a21"}, {file = "django-environ-0.10.0.tar.gz", hash = "sha256:b3559a91439c9d774a9e0c1ced872364772c612cdf6dc919506a2b13f7a77225"},
{file = "django_environ-0.9.0-py2.py3-none-any.whl", hash = "sha256:f21a5ef8cc603da1870bbf9a09b7e5577ab5f6da451b843dbcc721a7bca6b3d9"}, {file = "django_environ-0.10.0-py2.py3-none-any.whl", hash = "sha256:510f8c9c1d0a38b0815f91504270c29440a0cf44fab07f55942fa8d31bbb9be6"},
] ]
[package.extras] [package.extras]
@ -1189,14 +1189,14 @@ files = [
[[package]] [[package]]
name = "drf-spectacular" name = "drf-spectacular"
version = "0.25.1" version = "0.26.1"
description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework" description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "drf-spectacular-0.25.1.tar.gz", hash = "sha256:789696f9845ef2397c52f66154aec6d96411baf6aa09a5d40c5f0b0e99f6b3d8"}, {file = "drf-spectacular-0.26.1.tar.gz", hash = "sha256:1599a204bf9cc6be7ef3e509859885a38d4f871fe287a1f191479868afd9e234"},
{file = "drf_spectacular-0.25.1-py3-none-any.whl", hash = "sha256:d58684e702f5ad436c5bd1735d46df0e123e64de883092d38f1debb9fa4a03c9"}, {file = "drf_spectacular-0.26.1-py3-none-any.whl", hash = "sha256:6df86ff6c2dc663792e5ff618643bf41d2ac9dc6fb5d1b0f273e2778bab951e5"},
] ]
[package.dependencies] [package.dependencies]
@ -1228,33 +1228,49 @@ sgmllib3k = "*"
[[package]] [[package]]
name = "frozendict" name = "frozendict"
version = "2.3.6" version = "2.3.8"
description = "A simple immutable dictionary" description = "A simple immutable dictionary"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
files = [ files = [
{file = "frozendict-2.3.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2178f8cc97d4ca8736df2fea0ca18094e259db086b560e5905ecac7f0894adc5"}, {file = "frozendict-2.3.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d188d062084fba0e4bf32719ff7380b26c050b932ff164043ce82ab90587c52b"},
{file = "frozendict-2.3.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e3255b0f33a65b558d99d067c1dbedc6f30effe66967d5b201c7fcffb20a86e"}, {file = "frozendict-2.3.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f2a4e818ac457f6354401dcb631527af25e5a20fcfc81e6b5054b45fc245caca"},
{file = "frozendict-2.3.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e25079fe3e11ca1360b8435f4a848c851b3c657b3ba3577a6627bfe6628705f"}, {file = "frozendict-2.3.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a506d807858fa961aaa5b48dab6154fdc6bd045bbe9310788bbff141bb42d13"},
{file = "frozendict-2.3.6-cp310-cp310-win_amd64.whl", hash = "sha256:caed7300322a47ceeaa00a311f902cbbeb7a3d1c8955487de3ea0ad618048325"}, {file = "frozendict-2.3.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:750632cc890d8ee9484fe6d31b261159144b6efacc08e1317fe46accd1410373"},
{file = "frozendict-2.3.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a31827dbe892172e1b000ffe22d577986c863e790cc7d51ba8c7fff4f44ac7cf"}, {file = "frozendict-2.3.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ee5fe2658a8ac9a57f748acaf563f6a47f80b8308cbf0a04fac0ba057d41f75"},
{file = "frozendict-2.3.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d73b4cca476f3d51f1b11264a41e0c3dbc20a53fb6b1d0878e01cc0b71fa16ce"}, {file = "frozendict-2.3.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23c4bb46e6b8246e1e7e49b5593c2bc09221db0d8f31f7c092be8dfb42b9e620"},
{file = "frozendict-2.3.6-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:1b4abc85e4788c2fe434851971a5fde4b079ed369965a21911e485dde97c08f4"}, {file = "frozendict-2.3.8-cp310-cp310-win_amd64.whl", hash = "sha256:c31abc8acea309b132dde441856829f6003a3d242da8b54bce4c0f2a3c8c63f0"},
{file = "frozendict-2.3.6-cp36-cp36m-win_amd64.whl", hash = "sha256:9c312b6dfe6a3b6b910637442989119d38bac417486c44a0ed402a80a4f5890e"}, {file = "frozendict-2.3.8-cp310-cp310-win_arm64.whl", hash = "sha256:9ea5520e85447ff8d4681e181941e482662817ccba921b7cb3f87922056d892a"},
{file = "frozendict-2.3.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a9def8ad754a405f0d982fe59e4f47bccd760ddcb472bfe0149f07410245f3d7"}, {file = "frozendict-2.3.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f83fed36497af9562ead5e9fb8443224ba2781786bd3b92b1087cb7d0ff20135"},
{file = "frozendict-2.3.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8d49faff6eb3f2678dff4d3c83fcb49ccebb13d8360389a0b8941d3e1ee8a93"}, {file = "frozendict-2.3.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e27c5c1d29d0eda7979253ec88abc239da1313b38f39f4b16984db3b3e482300"},
{file = "frozendict-2.3.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d310b7ea4fdfe70935d3e9193c8711689914b35300b7234137760c7cdbf257e1"}, {file = "frozendict-2.3.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c785de7f1a13f15963945f400656b18f057c2fc76c089dacf127a2bb188c03"},
{file = "frozendict-2.3.6-cp37-cp37m-win_amd64.whl", hash = "sha256:63745ca9a3ffb98f7c6a742afb10cd998e8fcd4f59b40c0c7c0e5795e2092cc8"}, {file = "frozendict-2.3.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8cf35ddd25513428ec152614def9696afb93ae5ec0eb54fa6aa6206eda77ac4c"},
{file = "frozendict-2.3.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd420cad2ec3223b3210c3b5a30fdc4842021ff037ae3c00e5ba6dd48731b753"}, {file = "frozendict-2.3.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ffc684773de7c88724788fa9787d0016fd75830412d58acbd9ed1a04762c675b"},
{file = "frozendict-2.3.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ea7c9fe1661a0f4135179bc056d5d90f197df5602532d224507c301b1cbda5e"}, {file = "frozendict-2.3.8-cp36-cp36m-win_amd64.whl", hash = "sha256:4c258aab9c8488338634f2ec670ef049dbf0ab0e7a2fa9bc2c7b5009cb614801"},
{file = "frozendict-2.3.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6e52018dc4a8ceaabe420fba4b3c003e8c0391d2efe5c164008ff791e61471d6"}, {file = "frozendict-2.3.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47fc26468407fdeb428cfc89495b7921419e670355c21b383765482fdf6c5c14"},
{file = "frozendict-2.3.6-cp38-cp38-win_amd64.whl", hash = "sha256:5b7bbbeabdafa31d7abfea68d8d532994767e56a137855f6dafdcbbc1dc924a8"}, {file = "frozendict-2.3.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ea638228692db2bf94bce40ea4b25f4077588497b516bd16576575560094bd9"},
{file = "frozendict-2.3.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:638d056ddff3e96f288176fcd18330ee68cc38f39ee67e10e43f4ee57552ed82"}, {file = "frozendict-2.3.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a75bf87e76c4386caecdbdd02a99e53ad43a6b5c38fb3d5a634a9fc9ce41462"},
{file = "frozendict-2.3.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b722fca999b1d14e277e095214d2296e355f6f17d7727c17a4aa95882738184a"}, {file = "frozendict-2.3.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ed5a6c5c7a0f57269577c2a338a6002949aea21a23b7b7d06da7e7dced8b605b"},
{file = "frozendict-2.3.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9c8314f5b8812cb7bc6001595e5cc521dffe220a8789d942a3f946660cc45672"}, {file = "frozendict-2.3.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d086440328a465dea9bef2dbad7548d75d1a0a0d21f43a08c03e1ec79ac5240e"},
{file = "frozendict-2.3.6-cp39-cp39-win_amd64.whl", hash = "sha256:d1e36e820fd2cae4e26935a4b82ccaa2eef8d347709d1c27e3b7608744f72f83"}, {file = "frozendict-2.3.8-cp37-cp37m-win_amd64.whl", hash = "sha256:0bc4767e2f83db5b701c787e22380296977368b0c57e485ca71b2eedfa11c4a3"},
{file = "frozendict-2.3.6.tar.gz", hash = "sha256:14e376fb0c8fe0b11b77872a84356dfa191b24a240be66bf5ec66d9b0d203bb8"}, {file = "frozendict-2.3.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:638cf363d3cbca31a341503cf2219eac52a5f5140449676fae3d9644cd3c5487"},
{file = "frozendict-2.3.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b2fd8ce36277919b36e3c834d2389f3cd7ac068ae730c312671dd4439a5dd65"},
{file = "frozendict-2.3.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3957d52f1906b0c85f641a1911d214255873f6408ab4e5ad657cc27a247fb145"},
{file = "frozendict-2.3.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72cfe08ab8ae524e54848fa90b22d02c1b1ecfb3064438696bcaa4b953f18772"},
{file = "frozendict-2.3.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4742e76c4111bd09198d3ab66cef94be8506212311338f9182d6ef5f5cb60493"},
{file = "frozendict-2.3.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:313ed8d9ba6bac35d7635cd9580ee5721a0fb016f4d2d20f0efa05dbecbdb1be"},
{file = "frozendict-2.3.8-cp38-cp38-win_amd64.whl", hash = "sha256:d3c6ce943946c2a61501c8cf116fff0892d11dd579877eb36e2aea2c27fddfef"},
{file = "frozendict-2.3.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0f573dc4861dd7ec9e055c8cceaf45355e894e749f621f199aab7b311ac4bdb"},
{file = "frozendict-2.3.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b3435e5f1ca5ae68a5e95e64b09d6d5c645cadd6b87569a0b3019dd248c8d00"},
{file = "frozendict-2.3.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:145afd033ebfade28416093335261b8ec1af5cccc593482309e7add062ec8668"},
{file = "frozendict-2.3.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da98427de26b5a2865727947480cbb53860089c4d195baa29c539da811cea617"},
{file = "frozendict-2.3.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5e82befa7c385a668d569cebbebbdf49cee6fea4083f08e869a1b08cfb640a9f"},
{file = "frozendict-2.3.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80abe81d36e889ceec665e06ec764a7638000fa3e7be09786ac4d3ddc64b76db"},
{file = "frozendict-2.3.8-cp39-cp39-win_amd64.whl", hash = "sha256:8ccc94ac781710db44e142e1a11ff9b31d02c032c01c6868d51fcbef73086225"},
{file = "frozendict-2.3.8-cp39-cp39-win_arm64.whl", hash = "sha256:e72dbc1bcc2203cef38d205f692396f5505921a5680f66aa9a7e8bb71fd38f28"},
{file = "frozendict-2.3.8-py311-none-any.whl", hash = "sha256:ba41a7ed019bd03b62d63ed3f8dea35b8243d1936f7c9ed4b5298ca45a01928e"},
{file = "frozendict-2.3.8.tar.gz", hash = "sha256:5526559eca8f1780a4ee5146896f59afc31435313560208dd394a3a5e537d3ff"},
] ]
[[package]] [[package]]
@ -1368,10 +1384,10 @@ aiohttp = "==3.8.4"
arrow = "==1.2.3" arrow = "==1.2.3"
backports-zoneinfo = {version = "==0.2.1", markers = "python_version < \"3.9\""} backports-zoneinfo = {version = "==0.2.1", markers = "python_version < \"3.9\""}
bleach = "==5.0.1" bleach = "==5.0.1"
boto3 = "==1.26.99" boto3 = "==1.26.108"
celery = "==5.2.7" celery = "==5.2.7"
channels = {version = "==4.0.0", extras = ["daphne"]} channels = {version = "==4.0.0", extras = ["daphne"]}
channels-redis = "==4.0.0" channels-redis = "==4.1.0"
click = "==8.1.3" click = "==8.1.3"
cryptography = "==38.0.4" cryptography = "==38.0.4"
dj-rest-auth = {version = "2.2.8", extras = ["with-social"]} dj-rest-auth = {version = "2.2.8", extras = ["with-social"]}
@ -1383,14 +1399,14 @@ django-cacheops = "==6.1"
django-cleanup = "==6.0.0" django-cleanup = "==6.0.0"
django-cors-headers = "==3.13.0" django-cors-headers = "==3.13.0"
django-dynamic-preferences = "==1.14.0" django-dynamic-preferences = "==1.14.0"
django-environ = "==0.9.0" django-environ = "==0.10.0"
django-filter = "==22.1" django-filter = "==22.1"
django-oauth-toolkit = "2.2.0" django-oauth-toolkit = "2.2.0"
django-redis = "==5.2.0" django-redis = "==5.2.0"
django-storages = "==1.13.2" django-storages = "==1.13.2"
django-versatileimagefield = "==2.2" django-versatileimagefield = "==2.2"
djangorestframework = "==3.14.0" djangorestframework = "==3.14.0"
drf-spectacular = "==0.25.1" drf-spectacular = "==0.26.1"
feedparser = "==6.0.10" feedparser = "==6.0.10"
gunicorn = "==20.1.0" gunicorn = "==20.1.0"
ipython = "==7.34.0" ipython = "==7.34.0"
@ -1406,7 +1422,7 @@ pydub = "==0.25.1"
pyld = "==2.0.3" pyld = "==2.0.3"
python-ldap = "==3.4.3" python-ldap = "==3.4.3"
python-magic = "==0.4.27" python-magic = "==0.4.27"
redis = "==4.4.2" redis = "==4.5.4"
requests = "==2.28.2" requests = "==2.28.2"
requests-http-message-signatures = "==0.3.1" requests-http-message-signatures = "==0.3.1"
sentry-sdk = "==1.19.1" sentry-sdk = "==1.19.1"
@ -1547,14 +1563,14 @@ files = [
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "6.1.0" version = "6.6.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "importlib_metadata-6.1.0-py3-none-any.whl", hash = "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09"}, {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
{file = "importlib_metadata-6.1.0.tar.gz", hash = "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20"}, {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
] ]
[package.dependencies] [package.dependencies]
@ -2238,14 +2254,14 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"]
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "23.0" version = "23.1"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
{file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
] ]
[[package]] [[package]]
@ -2454,30 +2470,30 @@ files = [
[[package]] [[package]]
name = "pyasn1" name = "pyasn1"
version = "0.4.8" version = "0.5.0"
description = "ASN.1 types and codecs" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [ files = [
{file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"},
{file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"},
] ]
[[package]] [[package]]
name = "pyasn1-modules" name = "pyasn1-modules"
version = "0.2.8" version = "0.3.0"
description = "A collection of ASN.1-based protocols modules." description = "A collection of ASN.1-based protocols modules"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [ files = [
{file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"},
{file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"},
] ]
[package.dependencies] [package.dependencies]
pyasn1 = ">=0.4.6,<0.5.0" pyasn1 = ">=0.4.6,<0.6.0"
[[package]] [[package]]
name = "pycparser" name = "pycparser"
@ -2505,14 +2521,14 @@ files = [
[[package]] [[package]]
name = "pygments" name = "pygments"
version = "2.14.0" version = "2.15.1"
description = "Pygments is a syntax highlighting package written in Python." description = "Pygments is a syntax highlighting package written in Python."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.7"
files = [ files = [
{file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
{file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
] ]
[package.extras] [package.extras]
@ -2736,18 +2752,18 @@ files = [
[[package]] [[package]]
name = "redis" name = "redis"
version = "4.4.2" version = "4.5.4"
description = "Python client for Redis database and key-value store" description = "Python client for Redis database and key-value store"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "redis-4.4.2-py3-none-any.whl", hash = "sha256:e6206448e2f8a432871d07d432c13ed6c2abcf6b74edb436c99752b1371be387"}, {file = "redis-4.5.4-py3-none-any.whl", hash = "sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2"},
{file = "redis-4.4.2.tar.gz", hash = "sha256:a010f6cb7378065040a02839c3f75c7e0fb37a87116fb4a95be82a95552776c7"}, {file = "redis-4.5.4.tar.gz", hash = "sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893"},
] ]
[package.dependencies] [package.dependencies]
async-timeout = ">=4.0.2" async-timeout = {version = ">=4.0.2", markers = "python_version <= \"3.11.2\""}
[package.extras] [package.extras]
hiredis = ["hiredis (>=1.0.0)"] hiredis = ["hiredis (>=1.0.0)"]
@ -2812,14 +2828,14 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
[[package]] [[package]]
name = "s3transfer" name = "s3transfer"
version = "0.6.0" version = "0.6.1"
description = "An Amazon S3 Transfer Manager" description = "An Amazon S3 Transfer Manager"
category = "main" category = "main"
optional = false optional = false
python-versions = ">= 3.7" python-versions = ">= 3.7"
files = [ files = [
{file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, {file = "s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346"},
{file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, {file = "s3transfer-0.6.1.tar.gz", hash = "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9"},
] ]
[package.dependencies] [package.dependencies]
@ -2897,14 +2913,14 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"]
[[package]] [[package]]
name = "setuptools" name = "setuptools"
version = "67.6.1" version = "67.7.2"
description = "Easily download, build, install, upgrade, and uninstall Python packages" description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "setuptools-67.6.1-py3-none-any.whl", hash = "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078"}, {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
{file = "setuptools-67.6.1.tar.gz", hash = "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a"}, {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
] ]
[package.extras] [package.extras]
@ -2995,6 +3011,25 @@ docs = ["sphinxcontrib-websupport"]
lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"]
test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"]
[[package]]
name = "sphinx-copybutton"
version = "0.5.2"
description = "Add a copy button to each of your code cells."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"},
{file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"},
]
[package.dependencies]
sphinx = ">=1.8"
[package.extras]
code-style = ["pre-commit (==2.12.1)"]
rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"]
[[package]] [[package]]
name = "sphinx-design" name = "sphinx-design"
version = "0.3.0" version = "0.3.0"
@ -3168,16 +3203,21 @@ test = ["pytest"]
[[package]] [[package]]
name = "sqlparse" name = "sqlparse"
version = "0.4.3" version = "0.4.4"
description = "A non-validating SQL parser." description = "A non-validating SQL parser."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.5"
files = [ files = [
{file = "sqlparse-0.4.3-py3-none-any.whl", hash = "sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34"}, {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
{file = "sqlparse-0.4.3.tar.gz", hash = "sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268"}, {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
] ]
[package.extras]
dev = ["build", "flake8"]
doc = ["sphinx"]
test = ["pytest", "pytest-cov"]
[[package]] [[package]]
name = "traitlets" name = "traitlets"
version = "5.9.0" version = "5.9.0"
@ -3533,82 +3573,82 @@ files = [
[[package]] [[package]]
name = "websockets" name = "websockets"
version = "11.0" version = "11.0.3"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "websockets-11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:269e3547877a6ca55f62acdf291b256b01bc3469535e892af36afd3e17de284a"}, {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"},
{file = "websockets-11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70a4e03d2416c1dad16ccfab97c975192337c6481b07167c90221f1926893e1e"}, {file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"},
{file = "websockets-11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4100dc8566ea3b9c0528dee73284be524ab053aebd77e3fc7439a90e0d57745b"}, {file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"},
{file = "websockets-11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8e0505c556b2b48078291b300d930f2fb8ba81d1e36379b637c060cfa561ae4"}, {file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"},
{file = "websockets-11.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d5bc68cec8269b4b52ab6d1d8690f56dba35f7bcb83a5487518406300f81cf1"}, {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"},
{file = "websockets-11.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:067ac1f6153fc5218afc4563491dcbdb7384895cfc588a0afee962ca77fe0b58"}, {file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"},
{file = "websockets-11.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:910c84c0cfe4f872905b6ebe1866c579582070331abcb7a58621935eca95c18a"}, {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"},
{file = "websockets-11.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df0f7769450ca67a53182f917910e2b0b6dd3f8268f88cbfe54ee6be96812889"}, {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"},
{file = "websockets-11.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fe23605f5c351773b6fb82fcf680549980d63e126fab5213ed875686c0cec25d"}, {file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"},
{file = "websockets-11.0-cp310-cp310-win32.whl", hash = "sha256:eb2e7cd654a05c36fccf726385c64a0e1027997d05ba0859f4d84c3d87db1623"}, {file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"},
{file = "websockets-11.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb26c333751a1e3805ecc416a85dcfa3657676b185acd515fd6992f0cea898ef"}, {file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"},
{file = "websockets-11.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4a939963bae1055f14976ef2cf53e797c1997f8835ca9cf23060afc3e7d6718"}, {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"},
{file = "websockets-11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d7fc189fb632f8b31af8a5b32105919662a1bbaac20912320482415b7fed9c96"}, {file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"},
{file = "websockets-11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6e3cfc890f1326c95fd7d4cc50f2bd496d3f014fb2da36b4525a10f226be565d"}, {file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"},
{file = "websockets-11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9093f4c72c23ed5e475970c6a37e77c4f3a8856223421b9eb405b9fb2170629f"}, {file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"},
{file = "websockets-11.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5c56547f97bc76293522ccfcfbdde12442420f1a2c0218ff45d733a0030046df"}, {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"},
{file = "websockets-11.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffb406b4449d4fa41ebc47faa3b9153a082f6fe0e4a0891f596a5ddb69fdeccd"}, {file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"},
{file = "websockets-11.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8fad76be2c5e36fb3620ad507ac8004e9f358f5c4a9a1b756dbe7918d58884a0"}, {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"},
{file = "websockets-11.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:17eb1988d320e2f1f20e4a3523f1068a0bb08318ab123962fc99fd90c90ab0d6"}, {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"},
{file = "websockets-11.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9873288db9c673a2ba9c0f7b59a130576c50fc75f3336a706fff686009c41631"}, {file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"},
{file = "websockets-11.0-cp311-cp311-win32.whl", hash = "sha256:cf4ef6343478bf63098d3060fe06baf54d9c011b4b1b05e65e7957091cc87ef4"}, {file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"},
{file = "websockets-11.0-cp311-cp311-win_amd64.whl", hash = "sha256:713cd5fc1fd40436495c90a259274e1a4a39416c65447a256434941ddaf2f424"}, {file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"},
{file = "websockets-11.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:649ddddcbafd318d427b843425c92b1c035660c32507645c472c77356226cf07"}, {file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"},
{file = "websockets-11.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:564c53d84b95da527e96778f2cc873ef186038924abee601f9e8f12ebda9ad46"}, {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"},
{file = "websockets-11.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d8df2db9801063e4093efe01458b1705c9f76382ad32617c005eeeb201a730"}, {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"},
{file = "websockets-11.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcd876ed166a82d250fcf012b729315489e9d653cb659c2e013c19daba2eb8f"}, {file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"},
{file = "websockets-11.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cb00963b49d343210ebbdbe69a35004fbecad73da2158e83d481cd2a6716cf19"}, {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"},
{file = "websockets-11.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d6f7c2f822e439f47f3492ee3e48c87c7d134d619a42c6dba1a318504501bfb"}, {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"},
{file = "websockets-11.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c4b2ae9c0f1acec5d2f8000eb496eebb9db19055a63716ee166cf0694b945982"}, {file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"},
{file = "websockets-11.0-cp37-cp37m-win32.whl", hash = "sha256:2b363e0f9b4247a0c7482e22c70ef39fb3259a14f7c0791c9200b93145f60b4b"}, {file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"},
{file = "websockets-11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3d372c3426f165a0a22be9250526b1cd12e3556e80b4b2afaa6fd6649c99b086"}, {file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"},
{file = "websockets-11.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7eb914d37e0574246c63b995f9ca8d7bb7c2f2d53a8d4e9b00200ea856aa43c4"}, {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"},
{file = "websockets-11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a8717a5f3a00cde308e2971064bd5fcb14e0cc08f8234b97f4eb92b505ea95d4"}, {file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"},
{file = "websockets-11.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a17151722349c4af221616cca2f28e79237738bfbc53e7155240e2a8a7cc02f4"}, {file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"},
{file = "websockets-11.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4b60686d9b2ba500847c045595eb5887f4cca7102b4615773b6f490aa611107"}, {file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"},
{file = "websockets-11.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eededf25ef6b838e650eeeb1511804b82e9ece566fe6cdc11aa909d2992dcdaf"}, {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"},
{file = "websockets-11.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7587f339f016f0e1b0b6f013e98c83e382c5929774f2b8234c1b2d3f01dd1339"}, {file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"},
{file = "websockets-11.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:26369646078e16e7364729ed3e3b1a4315ab1a22ca3c48b4e25dea48fcc1a881"}, {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"},
{file = "websockets-11.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:92f51fbe87381ff76c1791dd44d599152b400f1adfa8453613f1ff6857200ee7"}, {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"},
{file = "websockets-11.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b5bb04a77c326d727c0b986c37a76147916d79db95629267307d1be47788a020"}, {file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"},
{file = "websockets-11.0-cp38-cp38-win32.whl", hash = "sha256:50ac95111009178e58b9a25aa51702cdaad4ed843b98eb9b58d69b323ccb224e"}, {file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"},
{file = "websockets-11.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a4076cd6a3678def988668fc4b1779da598e1e5c9fa26319af5499f00c23e1c"}, {file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"},
{file = "websockets-11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:26559e8a385f71ce2a58f3bb1d005ddd3db7d3328ddbfbff1034f4039d46c4ec"}, {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"},
{file = "websockets-11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f10d283697dec8d91fa983eb8e217c9cac27bc1032057768129b89780009318e"}, {file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"},
{file = "websockets-11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f74efe229e078bf5595e207e9a7b135ff37a10858263ed86be66003c4c98d47b"}, {file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"},
{file = "websockets-11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f048c88bfcc5bf0e038630cfb970b2c479f913819fd9653db920eef3b105a2b1"}, {file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"},
{file = "websockets-11.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ceab6c1827fa14ad10c6b0806941d577b21d17012a3648787ac2b946182285b4"}, {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"},
{file = "websockets-11.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:817227e23897808c4bb621da7f57b1f83ee18345bdc44f5c9c1bbd3a094a73f6"}, {file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"},
{file = "websockets-11.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6fdcc17348d8697c1f88bba38680cca94131f2a9db727a61fe067284e1e59e8d"}, {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"},
{file = "websockets-11.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b21ad915b747075f29fe2fa5590111d98988d6730d2cd212acfe52bbe6a2545"}, {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"},
{file = "websockets-11.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9ae401ad881d5329062b9b2d8160f0b2a147430974f2a3f32e6cedadddc2d634"}, {file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"},
{file = "websockets-11.0-cp39-cp39-win32.whl", hash = "sha256:ee84660927293f449760badfe010e06409edb99d72e1910e2e404d2eeff6990f"}, {file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"},
{file = "websockets-11.0-cp39-cp39-win_amd64.whl", hash = "sha256:2b4e704a9dac1faf4994e63dceae9e2f504913ff0f865bd3e5a097cbd5874a8f"}, {file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"},
{file = "websockets-11.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c2d6429c9bcd70ed8126a1f9ca6069e4ab95c96a3cc141fc84ce02917f7b45ec"}, {file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"},
{file = "websockets-11.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff3f67567862a853af2c0db362ede8249be50c576cd9eaf380736c6fce840414"}, {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"},
{file = "websockets-11.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b86ce3d17bcc4b6556b2a2e1277beed74ff6b1de23f002f9763e9875e8ba361d"}, {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"},
{file = "websockets-11.0-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59c4b458cc09ea6470a5eee98b06ccaa84f2a193b92e337a879612614df0f8eb"}, {file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"},
{file = "websockets-11.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e5e21aeb350906dfcff321bfa6c60541a1d05cadb6d431ecf9d6376365be60d4"}, {file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"},
{file = "websockets-11.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8731189f6985b239a6c34a353c36b45cb3c9fed1c287fbcf7f61df9e4a7ac392"}, {file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"},
{file = "websockets-11.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3aa7660ae0d3a4e47517bb5a545b9a02ff7b9632a640f617e755990ef65f66"}, {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"},
{file = "websockets-11.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:027aabfd053715ce0f5f6fc5107e5093e05b3c94fa555fb65375aa09cb845a66"}, {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"},
{file = "websockets-11.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8c729aa179ef105f096cad12070aef230be9e2ae509eb47c3cdd9257213c14"}, {file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"},
{file = "websockets-11.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ff607c6e16409ac83f1ae59cc96167fead577bc652e8dff48f7458ce082372ff"}, {file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"},
{file = "websockets-11.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ca3d7c08f472c40f28bb9fb99610d28dc97137612ab5308f80dac7ce79f87fe1"}, {file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"},
{file = "websockets-11.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f179deef8288dd8ec227d644ba5b711609093b634008643561f6d9c74938c3c"}, {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"},
{file = "websockets-11.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:269d33f1573a31130da9afd63a2558f60131522d3fe86d0aa2d1612ad065d27c"}, {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"},
{file = "websockets-11.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb0b306c1180d0268341447982b415aca7c072c84b4a59688dbc1d7d2ec25df9"}, {file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"},
{file = "websockets-11.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6ae209f11e433575e17d5d6e61a2f77ceda53b4bce07df55af614aa1d618e2e7"}, {file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"},
{file = "websockets-11.0-py3-none-any.whl", hash = "sha256:6ebd971b9b2c0aaa2188c472016e4dad93108b3db425a33ad584bdc41b22026d"}, {file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"},
{file = "websockets-11.0.tar.gz", hash = "sha256:19d638549c470f5fd3b67b52b2a08f2edba5a04e05323a706937e35f5f19d056"}, {file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"},
] ]
[[package]] [[package]]
@ -3698,86 +3738,86 @@ files = [
[[package]] [[package]]
name = "yarl" name = "yarl"
version = "1.8.2" version = "1.9.2"
description = "Yet another URL library" description = "Yet another URL library"
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"}, {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"},
{file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"}, {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"},
{file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"}, {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"}, {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"}, {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"}, {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"}, {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"},
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"}, {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"}, {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"}, {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"}, {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"}, {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"},
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"}, {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"},
{file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"}, {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"},
{file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"}, {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"},
{file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"}, {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"},
{file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"}, {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"},
{file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"}, {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"}, {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"}, {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"}, {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"}, {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"},
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"}, {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"}, {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"}, {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"}, {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"}, {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"},
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"}, {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"},
{file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"}, {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"},
{file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"}, {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"},
{file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"}, {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"}, {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"}, {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"}, {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"}, {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"},
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"}, {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"}, {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"}, {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"}, {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"}, {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"},
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"}, {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"},
{file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"}, {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"},
{file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"}, {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"},
{file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"}, {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"},
{file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"}, {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"},
{file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"}, {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"}, {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"}, {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"}, {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"}, {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"},
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"}, {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"}, {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"}, {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"}, {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"}, {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"},
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"}, {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"},
{file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"}, {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"},
{file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"}, {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"},
{file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"}, {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"},
{file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"}, {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"},
{file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"}, {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"}, {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"}, {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"}, {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"}, {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"},
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"}, {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"}, {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"}, {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"}, {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"}, {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"},
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"}, {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"},
{file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"}, {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"},
{file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"}, {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"},
{file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"}, {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"},
] ]
[package.dependencies] [package.dependencies]
@ -3851,4 +3891,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "d83c7f834086b51767b0a447dcfec83d0531474d1119672db56275d1b8e31709" content-hash = "be4da5013e5048931e893faae2e12a0737dcc0bfabcbc116eb275737ab1e8d8b"

Wyświetl plik

@ -16,8 +16,9 @@ sphinxcontrib-mermaid = "0.7.1"
myst-parser = "==1.0.0" myst-parser = "==1.0.0"
django = "==3.2.18" django = "==3.2.18"
django-environ = "==0.9.0" django-environ = "==0.10.0"
funkwhale-api = {path = "../api"} funkwhale-api = {path = "../api"}
sphinx-copybutton = "==0.5.2"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]

Wyświetl plik

@ -50,3 +50,5 @@ developers/plugins.html, ../developer/plugins/index.html
developers/authentication.html, ../developer/api/authentication.html developers/authentication.html, ../developer/api/authentication.html
documentation/index.html, ../contributor/documentation.html documentation/index.html, ../contributor/documentation.html
translators.html, ../contributor/translation.html translators.html, ../contributor/translation.html
federation.html, ../developer/federation/index.html
upgrading.html, ../administrator/upgrade/index.html

Wyświetl plik

@ -11,7 +11,7 @@
"serve": "vite preview", "serve": "vite preview",
"test": "vitest run", "test": "vitest run",
"test:unit": "vitest run", "test:unit": "vitest run",
"lint": "eslint --ext .ts,.js,.vue,.json,.html src public/embed.html", "lint": "eslint --ext .ts,.js,.vue,.json,.html src test public/embed.html",
"lint:tsc": "vue-tsc --noEmit", "lint:tsc": "vue-tsc --noEmit",
"fix-fomantic-css": "scripts/fix-fomantic-css.sh", "fix-fomantic-css": "scripts/fix-fomantic-css.sh",
"postinstall": "yarn run fix-fomantic-css" "postinstall": "yarn run fix-fomantic-css"
@ -77,6 +77,7 @@
"@vue/eslint-config-typescript": "11.0.2", "@vue/eslint-config-typescript": "11.0.2",
"@vue/test-utils": "2.2.7", "@vue/test-utils": "2.2.7",
"@vue/tsconfig": "0.1.3", "@vue/tsconfig": "0.1.3",
"axios-mock-adapter": "1.21.4",
"eslint": "8.30.0", "eslint": "8.30.0",
"eslint-config-standard": "17.0.0", "eslint-config-standard": "17.0.0",
"eslint-plugin-html": "7.1.0", "eslint-plugin-html": "7.1.0",
@ -96,6 +97,7 @@
"vite": "4.0.4", "vite": "4.0.4",
"vite-plugin-pwa": "0.14.4", "vite-plugin-pwa": "0.14.4",
"vite-plugin-vue-inspector": "1.1.4", "vite-plugin-vue-inspector": "1.1.4",
"standardized-audio-context-mock": "9.6.18",
"vitest": "0.25.8", "vitest": "0.25.8",
"vue-tsc": "1.0.24", "vue-tsc": "1.0.24",
"workbox-core": "6.5.4", "workbox-core": "6.5.4",

Wyświetl plik

@ -105,16 +105,17 @@ const openMenu = () => {
// little magic to ensure the menu is always visible in the viewport // little magic to ensure the menu is always visible in the viewport
// By default, try to display it on the right if there is enough room // By default, try to display it on the right if there is enough room
const menu = dropdown.value.find('.menu') const menu = dropdown.value.find('.menu')
if (menu.hasClass('visible')) return
const viewportOffset = menu.get(0)?.getBoundingClientRect() ?? { right: 0, left: 0 } const viewportOffset = menu.get(0)?.getBoundingClientRect() ?? { right: 0, left: 0 }
const viewportWidth = document.documentElement.clientWidth const viewportWidth = document.documentElement.clientWidth
const rightOverflow = viewportOffset.right - viewportWidth const rightOverflow = viewportOffset.right - viewportWidth
const leftOverflow = -viewportOffset.left const leftOverflow = -viewportOffset.left
if (rightOverflow > 0) { menu.css({
menu.css({ cssText: `left: ${-rightOverflow - 5}px !important;` }) cssText: rightOverflow > 0
} else if (leftOverflow > 0) { ? `left: ${-rightOverflow - 5}px !important;`
menu.css({ cssText: `right: -${leftOverflow + 5}px !important;` }) : `right: ${-leftOverflow + 5}px !important;`
} })
} }
</script> </script>

Wyświetl plik

@ -257,10 +257,10 @@ const remove = async () => {
</template> </template>
<template v-if="totalTracks > 0"> <template v-if="totalTracks > 0">
<span v-if="isSerie"> <span v-if="isSerie">
{{ $t('components.library.AlbumBase.meta.episodes', {episode_count: totalTracks}) }} {{ $t('components.library.AlbumBase.meta.episodes', totalTracks) }}
</span> </span>
<span v-else> <span v-else>
{{ $t('components.library.AlbumBase.meta.tracks', {tracks_count: totalTracks}) }} {{ $t('components.library.AlbumBase.meta.tracks', totalTracks) }}
</span> </span>
<span class="middle middledot symbol" /> <span class="middle middledot symbol" />
</template> </template>

Wyświetl plik

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Notification, LibraryFollow } from '~/types' import type { Notification, LibraryFollow } from '~/types'
import { computed, ref, watchEffect } from 'vue' import { computed, ref, watchEffect, watch } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useStore } from '~/store' import { useStore } from '~/store'
@ -30,7 +30,7 @@ const notificationData = computed(() => {
if (activity.type === 'Follow') { if (activity.type === 'Follow') {
if (activity.object && activity.object.type === 'music.Library') { if (activity.object && activity.object.type === 'music.Library') {
const detailUrl = { name: 'content.libraries.detail', params: { id: activity.object.uuid } } const detailUrl = { name: 'library.detail.edit', params: { id: activity.object.uuid } }
if (activity.related_object?.approved === null) { if (activity.related_object?.approved === null) {
return { return {
@ -76,7 +76,7 @@ const notificationData = computed(() => {
}) })
const read = ref(false) const read = ref(false)
watchEffect(async () => { watch(read, async () => {
await axios.patch(`federation/inbox/${item.value.id}/`, { is_read: read.value }) await axios.patch(`federation/inbox/${item.value.id}/`, { is_read: read.value })
item.value.is_read = read.value item.value.is_read = read.value
@ -92,11 +92,13 @@ const handleAction = (handler?: () => void) => {
const approveLibraryFollow = async (follow: LibraryFollow) => { const approveLibraryFollow = async (follow: LibraryFollow) => {
await axios.post(`federation/follows/library/${follow.uuid}/accept/`) await axios.post(`federation/follows/library/${follow.uuid}/accept/`)
follow.approved = true follow.approved = true
item.value.is_read = true
} }
const rejectLibraryFollow = async (follow: LibraryFollow) => { const rejectLibraryFollow = async (follow: LibraryFollow) => {
await axios.post(`federation/follows/library/${follow.uuid}/reject/`) await axios.post(`federation/follows/library/${follow.uuid}/reject/`)
follow.approved = false follow.approved = false
item.value.is_read = true
} }
</script> </script>

Wyświetl plik

@ -92,7 +92,7 @@ const queue = computed<QueueTrack[]>(() => {
}) })
// Current Index // Current Index
export const currentIndex = useClamp(useStorage('queue:index', 0), 0, () => tracks.value.length - 1) export const currentIndex = useClamp(useStorage('queue:index', 0), 0, () => Math.max(0, tracks.value.length - 1))
export const currentTrack = computed(() => queue.value[currentIndex.value]) export const currentTrack = computed(() => queue.value[currentIndex.value])
// Use Queue // Use Queue
@ -133,10 +133,10 @@ export const useQueue = createGlobalState(() => {
const isTrack = (track: Track | boolean): track is Track => typeof track !== 'boolean' const isTrack = (track: Track | boolean): track is Track => typeof track !== 'boolean'
// Adding tracks // Adding tracks
async function enqueueAt (index: number, ...newTracks: Track[]): Promise<void> async function enqueueAt(index: number, ...newTracks: Track[]): Promise<void>
// NOTE: Only last boolean of newTracks is considered as skipFetch // NOTE: Only last boolean of newTracks is considered as skipFetch
async function enqueueAt (index: number, ...newTracks: (Track | boolean)[]) : Promise<void> async function enqueueAt(index: number, ...newTracks: (Track | boolean)[]): Promise<void>
async function enqueueAt (index: number, ...newTracks: (Track | boolean)[]) : Promise<void> { async function enqueueAt (index: number, ...newTracks: (Track | boolean)[]): Promise<void> {
let skipFetch = false let skipFetch = false
if (!isTrack(newTracks[newTracks.length - 1])) { if (!isTrack(newTracks[newTracks.length - 1])) {
skipFetch = newTracks.pop() as boolean skipFetch = newTracks.pop() as boolean
@ -161,9 +161,9 @@ export const useQueue = createGlobalState(() => {
} }
} }
async function enqueue (...newTracks: Track[]): Promise<void> async function enqueue(...newTracks: Track[]): Promise<void>
// NOTE: Only last boolean of newTracks is considered as skipFetch // NOTE: Only last boolean of newTracks is considered as skipFetch
async function enqueue (...newTracks: (Track | boolean)[]): Promise<void> async function enqueue(...newTracks: (Track | boolean)[]): Promise<void>
async function enqueue (...newTracks: (Track | boolean)[]): Promise<void> { async function enqueue (...newTracks: (Track | boolean)[]): Promise<void> {
return enqueueAt(tracks.value.length, ...newTracks) return enqueueAt(tracks.value.length, ...newTracks)
} }
@ -257,6 +257,13 @@ export const useQueue = createGlobalState(() => {
list.value.splice(to, 0, id) list.value.splice(to, 0, id)
const current = currentIndex.value const current = currentIndex.value
// NOTE: We're batching the changes to avoid reactivity issues related to the currentIndex being clamped at list length
const listCopy = list.value.slice()
const [id] = listCopy.splice(from, 1)
listCopy.splice(to, 0, id)
list.value = listCopy
if (current === from) { if (current === from) {
currentIndex.value = to currentIndex.value = to
return return
@ -327,6 +334,8 @@ export const useQueue = createGlobalState(() => {
const lastTracks = [...tracks.value] const lastTracks = [...tracks.value]
tracks.value.length = 0 tracks.value.length = 0
await delMany(lastTracks) await delMany(lastTracks)
currentIndex.value = 0
} }
// Radio queue populating // Radio queue populating
@ -365,7 +374,7 @@ export const useQueue = createGlobalState(() => {
const radios = JSON.parse(oldRadios) const radios = JSON.parse(oldRadios)
store.commit('radios/current', radios.radios.current) store.commit('radios/current', radios.radios.current)
store.commit('radios/running', radios.radios.running) store.commit('radios/running', radios.radios.running)
} catch (err) {} } catch (err) { }
currentIndex.value = index currentIndex.value = index
delete localStorage.queue delete localStorage.queue
@ -374,7 +383,7 @@ export const useQueue = createGlobalState(() => {
if (localStorage.player) { if (localStorage.player) {
try { try {
const { player: { looping: loopingMode, volume } } = JSON.parse(localStorage.player) as { player: { looping: LoopingMode, volume: number }} const { player: { looping: loopingMode, volume } } = JSON.parse(localStorage.player) as { player: { looping: LoopingMode, volume: number } }
looping.value = loopingMode ?? 0 looping.value = loopingMode ?? 0
setGain(volume ?? 0.7) setGain(volume ?? 0.7)
delete localStorage.player delete localStorage.player

Wyświetl plik

@ -172,7 +172,7 @@
"next": "Další skladba", "next": "Další skladba",
"pause": "Pozastavit", "pause": "Pozastavit",
"play": "Hrát", "play": "Hrát",
"populatingRadio": "Načítání stopy rádia...", "populatingRadio": "Načítání skladby rádia...",
"previous": "Předchozí skladba", "previous": "Předchozí skladba",
"queue": "Fronta", "queue": "Fronta",
"remove": "Odstranit", "remove": "Odstranit",
@ -183,9 +183,11 @@
}, },
"message": { "message": {
"automaticPlay": "Další skladba se automaticky spustí za několik sekund…", "automaticPlay": "Další skladba se automaticky spustí za několik sekund…",
"radio": "Nové skladby se přidají automaticky." "radio": "Nové skladby se přidají automaticky.",
"webglUnsupported": "Váš prohlížeč nejspíš nepodporuje WebGL2."
}, },
"meta": { "meta": {
"end": "Konec",
"queuePosition": "Skladba { index } z { length }", "queuePosition": "Skladba { index } z { length }",
"startTime": "00:00", "startTime": "00:00",
"unknownAlbum": "Neznámé Album", "unknownAlbum": "Neznámé Album",
@ -1032,7 +1034,7 @@
"series": "Série" "series": "Série"
}, },
"meta": { "meta": {
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | {n} skladba | {n} skladeb"
}, },
"option": { "option": {
"none": "Žádné" "none": "Žádné"
@ -1095,7 +1097,7 @@
"UploadMetadataForm": { "UploadMetadataForm": {
"label": { "label": {
"description": "Popis", "description": "Popis",
"image": "Data stopy", "image": "Přebal skladby",
"position": "Pozice", "position": "Pozice",
"tags": "Tagy", "tags": "Tagy",
"title": "Název" "title": "Název"
@ -1429,7 +1431,7 @@
}, },
"meta": { "meta": {
"episodes": "{ n } interpret | { n } interpreti", "episodes": "{ n } interpret | { n } interpreti",
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | {n} skladba | {n} skladeb"
}, },
"title": "Album" "title": "Album"
}, },
@ -1440,7 +1442,7 @@
"header": { "header": {
"episodes": "Epizody", "episodes": "Epizody",
"libraries": "Knihovny uživatele", "libraries": "Knihovny uživatele",
"tracks": "Stopy" "tracks": "Skladby"
}, },
"meta": { "meta": {
"volume": "Hlasitost { number }" "volume": "Hlasitost { number }"
@ -1553,7 +1555,7 @@
"header": { "header": {
"album": "Alba tohoto interpreta", "album": "Alba tohoto interpreta",
"library": "Knihovny uživatele", "library": "Knihovny uživatele",
"track": "Stopy od tohoto interpreta" "track": "Nové skladby od tohoto interpreta"
}, },
"link": { "link": {
"filter": "Přehled filtrů" "filter": "Přehled filtrů"
@ -1866,7 +1868,7 @@
"TagDetail": { "TagDetail": {
"header": { "header": {
"channels": "Kanály", "channels": "Kanály",
"tracks": "Stopy" "tracks": "Skladby"
}, },
"link": { "link": {
"albums": "Alba", "albums": "Alba",
@ -1953,7 +1955,7 @@
"TrackEdit": { "TrackEdit": {
"header": { "header": {
"edit": "Upravit tuto stopu", "edit": "Upravit tuto stopu",
"suggest": "Navrhněte úpravu u této stopy" "suggest": "Navrhnout úpravu této skladby"
}, },
"message": { "message": {
"remote": " Tento objekt je spravován jiným serverem, nemůžete ho upravovat." "remote": " Tento objekt je spravován jiným serverem, nemůžete ho upravovat."
@ -1971,7 +1973,7 @@
"header": { "header": {
"builder": "Výroba rádia", "builder": "Výroba rádia",
"created": "Rádio vytvořeno", "created": "Rádio vytvořeno",
"matches": "{ n } stopa odpovídá zadaným filtrům | { n } stopy odpovídají zadaným filtrům", "matches": "0 stop odpovídajících zadaným filtrům | { n } skladba odpovídající zadaným filtrům | { n } skladeb odpovídajích zadaným filtrům",
"updated": "Rádio aktualizováno" "updated": "Rádio aktualizováno"
}, },
"label": { "label": {
@ -2004,7 +2006,7 @@
"cancelButton": "Zrušit", "cancelButton": "Zrušit",
"excludeLabel": "Vyloučit", "excludeLabel": "Vyloučit",
"matchingTracks": "0 skladeb odpovídajících filtru | {n} skladba odpovídající filtru | {n} skladeb odpovídajících filtru", "matchingTracks": "0 skladeb odpovídajících filtru | {n} skladba odpovídající filtru | {n} skladeb odpovídajících filtru",
"matchingTracksModalHeader": "Stopy které odpovídají filtru", "matchingTracksModalHeader": "Skladby odpovídající filtru",
"removeButton": "Odstranit" "removeButton": "Odstranit"
} }
} }
@ -2044,7 +2046,7 @@
"creationDate": "Datum vytvoření", "creationDate": "Datum vytvoření",
"domain": "Doména", "domain": "Doména",
"name": "Název", "name": "Název",
"tracks": "Stopy" "tracks": "Skladby"
} }
} }
} }
@ -2087,7 +2089,7 @@
"domain": "Doména", "domain": "Doména",
"name": "Název", "name": "Název",
"releaseDate": "Datum vydání", "releaseDate": "Datum vydání",
"tracks": "Stopy" "tracks": "Skladby"
} }
} }
} }
@ -2130,7 +2132,7 @@
"creationDate": "Datum vytvoření", "creationDate": "Datum vytvoření",
"domain": "Doména", "domain": "Doména",
"name": "Název", "name": "Název",
"tracks": "Stopy" "tracks": "Skladby"
} }
} }
} }
@ -2237,7 +2239,7 @@
"artists": "Interpreti", "artists": "Interpreti",
"creationDate": "Datum vytvoření", "creationDate": "Datum vytvoření",
"name": "Název", "name": "Název",
"tracks": "Stopy" "tracks": "Skladby"
} }
} }
} }
@ -2745,7 +2747,7 @@
}, },
"warning": { "warning": {
"createFilter": { "createFilter": {
"listIntro": "Neuvidíte stopy, alba a uživatelskou aktivitu spojenou s tímto interpretem:", "listIntro": "Neuvidíte skladby, alba a uživatelskou aktivitu spojenou s tímto interpretem:",
"listItem1": "V oblíbených a historii poslechu jiných uživatelů", "listItem1": "V oblíbených a historii poslechu jiných uživatelů",
"listItem2": "Ve widgetu \"Poslední přidané\"", "listItem2": "Ve widgetu \"Poslední přidané\"",
"listItem3": "Ve výpisu interpretů a alb", "listItem3": "Ve výpisu interpretů a alb",
@ -2809,15 +2811,15 @@
"playlists": { "playlists": {
"Card": { "Card": {
"meta": { "meta": {
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | {n} skladba | {n} skladeb"
} }
}, },
"Editor": { "Editor": {
"button": { "button": {
"addDuplicate": "Přesto přidat", "addDuplicate": "Přesto přidat",
"clear": "Vyčistit playlist", "clear": "Vyčistit playlist",
"copy": "Kopírovat stopy ve frontě do playlistu", "copy": "Kopírovat skladby ve frontě do playlistu",
"insertFromQueue": "Vložit z fronty ({ n } stopa) | Vložit z fronty ({ n } stopy)" "insertFromQueue": "Vložit z fronty ({ n } skladba) | Vložit z fronty ({ n } skladeb"
}, },
"error": { "error": {
"sync": "Došlo k chybě při ukládání změn" "sync": "Došlo k chybě při ukládání změn"
@ -2837,13 +2839,13 @@
"modal": { "modal": {
"clearPlaylist": { "clearPlaylist": {
"content": { "content": {
"warning": "Odstraní nevratně všechny stopy z tohoto playlistu." "warning": "Odstraní nevratně všechny skladby z tohoto playlistu."
}, },
"header": "Přejete si vyprázdnit seznam skladeb \"{ playlist }\"?" "header": "Přejete si vyprázdnit seznam skladeb \"{ playlist }\"?"
} }
}, },
"warning": { "warning": {
"duplicate": "Některé stopy ve frontě se v tomto playlistu již nacházejí:" "duplicate": "Některé skladby ve frontě se v tomto playlistu již nacházejí:"
} }
}, },
"Form": { "Form": {
@ -2878,17 +2880,17 @@
}, },
"header": { "header": {
"addFailure": "Stopu nelze přidat do playlistu", "addFailure": "Stopu nelze přidat do playlistu",
"addToPlaylist": "Přidat do seznamu skladeb", "addToPlaylist": "Přidat do seznamu skladeb",
"available": "Dostupné playlisty", "available": "Dostupné playlisty",
"manage": "Spravovat playlisty", "manage": "Spravovat playlisty",
"noResults": "Stopy které odpovídají filtru", "noResults": "Žádné výsledky odpovídající filtru",
"track": "{title}, od interpreta {artist}" "track": "{title}, od interpreta {artist}"
}, },
"label": { "label": {
"filter": "Název filtru" "filter": "Název filtru"
}, },
"placeholder": { "placeholder": {
"filterPlaylist": "Zadejte název seznamu skladeb" "filterPlaylist": "Zadejte název seznamu skladeb"
}, },
"table": { "table": {
"edit": { "edit": {
@ -2896,7 +2898,7 @@
"edit": "Upravit", "edit": "Upravit",
"lastModification": "Poslední změna", "lastModification": "Poslední změna",
"name": "Název", "name": "Název",
"tracks": "Stopy" "tracks": "Skladby"
} }
} }
}, },
@ -2954,7 +2956,7 @@
"composables": { "composables": {
"audio": { "audio": {
"usePlayOptions": { "usePlayOptions": {
"addToQueueMessage": "{ n } stopa byla přidána do fronty | { n } stopy byly přidány do fronty" "addToQueueMessage": "{n} skladeb bylo přidáno do fronty | { n } skladba byla přidána do fronty | { n } skladeb bylo přidány do fronty"
} }
}, },
"locale": { "locale": {
@ -3043,7 +3045,7 @@
"receivedMessages": "Přijaté zprávy", "receivedMessages": "Přijaté zprávy",
"releaseDate": "Datum vydání", "releaseDate": "Datum vydání",
"size": "Velikost", "size": "Velikost",
"trackTitle": "Název stopy", "trackTitle": "Název skladby",
"uploads": "Nahrané soubory", "uploads": "Nahrané soubory",
"username": "Uživatelské jméno", "username": "Uživatelské jméno",
"users": "Uživatelé" "users": "Uživatelé"
@ -3291,7 +3293,7 @@
"radios": "Rádia", "radios": "Rádia",
"series": "Série", "series": "Série",
"tags": "Tagy", "tags": "Tagy",
"tracks": "Stopy" "tracks": "Skladby"
} }
}, },
"admin": { "admin": {
@ -3324,7 +3326,7 @@
"table": { "table": {
"activity": { "activity": {
"edits": "Úpravy", "edits": "Úpravy",
"favorited": "Oblíbené stopy", "favorited": "Oblíbené skladby",
"firstSeen": "Prvně viděno", "firstSeen": "Prvně viděno",
"linkedReports": "Odkazy na hlášení", "linkedReports": "Odkazy na hlášení",
"listenings": "Poslechy", "listenings": "Poslechy",
@ -3334,7 +3336,7 @@
"albums": "Alba", "albums": "Alba",
"cachedSize": "Velikost v cache", "cachedSize": "Velikost v cache",
"totalSize": "Celková velikost", "totalSize": "Celková velikost",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory" "uploads": "Nahrané soubory"
}, },
"channelData": { "channelData": {
@ -3360,7 +3362,7 @@
"invitations": "Pozvánky", "invitations": "Pozvánky",
"libraries": "Knihovny", "libraries": "Knihovny",
"tags": "Tagy", "tags": "Tagy",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory", "uploads": "Nahrané soubory",
"users": "Uživatelé" "users": "Uživatelé"
} }
@ -3405,7 +3407,7 @@
"musicbrainz": "Otevřít na MusicBrainz", "musicbrainz": "Otevřít na MusicBrainz",
"remoteProfile": "Otevřít vzdálený profil", "remoteProfile": "Otevřít vzdálený profil",
"reports": "Odkazy na hlášení", "reports": "Odkazy na hlášení",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory" "uploads": "Nahrané soubory"
}, },
"modal": { "modal": {
@ -3418,7 +3420,7 @@
}, },
"table": { "table": {
"activity": { "activity": {
"favorited": "Oblíbené stopy", "favorited": "Oblíbené skladby",
"firstSeen": "Prvně viděno", "firstSeen": "Prvně viděno",
"listenings": "Poslechy", "listenings": "Poslechy",
"playlists": "Playlisty" "playlists": "Playlisty"
@ -3459,7 +3461,7 @@
"musicbrainz": "Otevřít na MusicBrainz", "musicbrainz": "Otevřít na MusicBrainz",
"remoteProfile": "Otevřít vzdálený profil", "remoteProfile": "Otevřít vzdálený profil",
"reports": "Odkazy na hlášení", "reports": "Odkazy na hlášení",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory" "uploads": "Nahrané soubory"
}, },
"modal": { "modal": {
@ -3472,7 +3474,7 @@
}, },
"table": { "table": {
"activity": { "activity": {
"favorited": "Oblíbené stopy", "favorited": "Oblíbené skladby",
"firstSeen": "Prvně viděno", "firstSeen": "Prvně viděno",
"listenings": "Poslechy", "listenings": "Poslechy",
"playlists": "Playlisty" "playlists": "Playlisty"
@ -3498,7 +3500,7 @@
"edits": "Úpravy", "edits": "Úpravy",
"libraries": "Knihovny", "libraries": "Knihovny",
"tags": "Tagy", "tags": "Tagy",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory" "uploads": "Nahrané soubory"
}, },
"menu": { "menu": {
@ -3530,7 +3532,7 @@
"domain": "Doména", "domain": "Doména",
"remoteProfile": "Otevřít vzdálený profil", "remoteProfile": "Otevřít vzdálený profil",
"reports": "Odkazy na hlášení", "reports": "Odkazy na hlášení",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory", "uploads": "Nahrané soubory",
"visibility": "Viditelnost" "visibility": "Viditelnost"
}, },
@ -3574,7 +3576,7 @@
"artists": "Interpreti", "artists": "Interpreti",
"django": "Zobrazit v administraci Django", "django": "Zobrazit v administraci Django",
"localProfile": "Otevřít místní profil", "localProfile": "Otevřít místní profil",
"tracks": "Stopy" "tracks": "Skladby"
}, },
"modal": { "modal": {
"delete": { "delete": {
@ -3602,7 +3604,7 @@
"header": { "header": {
"activity": "Aktivita", "activity": "Aktivita",
"local": "Místní", "local": "Místní",
"trackData": "Data stopy" "trackData": "Data skladby"
}, },
"link": { "link": {
"album": "Album", "album": "Album",
@ -3628,7 +3630,7 @@
}, },
"table": { "table": {
"activity": { "activity": {
"favorited": "Oblíbené stopy", "favorited": "Oblíbené skladby",
"firstSeen": "Prvně viděno", "firstSeen": "Prvně viděno",
"listenings": "Poslechy", "listenings": "Poslechy",
"playlists": "Playlisty" "playlists": "Playlisty"
@ -3728,7 +3730,7 @@
"openProfile": "Otevřít profil", "openProfile": "Otevřít profil",
"remoteProfile": "Otevřít vzdálený profil", "remoteProfile": "Otevřít vzdálený profil",
"requests": "Požádat o heslo", "requests": "Požádat o heslo",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory" "uploads": "Nahrané soubory"
}, },
"notApplicable": "N/A", "notApplicable": "N/A",
@ -3798,7 +3800,7 @@
"policy": "Zásady moderování vám pomáhají řídit interakci mezi vaší instancí a danou doménou nebo účtem" "policy": "Zásady moderování vám pomáhají řídit interakci mezi vaší instancí a danou doménou nebo účtem"
}, },
"header": { "header": {
"activePolicy": "Na tuto doménu jsou aplikována specifická pravidla moderace", "activePolicy": "Tato doména podléhá specifickým moderačním pravidlům",
"activity": "Aktivita", "activity": "Aktivita",
"audioContent": "Obsah audia", "audioContent": "Obsah audia",
"instanceData": "Data instance", "instanceData": "Data instance",
@ -3811,15 +3813,15 @@
"django": "Zobrazit v administraci Django", "django": "Zobrazit v administraci Django",
"knownAccounts": "Známé účty", "knownAccounts": "Známé účty",
"libraries": "Knihovny", "libraries": "Knihovny",
"tracks": "Stopy", "tracks": "Skladby",
"uploads": "Nahrané soubory", "uploads": "Nahrané soubory",
"website": "Otevřít web" "website": "Otevřít web"
}, },
"notApplicable": "N/A", "notApplicable": "N/A",
"table": { "table": {
"activity": { "activity": {
"emittedFollows": "Vydaná sledování knihovny", "emittedFollows": "Vyslaná sledování knihovny",
"emittedMessages": "Vydané zprávy", "emittedMessages": "Vyslané zprávy",
"firstSeen": "Prvně viděno", "firstSeen": "Prvně viděno",
"receivedFollows": "Přijatá sledování knihovny" "receivedFollows": "Přijatá sledování knihovny"
}, },
@ -3894,7 +3896,7 @@
}, },
"RequestsList": { "RequestsList": {
"header": { "header": {
"userRequests": "Uživatelské příručky" "userRequests": "Žádosti o registraci"
}, },
"label": { "label": {
"search": "Hledat", "search": "Hledat",
@ -3905,7 +3907,7 @@
"all": "Vše", "all": "Vše",
"approved": "Schváleno", "approved": "Schváleno",
"pending": "Čeká", "pending": "Čeká",
"refused": "Pozastaveno" "refused": "Odmítnuto"
} }
}, },
"ordering": { "ordering": {
@ -3917,9 +3919,9 @@
"label": "Řazení" "label": "Řazení"
}, },
"placeholder": { "placeholder": {
"search": "Hledat pomocí uživatelského jména" "search": "Hledat podle uživatelského jména"
}, },
"title": "Uživatelské příručky" "title": "Žádosti o registraci"
} }
}, },
"users": { "users": {
@ -3938,13 +3940,13 @@
"auth": { "auth": {
"Callback": { "Callback": {
"header": { "header": {
"loggingIn": "Načítání knihoven…" "loggingIn": "Přihlašování…"
} }
}, },
"EmailConfirm": { "EmailConfirm": {
"header": { "header": {
"failure": "Nepovedlo se ověřit vaší emailovou adresu", "failure": "Nepovedlo se ověřit vaši e-mailovou adresu",
"success": "Emailová adresa potvrzena" "success": "E-mailová adresa potvrzena"
}, },
"label": { "label": {
"confirmationCode": "Potvrzovací kód" "confirmationCode": "Potvrzovací kód"
@ -3956,24 +3958,24 @@
"message": { "message": {
"success": "Nyní můžete službu využívat bez omezení" "success": "Nyní můžete službu využívat bez omezení"
}, },
"title": "Potvrďte svou emailovou adresu" "title": "Potvrďte svou e-mailovou adresu"
}, },
"Login": { "Login": {
"header": { "header": {
"login": "Přihlásit k vašemu Funkwhale účtu" "login": "Přihlásit se k vašemu Funkwhale účtu"
}, },
"title": "Přihlásit se" "title": "Přihlásit se"
}, },
"PasswordReset": { "PasswordReset": {
"button": { "button": {
"requestReset": "Požádat o resetování hesla" "requestReset": "Požádat o obnovení hesla"
}, },
"header": { "header": {
"failure": "Chyba při žádosti o reset hesla", "failure": "Chyba při žádosti o obnovení hesla",
"reset": "Resetovat heslo" "reset": "Obnovit heslo"
}, },
"help": { "help": {
"form": "Použijte tento formulář pro žádost o reset hesla. Na zadanou adresu bude odeslán email s instrukcemi pro změnu vašeho hesla." "form": "Použijte tento formulář pro požádání o obnovení hesla. Na zadanou adresu bude odeslán e-mail s instrukcemi pro obnovu vašeho hesla."
}, },
"label": { "label": {
"email": "Emailová adresa účtu" "email": "Emailová adresa účtu"
@ -3982,9 +3984,9 @@
"back": "Zpět na přihlášení" "back": "Zpět na přihlášení"
}, },
"placeholder": { "placeholder": {
"email": "Zadejte emailovou adresu spojenou s vaším účtem" "email": "Zadejte e-mailovou adresu spojenou s vaším účtem"
}, },
"title": "Resetovat heslo" "title": "Obnovit heslo"
}, },
"PasswordResetConfirm": { "PasswordResetConfirm": {
"button": { "button": {
@ -4002,17 +4004,17 @@
"login": "Pokračovat k přihlášení" "login": "Pokračovat k přihlášení"
}, },
"message": { "message": {
"requestSent": "Pokud je emailová adresa zadaná v předchozím kroku validní a náleží k uživatelskému účtu, obdržíte během několika minut email s pokyny pro reset hesla.", "requestSent": "Pokud je e-mailová adresa zadaná v předchozím kroku platná a náleží nějakému uživatelskému účtu, obdržíte během několika minut e-mail s pokyny pro obnovení hesla.",
"success": "Vaše heslo bylo úspěšně změněno." "success": "Vaše heslo bylo úspěšně změněno."
}, },
"title": "Změňte své heslo" "title": "Změna hesla"
}, },
"Plugins": { "Plugins": {
"title": "Spravovat playlisty" "title": "Spravovat pluginy"
}, },
"ProfileActivity": { "ProfileActivity": {
"header": { "header": {
"playlists": "Playlisty", "playlists": "Seznamy skladeb",
"recentlyFavorited": "Poslední oblíbené", "recentlyFavorited": "Poslední oblíbené",
"recentlyListened": "Poslední poslechnuté" "recentlyListened": "Poslední poslechnuté"
} }
@ -4023,33 +4025,33 @@
}, },
"link": { "link": {
"activity": "Aktivita", "activity": "Aktivita",
"domainView": "Členem od { date }", "domainView": "Zobrazit na {domain}",
"moderation": "Otevřít v rozhraní pro moderaci", "moderation": "Otevřít v rozhraní pro moderaci",
"overview": "Náhled" "overview": "Náhled"
}, },
"title": "Profil { username }" "title": "Profil uživatele { username }"
}, },
"ProfileOverview": { "ProfileOverview": {
"button": { "button": {
"cancel": "Zrušit", "cancel": "Zrušit",
"createChannel": "Vytvořit novou knihovnu", "createChannel": "Vytvořit kanál",
"next": "Další stopa", "next": "Další krok",
"previous": "Předchozí stopa" "previous": "Předchozí krok"
}, },
"header": { "header": {
"channels": "Kanály", "channels": "Kanály",
"libraries": "Knihovny uživatele", "libraries": "Knihovny uživatele",
"sharedLibraries": "Toto album se vyskytuje v následujících knihovnách" "sharedLibraries": "Tento uživatel sdílel následující knihovny"
}, },
"link": { "link": {
"addNew": "Přidat obsah" "addNew": "Přidat nový"
}, },
"modal": { "modal": {
"createChannel": { "createChannel": {
"artist": { "artist": {
"header": "Jméno interpreta" "header": "Kanál interpreta"
}, },
"header": "Vytvořit novou knihovnu", "header": "Vytvořit kanál",
"podcast": { "podcast": {
"header": "Podcastový kanál" "header": "Podcastový kanál"
} }
@ -4072,36 +4074,36 @@
"edit": "Upravit…", "edit": "Upravit…",
"embed": "Vložit", "embed": "Vložit",
"play": "Přehrát", "play": "Přehrát",
"updateChannel": "Aktualizovat aplikaci", "updateChannel": "Aktualizovat kanál",
"upload": "Nahrát" "upload": "Nahrát"
}, },
"header": { "header": {
"artistChannel": "Jméno interpreta", "artistChannel": "Kanál interpreta",
"podcastChannel": "Podcastový kanál" "podcastChannel": "Podcastový kanál"
}, },
"link": { "link": {
"channelEpisodes": "Všechny díly", "channelEpisodes": "Všechny díly",
"channelOverview": "hled", "channelOverview": "Přehled",
"channelTracks": "Stopy", "channelTracks": "Skladby",
"domainView": "Členem od { date }", "domainView": "Zobrazit na {domain}",
"mirrored": "Zrcadleno z {domain}", "mirrored": "Zrcadleno z {domain}",
"moderation": "Otevřít v rozhraní pro moderaci" "moderation": "Otevřít v rozhraní pro moderaci"
}, },
"meta": { "meta": {
"episodes": "{ n } interpret | { n } interpreti", "episodes": "Žádné díly | {n} díl | {n} dílů",
"listenings": "{ n } poslech | { n } poslechy", "listenings": "Neposlechnuto | { n } poslech | { n } poslechů",
"subscribers": "{ n } oblíbená | { n } oblíbené", "subscribers": "Žádní odběratelé | {n} odběratel | {n} odběratelů",
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | {n} skladba | {n} skladeb"
}, },
"modal": { "modal": {
"delete": { "delete": {
"content": { "content": {
"warning": "Knihovna bude odstraněna, společně se souvisejícími nahranými soubory a sledováními. Tato akce je nevratná." "warning": "Kanál bude odstraněn, společně se souvisejícími nahranými soubory a sledováními. Tato akce je nevratná."
}, },
"header": "Odstranit tuto poznámku?" "header": "Odstranit tento kanál?"
}, },
"embed": { "embed": {
"header": "Vložit díla tohoto interpreta do webové stránky" "header": "Vložit díla tohoto interpreta na vaše webové stránky"
}, },
"subscribe": { "subscribe": {
"fediverse": { "fediverse": {
@ -4111,7 +4113,7 @@
"header": "Odebírat na Fediverse" "header": "Odebírat na Fediverse"
}, },
"funkwhale": { "funkwhale": {
"header": "Použití Funkwhale" "header": "Odebírat na Funkwhale"
}, },
"header": "Odebírat tento kanál", "header": "Odebírat tento kanál",
"rss": { "rss": {
@ -4127,23 +4129,23 @@
"DetailOverview": { "DetailOverview": {
"header": { "header": {
"albums": "Alba", "albums": "Alba",
"latestEpisodes": "Nejnovější díly", "latestEpisodes": "Poslední díly",
"latestTracks": "Další stopa", "latestTracks": "Poslední skladby",
"series": "Série", "series": "Série",
"uploadsFailure": "Některé nahrávky se nepodařilo publikovat", "uploadsFailure": "Některé nahrávky se nepodařilo publikovat",
"uploadsProcessing": "Nahrávky se zpracovávájí", "uploadsProcessing": "Nahrávky se zpracovávájí",
"uploadsSuccess": "Heslo úspěšně změněno" "uploadsSuccess": "Nahrávky úspěšně publikovány"
}, },
"link": { "link": {
"addAlbum": "Přidat obsah", "addAlbum": "Přidat nové",
"erroredUploads": "Knihovny a nahrané soubory", "erroredUploads": "Zobrazit nahrávky s chybami",
"skippedUploads": "Zobrazit přeskočené nahrávky" "skippedUploads": "Zobrazit přeskočené nahrávky"
}, },
"message": { "message": {
"processing": "Vaše nahrávky se zpracovávájí a budou publikovány brzy." "processing": "Vaše nahrávky se zpracovávájí a budou brzy publikovány."
}, },
"meta": { "meta": {
"progress": "Knihovny a nahrané soubory" "progress": "Zpracované nahrávky: {finished}/{total}"
} }
}, },
"SubscriptionsList": { "SubscriptionsList": {
@ -4152,15 +4154,15 @@
"subscribe": "Odebírat" "subscribe": "Odebírat"
}, },
"link": { "link": {
"addNew": "Přidat obsah" "addNew": "Přidat nový"
}, },
"modal": { "modal": {
"subscription": { "subscription": {
"header": "Popis" "header": "Odběr"
} }
}, },
"placeholder": { "placeholder": {
"search": "Filtrovat pomocí názvu…" "search": "Filtrovat dle názvu…"
}, },
"title": "Odebírané Kanály" "title": "Odebírané Kanály"
} }
@ -4169,7 +4171,7 @@
"Base": { "Base": {
"link": { "link": {
"libraries": "Knihovny", "libraries": "Knihovny",
"tracks": "Stopy" "tracks": "Skladby"
}, },
"menu": { "menu": {
"secondary": "Podmenu" "secondary": "Podmenu"
@ -4210,7 +4212,7 @@
"details": "Úpravy knihovny" "details": "Úpravy knihovny"
}, },
"meta": { "meta": {
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | {n} skladba | {n} skladeb"
} }
}, },
"FilesTable": { "FilesTable": {
@ -4391,7 +4393,7 @@
"meta": { "meta": {
"failedTracks": "Neúspěšné skladby: {tracks}", "failedTracks": "Neúspěšné skladby: {tracks}",
"lastUpdate": "Poslední aktualizace: ", "lastUpdate": "Poslední aktualizace: ",
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | {n} skladba | {n} skladeb"
}, },
"modal": { "modal": {
"unfollow": { "unfollow": {
@ -4440,25 +4442,25 @@
"library": { "library": {
"DetailAlbums": { "DetailAlbums": {
"empty": { "empty": {
"follow": "Ukončením sledování této knihovny ztratíte přístup k jejímu obsahu.", "follow": "Nejspíš budete muset sledovat tuto knihovnu pro zobrzení jejího obsahu.",
"upload": "Tato knihovna je prázdna, měli byste sem něco nahrát!" "upload": "Tato knihovna je prázdná, měli byste sem něco nahrát!"
} }
}, },
"DetailOverview": { "DetailOverview": {
"empty": { "empty": {
"follow": "Ukončením sledování této knihovny ztratíte přístup k jejímu obsahu.", "follow": "Nejspíš budete muset sledovat tuto knihovnu pro zobrzení jejího obsahu.",
"upload": "Tato knihovna je prázdna, měli byste sem něco nahrát!" "upload": "Tato knihovna je prázdná, měli byste sem něco nahrát!"
} }
}, },
"DetailTracks": { "DetailTracks": {
"empty": { "empty": {
"follow": "Ukončením sledování této knihovny ztratíte přístup k jejímu obsahu.", "follow": "Nejspíš budete muset sledovat tuto knihovnu pro zobrzení jejího obsahu.",
"upload": "Tato knihovna je prázdna, měli byste sem něco nahrát!" "upload": "Tato knihovna je prázdná, měli byste sem něco nahrát!"
} }
}, },
"Edit": { "Edit": {
"button": { "button": {
"accept": "Akceptovat", "accept": "Přijmout",
"reject": "Odmítnout" "reject": "Odmítnout"
}, },
"empty": { "empty": {
@ -4466,7 +4468,7 @@
}, },
"header": { "header": {
"followers": "Sledující", "followers": "Sledující",
"libraryContents": "Úpravy knihovny" "libraryContents": "Obsah knihovny"
}, },
"loading": { "loading": {
"followers": "Načítání sledujících…" "followers": "Načítání sledujících…"
@ -4480,7 +4482,7 @@
"user": "Uživatel" "user": "Uživatel"
}, },
"status": { "status": {
"accepted": "Akceptováno", "accepted": "Přijato",
"pending": "Čeká na schválení", "pending": "Čeká na schválení",
"rejected": "Odmítnuto" "rejected": "Odmítnuto"
} }
@ -4493,10 +4495,10 @@
"upload": "Nahrát" "upload": "Nahrát"
}, },
"description": { "description": {
"sharingLink": "Sdílejte tento odkaz s ostatními, aby mohli požádat o přístup k vaší knihovně." "sharingLink": "Sdílejte tento odkaz s ostatními, aby mohli požádat o přístup k vaší knihovně vložením do vyhledávacího pole na jejich podu."
}, },
"label": { "label": {
"instance": "Odmítnuto", "instance": "Omezeno",
"private": "Soukromé", "private": "Soukromé",
"public": "Veřejné", "public": "Veřejné",
"sharingLink": "Odkaz pro sdílení" "sharingLink": "Odkaz pro sdílení"
@ -4504,13 +4506,13 @@
"link": { "link": {
"albums": "Alba", "albums": "Alba",
"artists": "Interpreti", "artists": "Interpreti",
"domain": "Členem od { date }", "domain": "Zobrazit na {domain}",
"moderation": "Otevřít v rozhraní pro moderaci", "moderation": "Otevřít v rozhraní pro moderaci",
"owner": "Přihlášen jako { username }", "owner": "Vlastněno uživatelem { username }",
"tracks": "Stopy" "tracks": "Skladby"
}, },
"meta": { "meta": {
"tracks": "{ n } stopa | { n } stopy" "tracks": "Žádné skladby | { n } skladba | { n } skladeb"
}, },
"title": "Knihovna", "title": "Knihovna",
"tooltip": { "tooltip": {
@ -4524,21 +4526,21 @@
"Detail": { "Detail": {
"button": { "button": {
"cancel": "Zrušit", "cancel": "Zrušit",
"confirm": "Odstranit playlist", "confirm": "Odstranit seznam skladeb",
"delete": "Odstranit", "delete": "Odstranit",
"edit": "Upravit", "edit": "Upravit",
"embed": "Vložit", "embed": "Vložit",
"playAll": "Přehrát vše", "playAll": "Přehrát vše",
"stopEdit": "Zastavit rádio" "stopEdit": "Přestat upravovat"
}, },
"empty": { "empty": {
"noTracks": "Přetáhněte myší řádky pro změnu pořadí stop v playlistu" "noTracks": "V tomto seznamu skladeb zatím nejsou žádné skladby"
}, },
"header": { "header": {
"tracks": "Stopy" "tracks": "Skladby"
}, },
"meta": { "meta": {
"tracks": "Playlist obsahující { n } stopu, od { username } | Playlist obsahující { n } stopy, od { username }" "tracks": "Seznam skladeb obsahující { n } skladbu, od { username } | Seznam skladeb obsahující { n } skladeb, od { username }"
}, },
"modal": { "modal": {
"delete": { "delete": {
@ -4548,23 +4550,23 @@
"header": "Opravdu chcete odstranit seznam skladeb \"{ playlist }\"?" "header": "Opravdu chcete odstranit seznam skladeb \"{ playlist }\"?"
}, },
"embed": { "embed": {
"header": "Vložit tento playlist do webové stránky" "header": "Vložit tento playlist na vaši webovou stránku"
} }
}, },
"title": "Playlist" "title": "Seznam skladeb"
}, },
"List": { "List": {
"button": { "button": {
"create": "Vytvořit playlist", "create": "Vytvořit seznam skladeb",
"manage": "Spravovat vaše playlisty", "manage": "Spravovat vaše seznamy skladeb",
"search": "Hledat" "search": "Hledat"
}, },
"empty": { "empty": {
"noResults": "Žádný interpret neodpovídá zadání" "noResults": "Žádný výsledek odpovídající dotazu"
}, },
"header": { "header": {
"browse": "Procházení playlistů", "browse": "Procházení seznamů skladeb",
"playlists": "Playlisty" "playlists": "Seznamy skladeb"
}, },
"label": { "label": {
"search": "Hledat" "search": "Hledat"
@ -4581,7 +4583,7 @@
"results": "Výsledků na stránku" "results": "Výsledků na stránku"
}, },
"placeholder": { "placeholder": {
"search": "Zadejte název playlistu…" "search": "Zadejte název seznamu skladeb…"
} }
} }
}, },
@ -4593,11 +4595,11 @@
"edit": "Upravit…" "edit": "Upravit…"
}, },
"empty": { "empty": {
"noTracks": "Stopu nelze přidat do playlistu" "noTracks": "Do tohoto rádia nebyly zatím přidány žádné skladby"
}, },
"header": { "header": {
"radio": "Rádio obsahující {tracks} skladeb, vytvořil ", "radio": "Rádio obsahující {tracks} skladeb, vytvořil ",
"tracks": "Stopy" "tracks": "Skladby"
}, },
"modal": { "modal": {
"delete": { "delete": {

Wyświetl plik

@ -183,9 +183,11 @@
}, },
"message": { "message": {
"automaticPlay": "Der nächste Titel wird automatisch in wenigen Sekunden wiedergegeben…", "automaticPlay": "Der nächste Titel wird automatisch in wenigen Sekunden wiedergegeben…",
"radio": "Neue Titel werden hier automatisch hinzugefügt." "radio": "Neue Titel werden hier automatisch hinzugefügt.",
"webglUnsupported": "Leider unterstützt dein Browser kein WebGL2."
}, },
"meta": { "meta": {
"end": "Ende",
"queuePosition": "Titel { index } von { length }", "queuePosition": "Titel { index } von { length }",
"startTime": "00:00", "startTime": "00:00",
"unknownAlbum": "Unbekanntes Album", "unknownAlbum": "Unbekanntes Album",
@ -2922,9 +2924,11 @@
"radios": { "radios": {
"Button": { "Button": {
"startArtistsRadio": "Start Künstler*innen Radio", "startArtistsRadio": "Start Künstler*innen Radio",
"startPlaylistsRadio": "Starte Wiedergabelistenradio",
"startRadio": "Radio abspielen", "startRadio": "Radio abspielen",
"startTagsRadio": "Starte Tag Radio", "startTagsRadio": "Starte Tag Radio",
"stopArtistsRadio": "Stoppe Künstler*innen Radio", "stopArtistsRadio": "Stoppe Künstler*innen Radio",
"stopPlaylistsRadio": "Stoppe Wiedergabelistenradio",
"stopRadio": "Radio ausschalten", "stopRadio": "Radio ausschalten",
"stopTagsRadio": "Stoppe Tag Radio" "stopTagsRadio": "Stoppe Tag Radio"
}, },
@ -3196,6 +3200,9 @@
} }
} }
}, },
"useErrorHandler": {
"unexpectedError": "Ein unerwarteter Fehler ist aufgetreten."
},
"useThemeList": { "useThemeList": {
"darkTheme": "Dunkel", "darkTheme": "Dunkel",
"lightTheme": "Hell" "lightTheme": "Hell"

Wyświetl plik

@ -222,7 +222,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
min-width: 10em; min-width: 8em;
z-index: 2; z-index: 2;
> .control.button { > .control.button {
padding: 0.5em; padding: 0.5em;

Wyświetl plik

@ -291,6 +291,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
max-width: 100vw;
.ui.header { .ui.header {
width: 100%; width: 100%;
@ -462,6 +463,12 @@
align-items: center; align-items: center;
} }
.title.ellipsis {
@include media("<tablet") {
max-width: 35vw;
}
}
// NOTE: Taken from semantic ui // NOTE: Taken from semantic ui
&.active { &.active {
background: #E0E0E0; background: #E0E0E0;

Wyświetl plik

@ -35,6 +35,7 @@
vertical-align: middle; vertical-align: middle;
} }
&.sidebar { &.sidebar {
z-index: 10000 !important;
overflow-y: visible !important; overflow-y: visible !important;
background: var(--sidebar-background); background: var(--sidebar-background);
z-index: 1; z-index: 1;

Wyświetl plik

@ -150,7 +150,7 @@
.track-row, .track-row,
.track-table { .track-table {
padding: 0.5em; padding: 0.5em !important; /* Overwrite fomantic ui padding rules */
> div:not(.mobile) { > div:not(.mobile) {
padding: 0.25em; padding: 0.25em;
margin-right: 0.25em; margin-right: 0.25em;

Wyświetl plik

@ -4,7 +4,7 @@ import type { Notification } from '~/types'
import moment from 'moment' import moment from 'moment'
import axios from 'axios' import axios from 'axios'
import { ref, reactive, computed, watch, markRaw } from 'vue' import { ref, reactive, computed, watch } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useStore } from '~/store' import { useStore } from '~/store'
@ -38,7 +38,7 @@ const fetchData = async () => {
try { try {
const response = await axios.get('federation/inbox/', { params: filters }) const response = await axios.get('federation/inbox/', { params: filters })
notifications.count = response.data.count notifications.count = response.data.count
notifications.results = response.data.results.map(markRaw) notifications.results = response.data.results
} catch (error) { } catch (error) {
useErrorHandler(error as Error) useErrorHandler(error as Error)
} }
@ -50,7 +50,7 @@ watch(filters, fetchData, { immediate: true })
useWebSocketHandler('inbox.item_added', (event) => { useWebSocketHandler('inbox.item_added', (event) => {
notifications.count += 1 notifications.count += 1
notifications.results.unshift(markRaw((event.item))) notifications.results.unshift(event.item)
}) })
const instanceSupportMessageDelay = ref(60) const instanceSupportMessageDelay = ref(60)
@ -136,7 +136,8 @@ const markAllAsRead = async () => {
<option :value="90"> <option :value="90">
{{ $t('views.Notifications.option.delay.90') }} {{ $t('views.Notifications.option.delay.90') }}
</option> </option>
<option :value="null"> <!-- NOTE: Postpone notification 100 years, so that the user never sees it -->
<option :value="36500">
{{ $t('views.Notifications.option.delay.never') }} {{ $t('views.Notifications.option.delay.never') }}
</option> </option>
</select> </select>
@ -200,7 +201,8 @@ const markAllAsRead = async () => {
<option :value="90"> <option :value="90">
{{ $t('views.Notifications.option.delay.90') }} {{ $t('views.Notifications.option.delay.90') }}
</option> </option>
<option :value="null"> <!-- NOTE: Postpone notification 100 years, so that the user never sees it -->
<option :value="36500">
{{ $t('views.Notifications.option.delay.never') }} {{ $t('views.Notifications.option.delay.never') }}
</option> </option>
</select> </select>

Wyświetl plik

@ -0,0 +1,6 @@
import { AudioContext } from 'standardized-audio-context-mock'
import { vi } from 'vitest'
vi.mock('standardized-audio-context', () => ({
AudioContext
}))

Wyświetl plik

@ -0,0 +1,14 @@
import { config } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
import en from '~/locales/en_US.json'
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en
}
})
config.global.plugins ??= []
config.global.plugins.push(i18n)

Wyświetl plik

@ -0,0 +1,231 @@
import { useQueue } from '~/composables/audio/queue'
import type { Track } from '~/types'
const { tracks, enqueue, dequeue, clear, reorder, currentIndex } = useQueue()
describe('currentIndex', () => {
beforeEach(async () => {
await clear()
await enqueue(
{ id: 1, uploads: [] } as any as Track,
{ id: 2, uploads: [] } as any as Track,
{ id: 3, uploads: [] } as any as Track
)
})
describe('clamp', () => {
it('should be clamped to queue size', () => {
currentIndex.value = 100
expect(currentIndex.value).toBe(2)
currentIndex.value = -100
expect(currentIndex.value).toBe(0)
})
it('should be clamped to queue size after enqueue', async () => {
await enqueue({ id: 4, uploads: [] } as any as Track)
currentIndex.value = 100
expect(currentIndex.value).toBe(3)
currentIndex.value = -100
expect(currentIndex.value).toBe(0)
})
it('should be clamped to queue size after clear', async () => {
await clear()
expect(currentIndex.value).toBe(0)
currentIndex.value = 100
expect(currentIndex.value).toBe(0)
currentIndex.value = -100
expect(currentIndex.value).toBe(0)
})
it('should update currentIndex after removal of last track', async () => {
await dequeue(2)
currentIndex.value = 100
expect(currentIndex.value).toBe(1)
currentIndex.value = -100
expect(currentIndex.value).toBe(0)
})
it('should update currentIndex after removal of last track', async () => {
currentIndex.value = 2
tracks.value.splice(2, 1)
expect(currentIndex.value).toBe(1)
currentIndex.value = 100
expect(currentIndex.value).toBe(1)
currentIndex.value = -100
expect(currentIndex.value).toBe(0)
})
it('should update currentIndex after removal of middle track', async () => {
currentIndex.value = 2
tracks.value.splice(1, 1)
expect(currentIndex.value).toBe(1)
currentIndex.value = 100
expect(currentIndex.value).toBe(1)
currentIndex.value = -100
expect(currentIndex.value).toBe(0)
})
})
})
describe('Ordered queue', () => {
beforeEach(async () => {
await clear()
await enqueue(
{ id: 1, uploads: [] } as any as Track,
{ id: 2, uploads: [] } as any as Track,
{ id: 3, uploads: [] } as any as Track
)
})
describe('first track is playing', () => {
beforeEach(() => {
currentIndex.value = 0
})
it('reorder current track to the middle', () => {
reorder(0, 1)
expect(tracks.value).toEqual([2, 1, 3])
expect(currentIndex.value).toBe(1)
})
it('reorder current track to the end', () => {
reorder(0, 2)
expect(tracks.value).toEqual([2, 3, 1])
expect(currentIndex.value).toBe(2)
})
it('reorder middle track to the beginning', () => {
reorder(1, 0)
expect(tracks.value).toEqual([2, 1, 3])
expect(currentIndex.value).toBe(1)
})
it('reorder middle track to the end', () => {
reorder(1, 2)
expect(tracks.value).toEqual([1, 3, 2])
expect(currentIndex.value).toBe(0)
})
it('reorder last track to the beginning', () => {
reorder(2, 0)
expect(tracks.value).toEqual([3, 1, 2])
expect(currentIndex.value).toBe(1)
})
it('reorder last track to the middle', () => {
reorder(2, 1)
expect(tracks.value).toEqual([1, 3, 2])
expect(currentIndex.value).toBe(0)
})
})
describe('middle track is playing', () => {
beforeEach(() => {
currentIndex.value = 1
})
it('reorder current track to the beginning', () => {
reorder(1, 0)
expect(tracks.value).toEqual([2, 1, 3])
expect(currentIndex.value).toBe(0)
})
it('reorder current track to the end', () => {
reorder(1, 2)
expect(tracks.value).toEqual([1, 3, 2])
expect(currentIndex.value).toBe(2)
})
it('reorder first track to the middle', () => {
reorder(0, 1)
expect(tracks.value).toEqual([2, 1, 3])
expect(currentIndex.value).toBe(0)
})
it('reorder first track to the end', () => {
reorder(0, 2)
expect(tracks.value).toEqual([2, 3, 1])
expect(currentIndex.value).toBe(0)
})
it('reorder last track to the beginning', () => {
reorder(2, 0)
expect(tracks.value).toEqual([3, 1, 2])
expect(currentIndex.value).toBe(2)
})
it('reorder last track to the middle', () => {
reorder(2, 1)
expect(tracks.value).toEqual([1, 3, 2])
expect(currentIndex.value).toBe(2)
})
})
describe('last track is playing', () => {
beforeEach(() => {
currentIndex.value = 2
})
it('reorder current track to the beginning', () => {
reorder(2, 0)
expect(tracks.value).toEqual([3, 1, 2])
expect(currentIndex.value).toBe(0)
})
it('reorder current track to the middle', () => {
reorder(2, 1)
expect(tracks.value).toEqual([1, 3, 2])
expect(currentIndex.value).toBe(1)
})
it('reorder first track to the middle', () => {
reorder(0, 1)
expect(tracks.value).toEqual([2, 1, 3])
expect(currentIndex.value).toBe(2)
})
it('reorder first track to the end', () => {
reorder(0, 2)
expect(tracks.value).toEqual([2, 3, 1])
expect(currentIndex.value).toBe(1)
})
it('reorder middle track to the beginning', () => {
reorder(1, 0)
expect(tracks.value).toEqual([2, 1, 3])
expect(currentIndex.value).toBe(2)
})
it('reorder middle track to the end', () => {
reorder(1, 2)
expect(tracks.value).toEqual([1, 3, 2])
expect(currentIndex.value).toBe(1)
})
})
})
// TODO: Add tests for the shuffled queue
// describe('Shuffled queue', () => {
// beforeEach(async () => {
// await clear()
// await enqueue(
// { id: 1, uploads: [] } as any as Track,
// { id: 2, uploads: [] } as any as Track,
// { id: 3, uploads: [] } as any as Track,
// )
//
// shuffle()
// })
// })

Wyświetl plik

@ -3,7 +3,8 @@ import AlbumDetail from '~/views/admin/library/AlbumDetail.vue'
import SanitizedHtml from '~/components/SanitizedHtml.vue' import SanitizedHtml from '~/components/SanitizedHtml.vue'
import HumanDate from '~/components/common/HumanDate.vue' import HumanDate from '~/components/common/HumanDate.vue'
import moxios from 'moxios' import MockAdapter from 'axios-mock-adapter'
import axios from 'axios'
import { shallowMount } from '@vue/test-utils' import { shallowMount } from '@vue/test-utils'
import { sleep } from '?/utils' import { sleep } from '?/utils'
@ -11,23 +12,15 @@ import { sleep } from '?/utils'
import router from '~/router' import router from '~/router'
import store from '~/store' import store from '~/store'
beforeEach(() => moxios.install()) const axiosMock = new MockAdapter(axios)
afterEach(() => moxios.uninstall())
describe('views/admin/library', () => { describe('views/admin/library', () => {
describe('Album details', () => { describe('Album details', () => {
it('displays default cover', async () => { it('displays default cover', async () => {
const album = { cover: null, artist: { id: 1 }, title: 'dummy', id: 1, creation_date: '2020-01-01' } const album = { cover: null, artist: { id: 1 }, title: 'dummy', id: 1, creation_date: '2020-01-01' }
moxios.stubRequest('manage/library/albums/1/', { axiosMock.onGet('manage/library/albums/1/').reply(200, album)
status: 200, axiosMock.onGet('manage/library/albums/1/stats/').reply(200, {})
response: album
})
moxios.stubRequest('manage/library/albums/1/stats/', {
status: 200,
response: {}
})
const wrapper = shallowMount(AlbumDetail, { const wrapper = shallowMount(AlbumDetail, {
props: { id: 1 }, props: { id: 1 },

Wyświetl plik

@ -7,6 +7,9 @@ import { visualizer } from 'rollup-plugin-visualizer'
import manifest from './pwa-manifest.json' import manifest from './pwa-manifest.json'
import Inspector from 'vite-plugin-vue-inspector' import Inspector from 'vite-plugin-vue-inspector'
import { defineConfig } from 'vite'
const port = +(process.env.VUE_PORT ?? 8080) const port = +(process.env.VUE_PORT ?? 8080)
@ -78,6 +81,10 @@ export default defineConfig(({ mode }) => ({
src: './src', src: './src',
all: true, all: true,
reporter: ['text', 'cobertura'] reporter: ['text', 'cobertura']
} },
setupFiles: [
'./test/setup/mock-audio-context.ts',
'./test/setup/mock-vue-i18n.ts',
]
} }
})) }))

Plik diff jest za duży Load Diff