From 333e8d4677fbefea166c6506e540f90f32763e1a Mon Sep 17 00:00:00 2001 From: Georg Krause Date: Thu, 6 Jul 2023 11:30:57 +0200 Subject: [PATCH 01/50] fix(docs): Delete obsolete files from documentation deployment --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1764c4e9c..722e70962 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -362,7 +362,7 @@ deploy_documentation: - eval `ssh-agent -s` - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - script: - - rsync -r -e "ssh -p 2282" $CI_PROJECT_DIR/public/ docs@docs.funkwhale.audio:/htdocs/$CI_COMMIT_REF_NAME + - rsync -r -e --delete "ssh -p 2282" $CI_PROJECT_DIR/public/ docs@docs.funkwhale.audio:/htdocs/$CI_COMMIT_REF_NAME rules: - if: $CI_COMMIT_BRANCH =~ /(stable|develop)/ From b6d6f118f37202bc915065da6e3e8e4652ab91d0 Mon Sep 17 00:00:00 2001 From: Georg Krause Date: Thu, 6 Jul 2023 12:01:34 +0200 Subject: [PATCH 02/50] fix(docs): Fix rsync command argument order --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 722e70962..158948bb5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -362,7 +362,7 @@ deploy_documentation: - eval `ssh-agent -s` - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - script: - - rsync -r -e --delete "ssh -p 2282" $CI_PROJECT_DIR/public/ docs@docs.funkwhale.audio:/htdocs/$CI_COMMIT_REF_NAME + - rsync -r --delete -e "ssh -p 2282" $CI_PROJECT_DIR/public/ docs@docs.funkwhale.audio:/htdocs/$CI_COMMIT_REF_NAME rules: - if: $CI_COMMIT_BRANCH =~ /(stable|develop)/ From 58d0109d025024088abd3187485aba4fe4012ba9 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 13 Jul 2023 15:35:25 +0000 Subject: [PATCH 03/50] chore(api): update dependency click to v8.1.5 --- api/poetry.lock | 8 ++++---- api/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/poetry.lock b/api/poetry.lock index 9b2ff1acf..5347ba4e6 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -742,14 +742,14 @@ files = [ [[package]] name = "click" -version = "8.1.3" +version = "8.1.5" description = "Composable command line interface toolkit" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.5-py3-none-any.whl", hash = "sha256:e576aa487d679441d7d30abb87e1b43d24fc53bffb8758443b1a9e1cee504548"}, + {file = "click-8.1.5.tar.gz", hash = "sha256:4be4b1af8d665c6d942909916d31a213a106800c47d0eeba73d34da3cbc11367"}, ] [package.dependencies] @@ -4003,4 +4003,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "424c5787c18065c097583776a0eebf68dfd118df634d44fff7e9863c78e6f634" +content-hash = "3eebd3ca97c8b920d6b5795cfb8e7f08faabf4e6265ab63c2fbbf3de50b84e71" diff --git a/api/pyproject.toml b/api/pyproject.toml index 2a6858b1a..68265abc4 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -70,7 +70,7 @@ aiohttp = "==3.8.4" arrow = "==1.2.3" bleach = "==5.0.1" boto3 = "==1.26.161" -click = "==8.1.3" +click = "==8.1.5" cryptography = "==38.0.4" feedparser = "==6.0.10" musicbrainzngs = "==0.7.1" From 9bc1f09ef1da24fdbb047e4f7b10da62be4ffb73 Mon Sep 17 00:00:00 2001 From: jo Date: Tue, 25 Jul 2023 19:02:53 +0200 Subject: [PATCH 04/50] chore: upgrade pre-commit hooks --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3f8f3a0e6..be109f291 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,14 +25,14 @@ repos: - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + rev: v3.9.0 hooks: - id: pyupgrade args: [--py37-plus] exclude: ^(api/.*/migrations/.*) - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 23.7.0 hooks: - id: black @@ -47,7 +47,7 @@ repos: - id: flake8 - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.7.1 + rev: v3.0.0 hooks: - id: prettier files: \.(md|yml|yaml|json)$ @@ -59,7 +59,7 @@ repos: additional_dependencies: [tomli] - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.8.0.4 + rev: v0.9.0.5 hooks: - id: shellcheck From abadf6c9fb3148ee35ea56374fc5635b222a2ee8 Mon Sep 17 00:00:00 2001 From: jo Date: Tue, 25 Jul 2023 19:04:32 +0200 Subject: [PATCH 05/50] style: format file with black==23.7.0 --- api/config/schema.py | 2 +- api/funkwhale_api/activity/views.py | 1 - api/funkwhale_api/audio/renderers.py | 1 - api/funkwhale_api/common/fields.py | 2 +- api/funkwhale_api/common/filters.py | 2 -- .../common/management/commands/load_test_data.py | 2 -- api/funkwhale_api/common/middleware.py | 2 -- api/funkwhale_api/contrib/listenbrainz/client.py | 2 +- api/funkwhale_api/favorites/views.py | 1 - api/funkwhale_api/federation/activity.py | 1 - api/funkwhale_api/federation/api_views.py | 2 -- api/funkwhale_api/federation/jsonld.py | 2 -- api/funkwhale_api/federation/serializers.py | 2 -- api/funkwhale_api/federation/tasks.py | 1 - api/funkwhale_api/federation/utils.py | 2 -- api/funkwhale_api/history/views.py | 1 - api/funkwhale_api/manage/serializers.py | 2 -- api/funkwhale_api/manage/views.py | 1 - api/funkwhale_api/moderation/mrf_policies.py | 1 - api/funkwhale_api/music/filters.py | 3 --- .../music/management/commands/import_files.py | 1 - api/funkwhale_api/music/metadata.py | 1 - api/funkwhale_api/music/models.py | 2 -- api/funkwhale_api/music/tasks.py | 1 - api/funkwhale_api/playlists/views.py | 1 - api/funkwhale_api/radios/serializers.py | 1 - api/funkwhale_api/radios/views.py | 2 -- api/funkwhale_api/subsonic/views.py | 1 - api/funkwhale_api/users/admin.py | 1 - api/funkwhale_api/users/models.py | 1 - api/funkwhale_api/users/oauth/permissions.py | 2 -- api/funkwhale_api/users/serializers.py | 1 - api/tests/audio/test_views.py | 2 -- api/tests/federation/test_activity.py | 2 -- api/tests/federation/test_jsonld.py | 1 - api/tests/federation/test_routes.py | 1 - .../federation/test_third_party_activitypub.py | 2 -- api/tests/music/test_models.py | 2 -- api/tests/radios/test_api.py | 1 - api/tests/radios/test_filters.py | 2 -- api/tests/radios/test_radios.py | 2 +- api/tests/test_test_utils.py | 1 - api/tests/users/oauth/test_scopes.py | 1 - docs/get-releases-json.py | 3 +-- front/scripts/fix-fomantic-css.py | 16 +++++++++++++--- 45 files changed, 18 insertions(+), 66 deletions(-) diff --git a/api/config/schema.py b/api/config/schema.py index aea23f3fe..99e4555fa 100644 --- a/api/config/schema.py +++ b/api/config/schema.py @@ -46,7 +46,7 @@ def custom_preprocessing_hook(endpoints): # your modifications to the list of operations that are exposed in the schema api_type = os.environ.get("API_TYPE", "v1") - for (path, path_regex, method, callback) in endpoints: + for path, path_regex, method, callback in endpoints: if path.startswith("/api/v1/providers"): continue diff --git a/api/funkwhale_api/activity/views.py b/api/funkwhale_api/activity/views.py index 387a5f64d..4938301a5 100644 --- a/api/funkwhale_api/activity/views.py +++ b/api/funkwhale_api/activity/views.py @@ -9,7 +9,6 @@ from . import serializers, utils class ActivityViewSet(viewsets.GenericViewSet): - serializer_class = serializers.AutoSerializer permission_classes = [ConditionalAuthentication] queryset = TrackFavorite.objects.none() diff --git a/api/funkwhale_api/audio/renderers.py b/api/funkwhale_api/audio/renderers.py index 34812765c..79294ca3d 100644 --- a/api/funkwhale_api/audio/renderers.py +++ b/api/funkwhale_api/audio/renderers.py @@ -26,7 +26,6 @@ class PodcastRSSRenderer(renderers.JSONRenderer): class PodcastRSSContentNegociation(negotiation.DefaultContentNegotiation): def select_renderer(self, request, renderers, format_suffix=None): - return (PodcastRSSRenderer(), PodcastRSSRenderer.media_type) diff --git a/api/funkwhale_api/common/fields.py b/api/funkwhale_api/common/fields.py index 377c0663f..6217f66b0 100644 --- a/api/funkwhale_api/common/fields.py +++ b/api/funkwhale_api/common/fields.py @@ -57,7 +57,7 @@ class SmartSearchFilter(django_filters.CharFilter): return qs try: cleaned = self.config.clean(value) - except (forms.ValidationError): + except forms.ValidationError: return qs.none() return search.apply(qs, cleaned) diff --git a/api/funkwhale_api/common/filters.py b/api/funkwhale_api/common/filters.py index 1530954ac..6fb4b1b45 100644 --- a/api/funkwhale_api/common/filters.py +++ b/api/funkwhale_api/common/filters.py @@ -119,7 +119,6 @@ class MultipleQueryFilter(filters.TypedMultipleChoiceFilter): def filter_target(value): - config = { "artist": ["artist", "target_id", int], "album": ["album", "target_id", int], @@ -177,7 +176,6 @@ class ActorScopeFilter(filters.CharFilter): super().__init__(*args, **kwargs) def filter(self, queryset, value): - if not value: return queryset diff --git a/api/funkwhale_api/common/management/commands/load_test_data.py b/api/funkwhale_api/common/management/commands/load_test_data.py index 8209bb85f..f9997a331 100644 --- a/api/funkwhale_api/common/management/commands/load_test_data.py +++ b/api/funkwhale_api/common/management/commands/load_test_data.py @@ -46,7 +46,6 @@ def create_local_accounts(factories, count, dependencies): def create_taggable_items(dependency): def inner(factories, count, dependencies): - objs = [] tagged_objects = dependencies.get( dependency, list(CONFIG_BY_ID[dependency]["model"].objects.all().only("pk")) @@ -260,7 +259,6 @@ class Command(BaseCommand): self.stdout.write("") if options["dry_run"]: - self.stdout.write( "Run this command with --no-dry-run to commit the changes to the database" ) diff --git a/api/funkwhale_api/common/middleware.py b/api/funkwhale_api/common/middleware.py index 5736b973a..b83beb2e6 100644 --- a/api/funkwhale_api/common/middleware.py +++ b/api/funkwhale_api/common/middleware.py @@ -167,7 +167,6 @@ def render_tags(tags): """ for tag in tags: - yield "<{tag} {attrs} />".format( tag=tag.pop("tag"), attrs=" ".join( @@ -408,7 +407,6 @@ class PymallocMiddleware: self.get_response = get_response def __call__(self, request): - if tracemalloc.is_tracing(): snapshot = tracemalloc.take_snapshot() stats = snapshot.statistics("lineno") diff --git a/api/funkwhale_api/contrib/listenbrainz/client.py b/api/funkwhale_api/contrib/listenbrainz/client.py index b2d1f169b..70db31dc3 100644 --- a/api/funkwhale_api/contrib/listenbrainz/client.py +++ b/api/funkwhale_api/contrib/listenbrainz/client.py @@ -155,7 +155,7 @@ class ListenBrainzClient: def _get_payload_many(tracks): payload = [] - for (listened_at, track) in tracks: + for listened_at, track in tracks: data = _get_payload(track, listened_at) payload.append(data) return payload diff --git a/api/funkwhale_api/favorites/views.py b/api/funkwhale_api/favorites/views.py index c61251ac0..6a87d3b15 100644 --- a/api/funkwhale_api/favorites/views.py +++ b/api/funkwhale_api/favorites/views.py @@ -19,7 +19,6 @@ class TrackFavoriteViewSet( mixins.ListModelMixin, viewsets.GenericViewSet, ): - filterset_class = filters.TrackFavoriteFilter serializer_class = serializers.UserTrackFavoriteSerializer queryset = models.TrackFavorite.objects.all().select_related( diff --git a/api/funkwhale_api/federation/activity.py b/api/funkwhale_api/federation/activity.py index e76c82a5d..dedea8dd8 100644 --- a/api/funkwhale_api/federation/activity.py +++ b/api/funkwhale_api/federation/activity.py @@ -180,7 +180,6 @@ def receive(activity, on_behalf_of, inbox_actor=None): inbox_items = [] for recipients, type in [(local_to_recipients, "to"), (local_cc_recipients, "cc")]: - for r in recipients: inbox_items.append(models.InboxItem(actor_id=r, type=type, activity=copy)) diff --git a/api/funkwhale_api/federation/api_views.py b/api/funkwhale_api/federation/api_views.py index 201d9983a..e9d7bff01 100644 --- a/api/funkwhale_api/federation/api_views.py +++ b/api/funkwhale_api/federation/api_views.py @@ -208,7 +208,6 @@ class InboxItemViewSet( mixins.RetrieveModelMixin, viewsets.GenericViewSet, ): - queryset = ( models.InboxItem.objects.select_related("activity__actor") .prefetch_related("activity__object", "activity__target") @@ -239,7 +238,6 @@ class InboxItemViewSet( class FetchViewSet( mixins.CreateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet ): - queryset = models.Fetch.objects.select_related("actor") serializer_class = api_serializers.FetchSerializer permission_classes = [permissions.IsAuthenticated] diff --git a/api/funkwhale_api/federation/jsonld.py b/api/funkwhale_api/federation/jsonld.py index 8f1f362cc..101b7fb92 100644 --- a/api/funkwhale_api/federation/jsonld.py +++ b/api/funkwhale_api/federation/jsonld.py @@ -154,7 +154,6 @@ def dereference(value, references): def get_value(value, keep=None, attr=None): - if keep == "first": value = value[0] if attr: @@ -253,7 +252,6 @@ class JsonLdSerializer(serializers.Serializer): def run_validation(self, data=empty): if data and data is not empty: - self.jsonld_context = data.get("@context", []) if self.context.get("expand", self.jsonld_expand): try: diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py index 31858f76d..c96cd8f38 100644 --- a/api/funkwhale_api/federation/serializers.py +++ b/api/funkwhale_api/federation/serializers.py @@ -756,7 +756,6 @@ class FollowActionSerializer(serializers.Serializer): class AcceptFollowSerializer(FollowActionSerializer): - type = serializers.ChoiceField(choices=["Accept"]) action_type = "accept" @@ -770,7 +769,6 @@ class AcceptFollowSerializer(FollowActionSerializer): class RejectFollowSerializer(FollowActionSerializer): - type = serializers.ChoiceField(choices=["Reject"]) action_type = "reject" diff --git a/api/funkwhale_api/federation/tasks.py b/api/funkwhale_api/federation/tasks.py index d46cd721c..7d9abf634 100644 --- a/api/funkwhale_api/federation/tasks.py +++ b/api/funkwhale_api/federation/tasks.py @@ -139,7 +139,6 @@ def dispatch_outbox(activity): "delivery", ) def deliver_to_remote(delivery): - if not preferences.get("federation__enabled"): # federation is disabled, we only deliver to local recipients return diff --git a/api/funkwhale_api/federation/utils.py b/api/funkwhale_api/federation/utils.py index ee4d3834d..cd24dcb68 100644 --- a/api/funkwhale_api/federation/utils.py +++ b/api/funkwhale_api/federation/utils.py @@ -145,7 +145,6 @@ def is_local(url) -> bool: def get_actor_data_from_username(username): - parts = username.split("@") return { @@ -243,7 +242,6 @@ FID_MODEL_LABELS = [ def get_object_by_fid(fid, local=None): - if local: parsed = urllib.parse.urlparse(fid) if parsed.netloc != settings.FEDERATION_HOSTNAME: diff --git a/api/funkwhale_api/history/views.py b/api/funkwhale_api/history/views.py index 0012af790..812ed38ae 100644 --- a/api/funkwhale_api/history/views.py +++ b/api/funkwhale_api/history/views.py @@ -17,7 +17,6 @@ class ListeningViewSet( mixins.RetrieveModelMixin, viewsets.GenericViewSet, ): - serializer_class = serializers.ListeningSerializer queryset = models.Listening.objects.all().select_related( "user__actor__attachment_icon" diff --git a/api/funkwhale_api/manage/serializers.py b/api/funkwhale_api/manage/serializers.py index b96921e33..e097fc88f 100644 --- a/api/funkwhale_api/manage/serializers.py +++ b/api/funkwhale_api/manage/serializers.py @@ -395,7 +395,6 @@ class ManageNestedTrackSerializer(serializers.ModelSerializer): class ManageNestedAlbumSerializer(ManageBaseAlbumSerializer): - tracks_count = serializers.SerializerMethodField() class Meta: @@ -662,7 +661,6 @@ class ManageUploadSerializer(serializers.ModelSerializer): class ManageTagSerializer(ManageBaseAlbumSerializer): - tracks_count = serializers.SerializerMethodField() albums_count = serializers.SerializerMethodField() artists_count = serializers.SerializerMethodField() diff --git a/api/funkwhale_api/manage/views.py b/api/funkwhale_api/manage/views.py index 00c537f89..4de9b5e96 100644 --- a/api/funkwhale_api/manage/views.py +++ b/api/funkwhale_api/manage/views.py @@ -674,7 +674,6 @@ class ManageChannelViewSet( mixins.DestroyModelMixin, viewsets.GenericViewSet, ): - url_lookups = [ { "lookup_field": "uuid", diff --git a/api/funkwhale_api/moderation/mrf_policies.py b/api/funkwhale_api/moderation/mrf_policies.py index d6862b9e7..264baed37 100644 --- a/api/funkwhale_api/moderation/mrf_policies.py +++ b/api/funkwhale_api/moderation/mrf_policies.py @@ -36,7 +36,6 @@ def check_allow_list(payload, **kwargs): } if relevant_domains - allowed_domains: - raise mrf.Discard( "These domains are not allowed: {}".format( ", ".join(relevant_domains - allowed_domains) diff --git a/api/funkwhale_api/music/filters.py b/api/funkwhale_api/music/filters.py index 658dce608..0fc18bd8a 100644 --- a/api/funkwhale_api/music/filters.py +++ b/api/funkwhale_api/music/filters.py @@ -46,7 +46,6 @@ class RelatedFilterSet(filters.FilterSet): class ChannelFilterSet(filters.FilterSet): - channel = filters.CharFilter(field_name="_", method="filter_channel") def filter_channel(self, queryset, name, value): @@ -70,7 +69,6 @@ class ChannelFilterSet(filters.FilterSet): class LibraryFilterSet(filters.FilterSet): - library = filters.CharFilter(field_name="_", method="filter_library") def filter_library(self, queryset, name, value): @@ -96,7 +94,6 @@ class ArtistFilter( audio_filters.IncludeChannelsFilterSet, moderation_filters.HiddenContentFilterSet, ): - q = fields.SearchFilter(search_fields=["name"], fts_search_fields=["body_text"]) playable = filters.BooleanFilter(field_name="_", method="filter_playable") has_albums = filters.BooleanFilter(field_name="_", method="filter_has_albums") diff --git a/api/funkwhale_api/music/management/commands/import_files.py b/api/funkwhale_api/music/management/commands/import_files.py index d60e13c86..08c02138b 100644 --- a/api/funkwhale_api/music/management/commands/import_files.py +++ b/api/funkwhale_api/music/management/commands/import_files.py @@ -810,7 +810,6 @@ def check_updates(stdout, library, extensions, paths, batch_size): ) for upload in rows: - check_upload(stdout, upload) checked_paths.add(upload.source.replace("file://", "", 1)) diff --git a/api/funkwhale_api/music/metadata.py b/api/funkwhale_api/music/metadata.py index 4e909fe8a..479e210e0 100644 --- a/api/funkwhale_api/music/metadata.py +++ b/api/funkwhale_api/music/metadata.py @@ -136,7 +136,6 @@ def clean_flac_pictures(apic): def clean_ogg_pictures(metadata_block_picture): pictures = [] for b64_data in [metadata_block_picture]: - try: data = base64.b64decode(b64_data) except (TypeError, ValueError): diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index 9e4b81a15..fca044a16 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -437,7 +437,6 @@ class TrackQuerySet(common_models.LocalFromFidQuerySet, models.QuerySet): ) def annotate_playable_by_actor(self, actor): - files = ( Upload.objects.playable_by(actor) .filter(track=models.OuterRef("id")) @@ -448,7 +447,6 @@ class TrackQuerySet(common_models.LocalFromFidQuerySet, models.QuerySet): return self.annotate(is_playable_by_actor=subquery) def playable_by(self, actor, include=True): - if settings.MUSIC_USE_DENORMALIZATION: if actor is not None: query = models.Q(actor=None) | models.Q(actor=actor) diff --git a/api/funkwhale_api/music/tasks.py b/api/funkwhale_api/music/tasks.py index 705c98e3d..2d4e173d7 100644 --- a/api/funkwhale_api/music/tasks.py +++ b/api/funkwhale_api/music/tasks.py @@ -445,7 +445,6 @@ def get_best_candidate_or_create(model, query, defaults, sort_fields): """ candidates = model.objects.filter(query) if candidates: - return sort_candidates(candidates, sort_fields)[0], False return model.objects.create(**defaults), True diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py index ddcd0cea1..0b57a6ef9 100644 --- a/api/funkwhale_api/playlists/views.py +++ b/api/funkwhale_api/playlists/views.py @@ -20,7 +20,6 @@ class PlaylistViewSet( mixins.ListModelMixin, viewsets.GenericViewSet, ): - serializer_class = serializers.PlaylistSerializer queryset = ( models.Playlist.objects.all() diff --git a/api/funkwhale_api/radios/serializers.py b/api/funkwhale_api/radios/serializers.py index dc5d6c908..76e847d9e 100644 --- a/api/funkwhale_api/radios/serializers.py +++ b/api/funkwhale_api/radios/serializers.py @@ -54,7 +54,6 @@ class RadioSessionTrackSerializer(serializers.ModelSerializer): class RadioSessionSerializer(serializers.ModelSerializer): - related_object_id = serializers.CharField(required=False, allow_null=True) class Meta: diff --git a/api/funkwhale_api/radios/views.py b/api/funkwhale_api/radios/views.py index a81a1c218..adf2fe464 100644 --- a/api/funkwhale_api/radios/views.py +++ b/api/funkwhale_api/radios/views.py @@ -20,7 +20,6 @@ class RadioViewSet( mixins.DestroyModelMixin, viewsets.GenericViewSet, ): - serializer_class = serializers.RadioSerializer permission_classes = [ oauth_permissions.ScopePermission, @@ -87,7 +86,6 @@ class RadioViewSet( class RadioSessionViewSet( mixins.CreateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet ): - serializer_class = serializers.RadioSessionSerializer queryset = models.RadioSession.objects.all() permission_classes = [] diff --git a/api/funkwhale_api/subsonic/views.py b/api/funkwhale_api/subsonic/views.py index 6674a5e7c..316cce706 100644 --- a/api/funkwhale_api/subsonic/views.py +++ b/api/funkwhale_api/subsonic/views.py @@ -387,7 +387,6 @@ class SubsonicViewSet(viewsets.GenericViewSet): try: offset = int(data.get("offset", 0)) except (TypeError, ValueError): - offset = 0 try: diff --git a/api/funkwhale_api/users/admin.py b/api/funkwhale_api/users/admin.py index b63cf6b59..b5c3bde36 100644 --- a/api/funkwhale_api/users/admin.py +++ b/api/funkwhale_api/users/admin.py @@ -14,7 +14,6 @@ class MyUserChangeForm(UserChangeForm): class MyUserCreationForm(UserCreationForm): - error_message = UserCreationForm.error_messages.update( {"duplicate_username": "This username has already been taken."} ) diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py index 8c233188d..ad9523c45 100644 --- a/api/funkwhale_api/users/models.py +++ b/api/funkwhale_api/users/models.py @@ -114,7 +114,6 @@ class UserManager(BaseUserManager): class User(AbstractUser): - # First Name and Last Name do not cover name patterns # around the globe. name = models.CharField(_("Name of User"), blank=True, max_length=255) diff --git a/api/funkwhale_api/users/oauth/permissions.py b/api/funkwhale_api/users/oauth/permissions.py index 49d4af892..1bae9a1f0 100644 --- a/api/funkwhale_api/users/oauth/permissions.py +++ b/api/funkwhale_api/users/oauth/permissions.py @@ -47,7 +47,6 @@ METHOD_SCOPE_MAPPING = { class ScopePermission(permissions.BasePermission): def has_permission(self, request, view): - if request.method.lower() in ["options", "head"]: return True @@ -103,7 +102,6 @@ class ScopePermission(permissions.BasePermission): ) def has_permission_token(self, token, required_scope): - if token.is_expired(): return False diff --git a/api/funkwhale_api/users/serializers.py b/api/funkwhale_api/users/serializers.py index 8fe904f54..67908f6b9 100644 --- a/api/funkwhale_api/users/serializers.py +++ b/api/funkwhale_api/users/serializers.py @@ -185,7 +185,6 @@ class UserWriteSerializer(serializers.ModelSerializer): class UserReadSerializer(serializers.ModelSerializer): - permissions = serializers.SerializerMethodField() full_username = serializers.SerializerMethodField() avatar = common_serializers.AttachmentSerializer(source="get_avatar") diff --git a/api/tests/audio/test_views.py b/api/tests/audio/test_views.py index 1efd80eb8..1a1e46d65 100644 --- a/api/tests/audio/test_views.py +++ b/api/tests/audio/test_views.py @@ -138,7 +138,6 @@ def test_channel_update_permission(logged_in_api_client, factories): def test_channel_delete(logged_in_api_client, factories, mocker): - actor = logged_in_api_client.user.create_actor() channel = factories["audio.Channel"](attributed_to=actor) @@ -336,7 +335,6 @@ def test_channel_rss_feed_authentication_required(factories, api_client, prefere def test_channel_metadata_choices(factories, api_client): - expected = { "language": [ {"value": code, "label": name} for code, name in locales.ISO_639_CHOICES diff --git a/api/tests/federation/test_activity.py b/api/tests/federation/test_activity.py index 996843688..2a54a1494 100644 --- a/api/tests/federation/test_activity.py +++ b/api/tests/federation/test_activity.py @@ -16,7 +16,6 @@ from funkwhale_api.federation import ( def test_receive_validates_basic_attributes_and_stores_activity( mrf_inbox_registry, factories, now, mocker ): - mocker.patch.object( activity.InboxRouter, "get_matching_handlers", return_value=True ) @@ -598,7 +597,6 @@ def test_prepare_deliveries_and_inbox_items_allow_list(factories, preferences): def test_prepare_deliveries_and_inbox_items_instances_with_followers(factories): - domain1 = factories["federation.Domain"](with_service_actor=True) domain2 = factories["federation.Domain"](with_service_actor=True) library = factories["music.Library"](actor__local=True) diff --git a/api/tests/federation/test_jsonld.py b/api/tests/federation/test_jsonld.py index 0d13597fd..0419b7648 100644 --- a/api/tests/federation/test_jsonld.py +++ b/api/tests/federation/test_jsonld.py @@ -237,7 +237,6 @@ async def test_fetch_many(a_responses): def test_dereference(): - followers_doc = { "@context": jsonld.get_default_context(), "id": "https://noop/federation/actors/demo/followers", diff --git a/api/tests/federation/test_routes.py b/api/tests/federation/test_routes.py index 6cf8f12cd..ae77f364e 100644 --- a/api/tests/federation/test_routes.py +++ b/api/tests/federation/test_routes.py @@ -401,7 +401,6 @@ def test_inbox_delete_library(factories): def test_inbox_delete_album(factories): - album = factories["music.Album"](attributed=True) payload = { "type": "Delete", diff --git a/api/tests/federation/test_third_party_activitypub.py b/api/tests/federation/test_third_party_activitypub.py index 8841aac96..faa929e00 100644 --- a/api/tests/federation/test_third_party_activitypub.py +++ b/api/tests/federation/test_third_party_activitypub.py @@ -4,7 +4,6 @@ from funkwhale_api.federation import routes, serializers def test_pleroma_actor_from_ap_with_tags(factories): - payload = { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -73,7 +72,6 @@ def test_pleroma_actor_from_ap_with_tags(factories): def test_pleroma_actor_from_ap(factories): - payload = { "@context": [ "https://www.w3.org/ns/activitystreams", diff --git a/api/tests/music/test_models.py b/api/tests/music/test_models.py index 253eca2e7..28af9182f 100644 --- a/api/tests/music/test_models.py +++ b/api/tests/music/test_models.py @@ -156,7 +156,6 @@ def test_import_track_with_different_artist_than_release(factories, mocker): "extension,mimetype", [("ogg", "audio/ogg"), ("mp3", "audio/mpeg")] ) def test_audio_track_mime_type(extension, mimetype, factories): - name = ".".join(["test", extension]) path = os.path.join(DATA_DIR, name) upload = factories["music.Upload"](audio_file__from_path=path, mimetype=None) @@ -166,7 +165,6 @@ def test_audio_track_mime_type(extension, mimetype, factories): @pytest.mark.parametrize("name", ["test.ogg", "test.mp3"]) def test_audio_track_checksum(name, factories): - path = os.path.join(DATA_DIR, name) upload = factories["music.Upload"](audio_file__from_path=path, mimetype=None) diff --git a/api/tests/radios/test_api.py b/api/tests/radios/test_api.py index 3b41dbc7e..4654f012b 100644 --- a/api/tests/radios/test_api.py +++ b/api/tests/radios/test_api.py @@ -135,7 +135,6 @@ def test_clean_config_is_called_on_serializer_save(mocker, factories): @pytest.mark.parametrize("radio_type", ["random", "less-listened", "favorites"]) def test_create_radio_session(radio_type, logged_in_api_client): - url = reverse("api:v1:radios:sessions-list") response = logged_in_api_client.post(url, {"radio_type": radio_type}) diff --git a/api/tests/radios/test_filters.py b/api/tests/radios/test_filters.py index d63ef7940..a75d7b5a7 100644 --- a/api/tests/radios/test_filters.py +++ b/api/tests/radios/test_filters.py @@ -2,7 +2,6 @@ from funkwhale_api.radios import filters def test_clean_config_artist_name_sorting(factories): - artist3 = factories["music.Artist"](name="The Green Eyes") artist2 = factories["music.Artist"](name="The Green Eyed Machine") artist1 = factories["music.Artist"](name="The Green Seed") @@ -21,7 +20,6 @@ def test_clean_config_artist_name_sorting(factories): def test_clean_config_tag_name_sorting(factories): - tag3 = factories["tags.Tag"](name="Rock") tag2 = factories["tags.Tag"](name="Classic") tag1 = factories["tags.Tag"](name="Punk") diff --git a/api/tests/radios/test_radios.py b/api/tests/radios/test_radios.py index 46cd5e2b6..edef108f4 100644 --- a/api/tests/radios/test_radios.py +++ b/api/tests/radios/test_radios.py @@ -419,7 +419,7 @@ def test_can_start_custom_multiple_radio_from_api(api_client, factories): tracks = factories["music.Track"].create_batch(5) url = reverse("api:v1:radios:sessions-list") map_filters_to_type = {"tags": "names", "artists": "ids", "playlists": "names"} - for (key, value) in map_filters_to_type.items(): + for key, value in map_filters_to_type.items(): attr = value[:-1] track_filter_key = [getattr(a.artist, attr) for a in tracks] config = {"filters": [{"type": key, value: track_filter_key}]} diff --git a/api/tests/test_test_utils.py b/api/tests/test_test_utils.py index a17b21856..301be25d1 100644 --- a/api/tests/test_test_utils.py +++ b/api/tests/test_test_utils.py @@ -2,5 +2,4 @@ from . import utils as test_utils def test_to_api_date(now): - assert test_utils.to_api_date(now) == now.isoformat().split("+")[0] + "Z" diff --git a/api/tests/users/oauth/test_scopes.py b/api/tests/users/oauth/test_scopes.py index e55b78319..c0e7488ba 100644 --- a/api/tests/users/oauth/test_scopes.py +++ b/api/tests/users/oauth/test_scopes.py @@ -187,5 +187,4 @@ from funkwhale_api.users.oauth import scopes ], ) def test_get_scopes_from_user_permissions(user_perms, expected): - assert scopes.get_from_permissions(**user_perms) == expected diff --git a/docs/get-releases-json.py b/docs/get-releases-json.py index 773106051..a668dc104 100755 --- a/docs/get-releases-json.py +++ b/docs/get-releases-json.py @@ -7,7 +7,6 @@ from distutils.version import StrictVersion def get_versions(): - output = subprocess.check_output( ["git", "tag", "-l", "--format=%(creatordate:iso-strict)|%(refname:short)"] ) @@ -16,7 +15,7 @@ def get_versions(): for line in output.decode().splitlines(): try: date, tag = line.split("|") - except (ValueError): + except ValueError: continue if not date or not tag: diff --git a/front/scripts/fix-fomantic-css.py b/front/scripts/fix-fomantic-css.py index 9266931e8..95f9940ec 100755 --- a/front/scripts/fix-fomantic-css.py +++ b/front/scripts/fix-fomantic-css.py @@ -267,7 +267,11 @@ REPLACEMENTS = { ("background", "var(--site-background)"), ("color", "var(--text-color)"), ], - ("::-webkit-selection", "::-moz-selection", "::selection",): [ + ( + "::-webkit-selection", + "::-moz-selection", + "::selection", + ): [ ("color", "var(--text-selection-color)"), ("background-color", "var(--text-selection-background)"), ], @@ -448,7 +452,10 @@ REPLACEMENTS = { ): [ ("color", "var(--input-focus-placeholder-color)"), ], - (".ui.form .field > label", ".ui.form .inline.fields .field > label",): [ + ( + ".ui.form .field > label", + ".ui.form .inline.fields .field > label", + ): [ ("color", "var(--form-label-color)"), ], }, @@ -779,7 +786,10 @@ REPLACEMENTS = { ".structured", "tablet stackable", ], - (".ui.table", ".ui.table > thead > tr > th",): [ + ( + ".ui.table", + ".ui.table > thead > tr > th", + ): [ ("color", "var(--text-color)"), ("background", "var(--table-background)"), ], From 87bf8f1c2b7e147f3cf3794f15dba645a1b26951 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 25 Jul 2023 18:04:36 +0000 Subject: [PATCH 06/50] chore(api): update dependency django to v3.2.20 --- api/poetry.lock | 8 ++++---- api/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/poetry.lock b/api/poetry.lock index 5347ba4e6..4deee437a 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -1056,14 +1056,14 @@ with-social = ["django-allauth (>=0.40.0,<0.53.0)"] [[package]] name = "django" -version = "3.2.19" +version = "3.2.20" description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "Django-3.2.19-py3-none-any.whl", hash = "sha256:21cc991466245d659ab79cb01204f9515690f8dae00e5eabde307f14d24d4d7d"}, - {file = "Django-3.2.19.tar.gz", hash = "sha256:031365bae96814da19c10706218c44dff3b654cc4de20a98bd2d29b9bde469f0"}, + {file = "Django-3.2.20-py3-none-any.whl", hash = "sha256:a477ab326ae7d8807dc25c186b951ab8c7648a3a23f9497763c37307a2b5ef87"}, + {file = "Django-3.2.20.tar.gz", hash = "sha256:dec2a116787b8e14962014bf78e120bba454135108e1af9e9b91ade7b2964c40"}, ] [package.dependencies] @@ -4003,4 +4003,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "3eebd3ca97c8b920d6b5795cfb8e7f08faabf4e6265ab63c2fbbf3de50b84e71" +content-hash = "9b7211882ccaae230eb5ecdcbb73ea2467467a5886980e8a6b1430fb76b2832e" diff --git a/api/pyproject.toml b/api/pyproject.toml index 68265abc4..c08405280 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -29,7 +29,7 @@ python = "^3.7" # Django dj-rest-auth = { extras = ["with_social"], version = "2.2.8" } -django = "==3.2.19" +django = "==3.2.20" django-allauth = "==0.42.0" django-cache-memoize = "0.1.10" django-cacheops = "==6.1" From 4b4815435c80413a34ffbf2aeeb80132008165a7 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 25 Jul 2023 20:35:11 +0000 Subject: [PATCH 07/50] chore(api): update dependency aiohttp to v3.8.5 Part-of: --- api/poetry.lock | 178 ++++++++++++++++++++++----------------------- api/pyproject.toml | 2 +- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/api/poetry.lock b/api/poetry.lock index 4deee437a..a7f70f443 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -2,99 +2,99 @@ [[package]] name = "aiohttp" -version = "3.8.4" +version = "3.8.5" description = "Async http client/server framework (asyncio)" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ce45967538fb747370308d3145aa68a074bdecb4f3a300869590f725ced69c1"}, - {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b744c33b6f14ca26b7544e8d8aadff6b765a80ad6164fb1a430bbadd593dfb1a"}, - {file = "aiohttp-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a45865451439eb320784918617ba54b7a377e3501fb70402ab84d38c2cd891b"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d42d7cba1cec432d47ab13b6637bee393a10f664c425ea7b305d1301ca1a3"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee3c36df21b5714d49fc4580247947aa64bcbe2939d1b77b4c8dcb8f6c9faecc"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:176a64b24c0935869d5bbc4c96e82f89f643bcdf08ec947701b9dbb3c956b7dd"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c844fd628851c0bc309f3c801b3a3d58ce430b2ce5b359cd918a5a76d0b20cb5"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5393fb786a9e23e4799fec788e7e735de18052f83682ce2dfcabaf1c00c2c08e"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e4b09863aae0dc965c3ef36500d891a3ff495a2ea9ae9171e4519963c12ceefd"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:adfbc22e87365a6e564c804c58fc44ff7727deea782d175c33602737b7feadb6"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:147ae376f14b55f4f3c2b118b95be50a369b89b38a971e80a17c3fd623f280c9"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:eafb3e874816ebe2a92f5e155f17260034c8c341dad1df25672fb710627c6949"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6cc15d58053c76eacac5fa9152d7d84b8d67b3fde92709195cb984cfb3475ea"}, - {file = "aiohttp-3.8.4-cp310-cp310-win32.whl", hash = "sha256:59f029a5f6e2d679296db7bee982bb3d20c088e52a2977e3175faf31d6fb75d1"}, - {file = "aiohttp-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:fe7ba4a51f33ab275515f66b0a236bcde4fb5561498fe8f898d4e549b2e4509f"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d8ef1a630519a26d6760bc695842579cb09e373c5f227a21b67dc3eb16cfea4"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b3f2e06a512e94722886c0827bee9807c86a9f698fac6b3aee841fab49bbfb4"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a80464982d41b1fbfe3154e440ba4904b71c1a53e9cd584098cd41efdb188ef"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b631e26df63e52f7cce0cce6507b7a7f1bc9b0c501fcde69742130b32e8782f"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f43255086fe25e36fd5ed8f2ee47477408a73ef00e804cb2b5cba4bf2ac7f5e"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d347a172f866cd1d93126d9b239fcbe682acb39b48ee0873c73c933dd23bd0f"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3fec6a4cb5551721cdd70473eb009d90935b4063acc5f40905d40ecfea23e05"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a37fe8f7c1e6ce8f2d9c411676e4bc633a8462844e38f46156d07a7d401654"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d1e6a862b76f34395a985b3cd39a0d949ca80a70b6ebdea37d3ab39ceea6698a"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd468460eefef601ece4428d3cf4562459157c0f6523db89365202c31b6daebb"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:618c901dd3aad4ace71dfa0f5e82e88b46ef57e3239fc7027773cb6d4ed53531"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:652b1bff4f15f6287550b4670546a2947f2a4575b6c6dff7760eafb22eacbf0b"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80575ba9377c5171407a06d0196b2310b679dc752d02a1fcaa2bc20b235dbf24"}, - {file = "aiohttp-3.8.4-cp311-cp311-win32.whl", hash = "sha256:bbcf1a76cf6f6dacf2c7f4d2ebd411438c275faa1dc0c68e46eb84eebd05dd7d"}, - {file = "aiohttp-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:6e74dd54f7239fcffe07913ff8b964e28b712f09846e20de78676ce2a3dc0bfc"}, - {file = "aiohttp-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:880e15bb6dad90549b43f796b391cfffd7af373f4646784795e20d92606b7a51"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb96fa6b56bb536c42d6a4a87dfca570ff8e52de2d63cabebfd6fb67049c34b6"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a6cadebe132e90cefa77e45f2d2f1a4b2ce5c6b1bfc1656c1ddafcfe4ba8131"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f352b62b45dff37b55ddd7b9c0c8672c4dd2eb9c0f9c11d395075a84e2c40f75"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ab43061a0c81198d88f39aaf90dae9a7744620978f7ef3e3708339b8ed2ef01"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9cb1565a7ad52e096a6988e2ee0397f72fe056dadf75d17fa6b5aebaea05622"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1b3ea7edd2d24538959c1c1abf97c744d879d4e541d38305f9bd7d9b10c9ec41"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7c7837fe8037e96b6dd5cfcf47263c1620a9d332a87ec06a6ca4564e56bd0f36"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3b90467ebc3d9fa5b0f9b6489dfb2c304a1db7b9946fa92aa76a831b9d587e99"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:cab9401de3ea52b4b4c6971db5fb5c999bd4260898af972bf23de1c6b5dd9d71"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d1f9282c5f2b5e241034a009779e7b2a1aa045f667ff521e7948ea9b56e0c5ff"}, - {file = "aiohttp-3.8.4-cp36-cp36m-win32.whl", hash = "sha256:5e14f25765a578a0a634d5f0cd1e2c3f53964553a00347998dfdf96b8137f777"}, - {file = "aiohttp-3.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4c745b109057e7e5f1848c689ee4fb3a016c8d4d92da52b312f8a509f83aa05e"}, - {file = "aiohttp-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aede4df4eeb926c8fa70de46c340a1bc2c6079e1c40ccf7b0eae1313ffd33519"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddaae3f3d32fc2cb4c53fab020b69a05c8ab1f02e0e59665c6f7a0d3a5be54f"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4eb3b82ca349cf6fadcdc7abcc8b3a50ab74a62e9113ab7a8ebc268aad35bb9"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bcb89336efa095ea21b30f9e686763f2be4478f1b0a616969551982c4ee4c3b"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c08e8ed6fa3d477e501ec9db169bfac8140e830aa372d77e4a43084d8dd91ab"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6cd05ea06daca6ad6a4ca3ba7fe7dc5b5de063ff4daec6170ec0f9979f6c332"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7a00a9ed8d6e725b55ef98b1b35c88013245f35f68b1b12c5cd4100dddac333"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:de04b491d0e5007ee1b63a309956eaed959a49f5bb4e84b26c8f5d49de140fa9"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:40653609b3bf50611356e6b6554e3a331f6879fa7116f3959b20e3528783e699"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dbf3a08a06b3f433013c143ebd72c15cac33d2914b8ea4bea7ac2c23578815d6"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854f422ac44af92bfe172d8e73229c270dc09b96535e8a548f99c84f82dde241"}, - {file = "aiohttp-3.8.4-cp37-cp37m-win32.whl", hash = "sha256:aeb29c84bb53a84b1a81c6c09d24cf33bb8432cc5c39979021cc0f98c1292a1a"}, - {file = "aiohttp-3.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:db3fc6120bce9f446d13b1b834ea5b15341ca9ff3f335e4a951a6ead31105480"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fabb87dd8850ef0f7fe2b366d44b77d7e6fa2ea87861ab3844da99291e81e60f"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91f6d540163f90bbaef9387e65f18f73ffd7c79f5225ac3d3f61df7b0d01ad15"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d265f09a75a79a788237d7f9054f929ced2e69eb0bb79de3798c468d8a90f945"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d89efa095ca7d442a6d0cbc755f9e08190ba40069b235c9886a8763b03785da"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dac314662f4e2aa5009977b652d9b8db7121b46c38f2073bfeed9f4049732cd"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe11310ae1e4cd560035598c3f29d86cef39a83d244c7466f95c27ae04850f10"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ddb2a2026c3f6a68c3998a6c47ab6795e4127315d2e35a09997da21865757f8"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e75b89ac3bd27d2d043b234aa7b734c38ba1b0e43f07787130a0ecac1e12228a"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6e601588f2b502c93c30cd5a45bfc665faaf37bbe835b7cfd461753068232074"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a5d794d1ae64e7753e405ba58e08fcfa73e3fad93ef9b7e31112ef3c9a0efb52"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a1f4689c9a1462f3df0a1f7e797791cd6b124ddbee2b570d34e7f38ade0e2c71"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3032dcb1c35bc330134a5b8a5d4f68c1a87252dfc6e1262c65a7e30e62298275"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8189c56eb0ddbb95bfadb8f60ea1b22fcfa659396ea36f6adcc521213cd7b44d"}, - {file = "aiohttp-3.8.4-cp38-cp38-win32.whl", hash = "sha256:33587f26dcee66efb2fff3c177547bd0449ab7edf1b73a7f5dea1e38609a0c54"}, - {file = "aiohttp-3.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:e595432ac259af2d4630008bf638873d69346372d38255774c0e286951e8b79f"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a7bdf9e57126dc345b683c3632e8ba317c31d2a41acd5800c10640387d193ed"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22f6eab15b6db242499a16de87939a342f5a950ad0abaf1532038e2ce7d31567"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7235604476a76ef249bd64cb8274ed24ccf6995c4a8b51a237005ee7a57e8643"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea9eb976ffdd79d0e893869cfe179a8f60f152d42cb64622fca418cd9b18dc2a"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92c0cea74a2a81c4c76b62ea1cac163ecb20fb3ba3a75c909b9fa71b4ad493cf"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:493f5bc2f8307286b7799c6d899d388bbaa7dfa6c4caf4f97ef7521b9cb13719"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a63f03189a6fa7c900226e3ef5ba4d3bd047e18f445e69adbd65af433add5a2"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10c8cefcff98fd9168cdd86c4da8b84baaa90bf2da2269c6161984e6737bf23e"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bca5f24726e2919de94f047739d0a4fc01372801a3672708260546aa2601bf57"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:03baa76b730e4e15a45f81dfe29a8d910314143414e528737f8589ec60cf7391"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8c29c77cc57e40f84acef9bfb904373a4e89a4e8b74e71aa8075c021ec9078c2"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:03543dcf98a6619254b409be2d22b51f21ec66272be4ebda7b04e6412e4b2e14"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17b79c2963db82086229012cff93ea55196ed31f6493bb1ccd2c62f1724324e4"}, - {file = "aiohttp-3.8.4-cp39-cp39-win32.whl", hash = "sha256:34ce9f93a4a68d1272d26030655dd1b58ff727b3ed2a33d80ec433561b03d67a"}, - {file = "aiohttp-3.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:41a86a69bb63bb2fc3dc9ad5ea9f10f1c9c8e282b471931be0268ddd09430b04"}, - {file = "aiohttp-3.8.4.tar.gz", hash = "sha256:bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a94159871304770da4dd371f4291b20cac04e8c94f11bdea1c3478e557fbe0d8"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:13bf85afc99ce6f9ee3567b04501f18f9f8dbbb2ea11ed1a2e079670403a7c84"}, + {file = "aiohttp-3.8.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ce2ac5708501afc4847221a521f7e4b245abf5178cf5ddae9d5b3856ddb2f3a"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96943e5dcc37a6529d18766597c491798b7eb7a61d48878611298afc1fca946c"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ad5c3c4590bb3cc28b4382f031f3783f25ec223557124c68754a2231d989e2b"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c413c633d0512df4dc7fd2373ec06cc6a815b7b6d6c2f208ada7e9e93a5061d"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df72ac063b97837a80d80dec8d54c241af059cc9bb42c4de68bd5b61ceb37caa"}, + {file = "aiohttp-3.8.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c48c5c0271149cfe467c0ff8eb941279fd6e3f65c9a388c984e0e6cf57538e14"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:368a42363c4d70ab52c2c6420a57f190ed3dfaca6a1b19afda8165ee16416a82"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7607ec3ce4993464368505888af5beb446845a014bc676d349efec0e05085905"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0d21c684808288a98914e5aaf2a7c6a3179d4df11d249799c32d1808e79503b5"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:312fcfbacc7880a8da0ae8b6abc6cc7d752e9caa0051a53d217a650b25e9a691"}, + {file = "aiohttp-3.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad093e823df03bb3fd37e7dec9d4670c34f9e24aeace76808fc20a507cace825"}, + {file = "aiohttp-3.8.5-cp310-cp310-win32.whl", hash = "sha256:33279701c04351a2914e1100b62b2a7fdb9a25995c4a104259f9a5ead7ed4802"}, + {file = "aiohttp-3.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:6e4a280e4b975a2e7745573e3fc9c9ba0d1194a3738ce1cbaa80626cc9b4f4df"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae871a964e1987a943d83d6709d20ec6103ca1eaf52f7e0d36ee1b5bebb8b9b9"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:461908b2578955045efde733719d62f2b649c404189a09a632d245b445c9c975"}, + {file = "aiohttp-3.8.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:72a860c215e26192379f57cae5ab12b168b75db8271f111019509a1196dfc780"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc14be025665dba6202b6a71cfcdb53210cc498e50068bc088076624471f8bb9"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af740fc2711ad85f1a5c034a435782fbd5b5f8314c9a3ef071424a8158d7f6b"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:841cd8233cbd2111a0ef0a522ce016357c5e3aff8a8ce92bcfa14cef890d698f"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed1c46fb119f1b59304b5ec89f834f07124cd23ae5b74288e364477641060ff"}, + {file = "aiohttp-3.8.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84f8ae3e09a34f35c18fa57f015cc394bd1389bce02503fb30c394d04ee6b938"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62360cb771707cb70a6fd114b9871d20d7dd2163a0feafe43fd115cfe4fe845e"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:23fb25a9f0a1ca1f24c0a371523546366bb642397c94ab45ad3aedf2941cec6a"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0ba0d15164eae3d878260d4c4df859bbdc6466e9e6689c344a13334f988bb53"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5d20003b635fc6ae3f96d7260281dfaf1894fc3aa24d1888a9b2628e97c241e5"}, + {file = "aiohttp-3.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0175d745d9e85c40dcc51c8f88c74bfbaef9e7afeeeb9d03c37977270303064c"}, + {file = "aiohttp-3.8.5-cp311-cp311-win32.whl", hash = "sha256:2e1b1e51b0774408f091d268648e3d57f7260c1682e7d3a63cb00d22d71bb945"}, + {file = "aiohttp-3.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:043d2299f6dfdc92f0ac5e995dfc56668e1587cea7f9aa9d8a78a1b6554e5755"}, + {file = "aiohttp-3.8.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cae533195e8122584ec87531d6df000ad07737eaa3c81209e85c928854d2195c"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f21e83f355643c345177a5d1d8079f9f28b5133bcd154193b799d380331d5d3"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a75ef35f2df54ad55dbf4b73fe1da96f370e51b10c91f08b19603c64004acc"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e2e9839e14dd5308ee773c97115f1e0a1cb1d75cbeeee9f33824fa5144c7634"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44e65da1de4403d0576473e2344828ef9c4c6244d65cf4b75549bb46d40b8dd"}, + {file = "aiohttp-3.8.5-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d847e4cde6ecc19125ccbc9bfac4a7ab37c234dd88fbb3c5c524e8e14da543"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c7a815258e5895d8900aec4454f38dca9aed71085f227537208057853f9d13f2"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:8b929b9bd7cd7c3939f8bcfffa92fae7480bd1aa425279d51a89327d600c704d"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5db3a5b833764280ed7618393832e0853e40f3d3e9aa128ac0ba0f8278d08649"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:a0215ce6041d501f3155dc219712bc41252d0ab76474615b9700d63d4d9292af"}, + {file = "aiohttp-3.8.5-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:fd1ed388ea7fbed22c4968dd64bab0198de60750a25fe8c0c9d4bef5abe13824"}, + {file = "aiohttp-3.8.5-cp36-cp36m-win32.whl", hash = "sha256:6e6783bcc45f397fdebc118d772103d751b54cddf5b60fbcc958382d7dd64f3e"}, + {file = "aiohttp-3.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:b5411d82cddd212644cf9360879eb5080f0d5f7d809d03262c50dad02f01421a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:01d4c0c874aa4ddfb8098e85d10b5e875a70adc63db91f1ae65a4b04d3344cda"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5980a746d547a6ba173fd5ee85ce9077e72d118758db05d229044b469d9029a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a482e6da906d5e6e653be079b29bc173a48e381600161c9932d89dfae5942ef"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80bd372b8d0715c66c974cf57fe363621a02f359f1ec81cba97366948c7fc873"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1161b345c0a444ebcf46bf0a740ba5dcf50612fd3d0528883fdc0eff578006a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd56db019015b6acfaaf92e1ac40eb8434847d9bf88b4be4efe5bfd260aee692"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:153c2549f6c004d2754cc60603d4668899c9895b8a89397444a9c4efa282aaf4"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4a01951fabc4ce26ab791da5f3f24dca6d9a6f24121746eb19756416ff2d881b"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bfb9162dcf01f615462b995a516ba03e769de0789de1cadc0f916265c257e5d8"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:7dde0009408969a43b04c16cbbe252c4f5ef4574ac226bc8815cd7342d2028b6"}, + {file = "aiohttp-3.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4149d34c32f9638f38f544b3977a4c24052042affa895352d3636fa8bffd030a"}, + {file = "aiohttp-3.8.5-cp37-cp37m-win32.whl", hash = "sha256:68c5a82c8779bdfc6367c967a4a1b2aa52cd3595388bf5961a62158ee8a59e22"}, + {file = "aiohttp-3.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2cf57fb50be5f52bda004b8893e63b48530ed9f0d6c96c84620dc92fe3cd9b9d"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:eca4bf3734c541dc4f374ad6010a68ff6c6748f00451707f39857f429ca36ced"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1274477e4c71ce8cfe6c1ec2f806d57c015ebf84d83373676036e256bc55d690"}, + {file = "aiohttp-3.8.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:28c543e54710d6158fc6f439296c7865b29e0b616629767e685a7185fab4a6b9"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:910bec0c49637d213f5d9877105d26e0c4a4de2f8b1b29405ff37e9fc0ad52b8"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5443910d662db951b2e58eb70b0fbe6b6e2ae613477129a5805d0b66c54b6cb7"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e460be6978fc24e3df83193dc0cc4de46c9909ed92dd47d349a452ef49325b7"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb1558def481d84f03b45888473fc5a1f35747b5f334ef4e7a571bc0dfcb11f8"}, + {file = "aiohttp-3.8.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34dd0c107799dcbbf7d48b53be761a013c0adf5571bf50c4ecad5643fe9cfcd0"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aa1990247f02a54185dc0dff92a6904521172a22664c863a03ff64c42f9b5410"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0e584a10f204a617d71d359fe383406305a4b595b333721fa50b867b4a0a1548"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a3cf433f127efa43fee6b90ea4c6edf6c4a17109d1d037d1a52abec84d8f2e42"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c11f5b099adafb18e65c2c997d57108b5bbeaa9eeee64a84302c0978b1ec948b"}, + {file = "aiohttp-3.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:84de26ddf621d7ac4c975dbea4c945860e08cccde492269db4e1538a6a6f3c35"}, + {file = "aiohttp-3.8.5-cp38-cp38-win32.whl", hash = "sha256:ab88bafedc57dd0aab55fa728ea10c1911f7e4d8b43e1d838a1739f33712921c"}, + {file = "aiohttp-3.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:5798a9aad1879f626589f3df0f8b79b3608a92e9beab10e5fda02c8a2c60db2e"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a6ce61195c6a19c785df04e71a4537e29eaa2c50fe745b732aa937c0c77169f3"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:773dd01706d4db536335fcfae6ea2440a70ceb03dd3e7378f3e815b03c97ab51"}, + {file = "aiohttp-3.8.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f83a552443a526ea38d064588613aca983d0ee0038801bc93c0c916428310c28"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f7372f7341fcc16f57b2caded43e81ddd18df53320b6f9f042acad41f8e049a"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea353162f249c8097ea63c2169dd1aa55de1e8fecbe63412a9bc50816e87b761"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d47ae48db0b2dcf70bc8a3bc72b3de86e2a590fc299fdbbb15af320d2659de"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d827176898a2b0b09694fbd1088c7a31836d1a505c243811c87ae53a3f6273c1"}, + {file = "aiohttp-3.8.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3562b06567c06439d8b447037bb655ef69786c590b1de86c7ab81efe1c9c15d8"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e874cbf8caf8959d2adf572a78bba17cb0e9d7e51bb83d86a3697b686a0ab4d"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6809a00deaf3810e38c628e9a33271892f815b853605a936e2e9e5129762356c"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:33776e945d89b29251b33a7e7d006ce86447b2cfd66db5e5ded4e5cd0340585c"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eaeed7abfb5d64c539e2db173f63631455f1196c37d9d8d873fc316470dfbacd"}, + {file = "aiohttp-3.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e91d635961bec2d8f19dfeb41a539eb94bd073f075ca6dae6c8dc0ee89ad6f91"}, + {file = "aiohttp-3.8.5-cp39-cp39-win32.whl", hash = "sha256:00ad4b6f185ec67f3e6562e8a1d2b69660be43070bd0ef6fcec5211154c7df67"}, + {file = "aiohttp-3.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:c0a9034379a37ae42dea7ac1e048352d96286626251862e448933c0f59cbd79c"}, + {file = "aiohttp-3.8.5.tar.gz", hash = "sha256:b9552ec52cc147dbf1944ac7ac98af7602e51ea2dcd076ed194ca3c0d1c7d0bc"}, ] [package.dependencies] @@ -4003,4 +4003,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "9b7211882ccaae230eb5ecdcbb73ea2467467a5886980e8a6b1430fb76b2832e" +content-hash = "a0cda10a5e4e05bcef83824fcdc7c03003377099ca8d868b5a89852bdf302cf8" diff --git a/api/pyproject.toml b/api/pyproject.toml index c08405280..b6f9f6a33 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -66,7 +66,7 @@ gunicorn = "==20.1.0" uvicorn = { version = "==0.20.0", extras = ["standard"] } # Libs -aiohttp = "==3.8.4" +aiohttp = "==3.8.5" arrow = "==1.2.3" bleach = "==5.0.1" boto3 = "==1.26.161" From 9625732b083a2c25ef416e5d2e18a488cefab984 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Thu, 20 Jul 2023 12:52:41 +0200 Subject: [PATCH 08/50] fix(queue): clear shuffled id list when queue is cleared Part-of: --- changes/changelog.d/2192.bugfix | 1 + front/src/composables/audio/queue.ts | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 changes/changelog.d/2192.bugfix diff --git a/changes/changelog.d/2192.bugfix b/changes/changelog.d/2192.bugfix new file mode 100644 index 000000000..c43afc485 --- /dev/null +++ b/changes/changelog.d/2192.bugfix @@ -0,0 +1 @@ +Clear shuffled id list on queue clear (#2192) diff --git a/front/src/composables/audio/queue.ts b/front/src/composables/audio/queue.ts index f0eeb72e4..dd415a371 100644 --- a/front/src/composables/audio/queue.ts +++ b/front/src/composables/audio/queue.ts @@ -329,6 +329,10 @@ export const useQueue = createGlobalState(() => { clearRadio.value = true const lastTracks = [...tracks.value] + + // Clear shuffled tracks + shuffledIds.value.length = 0 + tracks.value.length = 0 await delMany(lastTracks) From 4525d083af70dd97dd03b8ebbe336f6a07f8ea8d Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Tue, 25 Jul 2023 14:25:44 +0200 Subject: [PATCH 09/50] fix: avoid sending language settings multiple times Part-of: --- front/src/store/ui.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/front/src/store/ui.ts b/front/src/store/ui.ts index 56ff605b8..9baf941ce 100644 --- a/front/src/store/ui.ts +++ b/front/src/store/ui.ts @@ -225,7 +225,9 @@ const store: Module = { commit('notifications', { type: 'pendingReviewRequests', count: response.data.count }) }, - async currentLanguage ({ commit, rootState }, value) { + async currentLanguage ({ commit, rootState, state }, value) { + if (state.selectedLanguage && state.currentLanguage === value) return + commit('currentLanguage', value) if (rootState.auth.authenticated) { await axios.post('users/settings', { language: value }) From 93bf644d2c2eb814047df716f4a13efa128327e9 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Tue, 25 Jul 2023 14:28:35 +0200 Subject: [PATCH 10/50] fix(front): resolve initialization race condition Part-of: --- .../resolve-axios-race-condition.bugfix | 2 + front/src/main.ts | 43 +++++++++++++------ 2 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 changes/changelog.d/resolve-axios-race-condition.bugfix diff --git a/changes/changelog.d/resolve-axios-race-condition.bugfix b/changes/changelog.d/resolve-axios-race-condition.bugfix new file mode 100644 index 000000000..11d7b7e46 --- /dev/null +++ b/changes/changelog.d/resolve-axios-race-condition.bugfix @@ -0,0 +1,2 @@ +Resolve race condition regarding axios when initializing the frontend +Prevent sending same language setting to backend multiple times diff --git a/front/src/main.ts b/front/src/main.ts index d7ffdbb7d..b9bb82224 100644 --- a/front/src/main.ts +++ b/front/src/main.ts @@ -1,4 +1,4 @@ -import type { InitModule } from '~/types' +import type { InitModule, InitModuleContext } from '~/types' import store, { key } from '~/store' import router from '~/router' @@ -22,6 +22,7 @@ const app = createApp({ data: () => ({ ready: false }), mounted () { this.ready = true + logger.info('Everything loaded!') }, render () { if (this.ready) { @@ -35,19 +36,35 @@ const app = createApp({ app.use(router) app.use(store, key) -const modules: Array> = [] -for (const module of Object.values(import.meta.glob('./init/*.ts', { eager: true })) as { install?: InitModule }[]) { - modules.push(module.install?.({ - app, - router, - store - })) +const modules: Record = import.meta.glob('./init/*.ts', { eager: true }) +const moduleContext: InitModuleContext = { + app, + router, + store } -// Wait for all modules to load -Promise.all(modules).finally(() => { - app.mount('#app') - logger.info('Everything loaded!') -}) +// NOTE: Other modules may depend on network requests and we need to ensure +// that all axios interceptors are set before any requests are made +// and that the instance url is set before any requests are made +const IMPORTANT_MODULES_QUEUE = ['axios', 'instance'] +const waitForImportantModules = async () => { + for (const moduleName of IMPORTANT_MODULES_QUEUE) { + const path = `./init/${moduleName}.ts` + if (!(path in modules)) { + logger.error(`Failed to load important module: ${path}`) + continue + } + + await modules[path].install?.(moduleContext) + delete modules[path] + } +} + +waitForImportantModules() + // NOTE: We load the modules in parallel + .then(() => Promise.all(Object.values(modules).map(module => module.install?.(moduleContext)))) + .catch(error => logger.error('Failed to load modules:', error)) + // NOTE: We need to mount the app after all modules are loaded + .finally(() => app.mount('#app')) // TODO (wvffle): Rename filters from useSharedLabels to filters from backend From c01031945f77dbcc334d54abaeac40e716213123 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 26 Jul 2023 08:06:11 +0000 Subject: [PATCH 11/50] chore(api): update dependency click to v8.1.6 Part-of: --- api/poetry.lock | 8 ++++---- api/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/poetry.lock b/api/poetry.lock index a7f70f443..8c3750f40 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -742,14 +742,14 @@ files = [ [[package]] name = "click" -version = "8.1.5" +version = "8.1.6" description = "Composable command line interface toolkit" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.5-py3-none-any.whl", hash = "sha256:e576aa487d679441d7d30abb87e1b43d24fc53bffb8758443b1a9e1cee504548"}, - {file = "click-8.1.5.tar.gz", hash = "sha256:4be4b1af8d665c6d942909916d31a213a106800c47d0eeba73d34da3cbc11367"}, + {file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"}, + {file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"}, ] [package.dependencies] @@ -4003,4 +4003,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "a0cda10a5e4e05bcef83824fcdc7c03003377099ca8d868b5a89852bdf302cf8" +content-hash = "f35e143d5fb86e57f21c01e9a60f44e6498d377237175b5bb4dd461c38124d62" diff --git a/api/pyproject.toml b/api/pyproject.toml index b6f9f6a33..4010b6f11 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -70,7 +70,7 @@ aiohttp = "==3.8.5" arrow = "==1.2.3" bleach = "==5.0.1" boto3 = "==1.26.161" -click = "==8.1.5" +click = "==8.1.6" cryptography = "==38.0.4" feedparser = "==6.0.10" musicbrainzngs = "==0.7.1" From b59e29883f2e277493ad8b8944551b9267d92f19 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Tue, 25 Jul 2023 16:32:24 +0200 Subject: [PATCH 12/50] feat(front): use logger instead of console.log Part-of: --- front/src/api/player.ts | 20 +-- front/src/components/Home.vue | 4 +- front/src/components/RemoteSearchForm.vue | 4 +- front/src/components/admin/SettingsGroup.vue | 13 +- front/src/components/auth/ApplicationNew.vue | 5 +- front/src/components/auth/SignupForm.vue | 2 +- front/src/components/common/ContentForm.vue | 6 +- front/src/components/favorites/List.vue | 4 +- front/src/components/library/AlbumBase.vue | 5 +- front/src/components/library/Albums.vue | 4 +- front/src/components/library/Artists.vue | 4 +- front/src/components/library/Home.vue | 4 +- front/src/components/library/Podcasts.vue | 4 +- front/src/components/library/Radios.vue | 4 +- .../manage/moderation/ReportCard.vue | 6 +- front/src/composables/audio/player.ts | 9 +- front/src/composables/audio/queue.ts | 12 +- front/src/composables/audio/tracks.ts | 11 +- front/src/composables/audio/visualizer.ts | 8 +- .../src/composables/navigation/useOrdering.ts | 1 - front/src/composables/onKeyboardShortcut.ts | 5 +- front/src/composables/useLogger.ts | 126 ++++++++++++++++-- front/src/init/axios.ts | 2 +- front/src/init/webSocket.ts | 5 +- front/src/router/guards.ts | 7 +- front/src/store/auth.ts | 6 +- front/src/store/ui.ts | 6 +- front/src/views/Search.vue | 6 +- .../views/admin/moderation/ReportsList.vue | 5 +- front/src/views/content/remote/Card.vue | 5 +- front/src/views/playlists/List.vue | 4 +- 31 files changed, 235 insertions(+), 72 deletions(-) diff --git a/front/src/api/player.ts b/front/src/api/player.ts index 53c72d5a0..97b91a851 100644 --- a/front/src/api/player.ts +++ b/front/src/api/player.ts @@ -4,6 +4,10 @@ import { createEventHook, refDefault, type EventHookOn, useEventListener } from import { createAudioSource } from '~/composables/audio/audio-api' import { effectScope, reactive, ref, type Ref } from 'vue' +import useLogger from '~/composables/useLogger' + +const logger = useLogger() + export interface SoundSource { uuid: string mimetype: string @@ -73,7 +77,7 @@ export class HTMLSound implements Sound { this.#audio.src = source this.#audio.preload = 'auto' - console.log('CREATED SOUND INSTANCE', this) + logger.log('CREATED SOUND INSTANCE', this) this.#scope.run(() => { useEventListener(this.#audio, 'ended', () => this.#soundEndEventHook.trigger(this)) @@ -84,19 +88,19 @@ export class HTMLSound implements Sound { }) useEventListener(this.#audio, 'waiting', () => { - console.log('>> AUDIO WAITING', this) + logger.log('>> AUDIO WAITING', this) }) useEventListener(this.#audio, 'playing', () => { - console.log('>> AUDIO PLAYING', this) + logger.log('>> AUDIO PLAYING', this) }) useEventListener(this.#audio, 'stalled', () => { - console.log('>> AUDIO STALLED', this) + logger.log('>> AUDIO STALLED', this) }) useEventListener(this.#audio, 'suspend', () => { - console.log('>> AUDIO SUSPEND', this) + logger.log('>> AUDIO SUSPEND', this) }) useEventListener(this.#audio, 'loadeddata', () => { @@ -106,7 +110,7 @@ export class HTMLSound implements Sound { useEventListener(this.#audio, 'error', (err) => { if (this.#ignoreError) return - console.error('>> AUDIO ERRORED', err, this) + logger.error('>> AUDIO ERRORED', err, this) this.isErrored.value = true this.isLoaded.value = true }) @@ -116,7 +120,7 @@ export class HTMLSound implements Sound { async preload () { this.isDisposed.value = false this.isErrored.value = false - console.log('CALLING PRELOAD ON', this) + logger.log('CALLING PRELOAD ON', this) this.#audio.load() } @@ -141,7 +145,7 @@ export class HTMLSound implements Sound { try { await this.#audio.play() } catch (err) { - console.error('>> AUDIO PLAY ERROR', err, this) + logger.error('>> AUDIO PLAY ERROR', err, this) this.isErrored.value = true } } diff --git a/front/src/components/Home.vue b/front/src/components/Home.vue index 7cabd3cc6..23e16ea77 100644 --- a/front/src/components/Home.vue +++ b/front/src/components/Home.vue @@ -5,6 +5,7 @@ import ChannelsWidget from '~/components/audio/ChannelsWidget.vue' import LoginForm from '~/components/auth/LoginForm.vue' import SignupForm from '~/components/auth/SignupForm.vue' import useMarkdown from '~/composables/useMarkdown' +import useLogger from '~/composables/useLogger' import { humanSize } from '~/utils/filters' import { useStore } from '~/store' import { computed } from 'vue' @@ -18,6 +19,7 @@ const labels = computed(() => ({ })) const store = useStore() +const logger = useLogger() const nodeinfo = computed(() => store.state.instance.nodeinfo) const podName = computed(() => get(nodeinfo.value, 'metadata.nodeName') || 'Funkwhale') @@ -54,7 +56,7 @@ const headerStyle = computed(() => { // TODO (wvffle): Check if needed const router = useRouter() whenever(() => store.state.auth.authenticated, () => { - console.log('Authenticated, redirecting to /library…') + logger.log('Authenticated, redirecting to /library…') router.push('/library') }) diff --git a/front/src/components/RemoteSearchForm.vue b/front/src/components/RemoteSearchForm.vue index 7d3859d71..00e0c858b 100644 --- a/front/src/components/RemoteSearchForm.vue +++ b/front/src/components/RemoteSearchForm.vue @@ -9,6 +9,7 @@ import { useStore } from '~/store' import axios from 'axios' import updateQueryString from '~/composables/updateQueryString' +import useLogger from '~/composables/useLogger' type Type = 'rss' | 'artists' | 'both' @@ -37,6 +38,7 @@ const type = ref(props.initialType) const id = ref(props.initialId) const errors = ref([] as string[]) +const logger = useLogger() const { t } = useI18n() const labels = computed(() => ({ title: type.value === 'rss' @@ -102,7 +104,7 @@ const submit = () => { const isLoading = ref(false) const createFetch = async () => { - console.log(id.value, props.standalone) + logger.debug(id.value, props.standalone) if (!id.value) return if (props.standalone) { history.replaceState(history.state, '', updateQueryString(location.href, 'id', id.value)) diff --git a/front/src/components/admin/SettingsGroup.vue b/front/src/components/admin/SettingsGroup.vue index 609dd8a6e..ae05e1e48 100644 --- a/front/src/components/admin/SettingsGroup.vue +++ b/front/src/components/admin/SettingsGroup.vue @@ -18,15 +18,16 @@ const values = reactive({} as Record) const result = ref(null) const errors = ref([] as string[]) -const fileRefs = reactive({} as Record) -const setFileRef = (identifier: string) => (el: FunctionRef) => { - console.log(el) - fileRefs[identifier] = el as HTMLInputElement -} - const logger = useLogger() const store = useStore() +// TODO (wvffle): Use VueUse +const fileRefs = reactive({} as Record) +const setFileRef = (identifier: string) => (el: FunctionRef) => { + logger.debug(el) + fileRefs[identifier] = el as HTMLInputElement +} + const settings = computed(() => { const byIdentifier = props.settingsData.reduce((acc, entry) => { acc[entry.identifier] = entry diff --git a/front/src/components/auth/ApplicationNew.vue b/front/src/components/auth/ApplicationNew.vue index b099263fd..9cb2ac956 100644 --- a/front/src/components/auth/ApplicationNew.vue +++ b/front/src/components/auth/ApplicationNew.vue @@ -9,6 +9,8 @@ import { useStore } from '~/store' import ApplicationForm from '~/components/auth/ApplicationForm.vue' +import useLogger from '~/composables/useLogger' + interface Props { name?: string scopes?: string @@ -27,6 +29,7 @@ const defaults = reactive({ redirectUris: props.redirectUris }) +const logger = useLogger() const { t } = useI18n() const labels = computed(() => ({ title: t('components.auth.ApplicationNew.title') @@ -37,7 +40,7 @@ const store = useStore() const created = (application: Application) => { store.state.auth.applicationSecret = application.client_secret - console.log(application) + logger.debug(application) return router.push({ name: 'settings.applications.edit', params: { diff --git a/front/src/components/auth/SignupForm.vue b/front/src/components/auth/SignupForm.vue index e08cbb1a7..71c37543c 100644 --- a/front/src/components/auth/SignupForm.vue +++ b/front/src/components/auth/SignupForm.vue @@ -42,7 +42,7 @@ const labels = computed(() => ({ const signupRequiresApproval = computed(() => props.signupApprovalEnabled ?? store.state.instance.settings.moderation.signup_approval_enabled.value) const formCustomization = computed(() => props.customization ?? store.state.instance.settings.moderation.signup_form_customization.value) -watchEffect(() => console.log(store.state.instance.settings.moderation.signup_approval_enabled.value)) +watchEffect(() => logger.debug(store.state.instance.settings.moderation.signup_approval_enabled.value)) const payload = reactive({ username: '', diff --git a/front/src/components/common/ContentForm.vue b/front/src/components/common/ContentForm.vue index 3905cdb55..afa02f994 100644 --- a/front/src/components/common/ContentForm.vue +++ b/front/src/components/common/ContentForm.vue @@ -4,6 +4,8 @@ import { useVModel, watchDebounced, useTextareaAutosize, syncRef } from '@vueuse import { ref, computed, watchEffect, onMounted, nextTick, watch } from 'vue' import { useI18n } from 'vue-i18n' +import useLogger from '~/composables/useLogger' + interface Events { (e: 'update:modelValue', value: string): void } @@ -26,6 +28,8 @@ const props = withDefaults(defineProps(), { required: false }) +const logger = useLogger() + const { t } = useI18n() const { textarea, input } = useTextareaAutosize() const value = useVModel(props, 'modelValue', emit) @@ -47,7 +51,7 @@ const loadPreview = async () => { const response = await axios.post('text-preview/', { text: value.value, permissive: props.permissive }) preview.value = response.data.rendered } catch (error) { - console.error(error) + logger.error(error) } isLoadingPreview.value = false } diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 83f6b23a0..cd6a7f540 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -65,7 +65,7 @@ const fetchFavorites = async () => { } try { - logger.time('Loading user favorites') + const stop = logger.time('Loading user favorites') const response = await axios.get('tracks/', { params }) results.length = 0 @@ -81,7 +81,7 @@ const fetchFavorites = async () => { } catch (error) { useErrorHandler(error as Error) } finally { - logger.timeEnd('Loading user favorites') + stop() isLoading.value = false } } diff --git a/front/src/components/library/AlbumBase.vue b/front/src/components/library/AlbumBase.vue index 257d4a9e7..a03100672 100644 --- a/front/src/components/library/AlbumBase.vue +++ b/front/src/components/library/AlbumBase.vue @@ -15,6 +15,7 @@ import TagsList from '~/components/tags/List.vue' import AlbumDropdown from './AlbumDropdown.vue' import useErrorHandler from '~/composables/useErrorHandler' +import useLogger from '~/composables/useLogger' interface Events { (e: 'deleted'): void @@ -39,6 +40,8 @@ const isSerie = computed(() => object.value?.artist.content_category === 'podcas const totalDuration = computed(() => sum((object.value?.tracks ?? []).map(track => track.uploads[0]?.duration ?? 0))) const publicLibraries = computed(() => libraries.value?.filter(library => library.privacy_level === 'everyone') ?? []) +const logger = useLogger() + const { t } = useI18n() const labels = computed(() => ({ title: t('components.library.AlbumBase.title') @@ -93,7 +96,7 @@ const fetchTracks = async () => { tracks.push(...response.data.results) } } catch (error) { - console.error(error) + logger.error(error) } finally { isLoadingTracks.value = false } diff --git a/front/src/components/library/Albums.vue b/front/src/components/library/Albums.vue index aab3ef9f3..db9f64271 100644 --- a/front/src/components/library/Albums.vue +++ b/front/src/components/library/Albums.vue @@ -72,7 +72,7 @@ const fetchData = async () => { content_category: 'music' } - logger.time('Fetching albums') + const stop = logger.time('Fetching albums') try { const response = await axios.get('albums/', { params, @@ -86,7 +86,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - logger.timeEnd('Fetching albums') + stop() isLoading.value = false } } diff --git a/front/src/components/library/Artists.vue b/front/src/components/library/Artists.vue index 4bfd1935b..8b2e99d7c 100644 --- a/front/src/components/library/Artists.vue +++ b/front/src/components/library/Artists.vue @@ -73,7 +73,7 @@ const fetchData = async () => { has_albums: excludeCompilation.value } - logger.time('Fetching artists') + const stop = logger.time('Fetching artists') try { const response = await axios.get('artists/', { params, @@ -87,7 +87,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - logger.timeEnd('Fetching artists') + stop() isLoading.value = false } } diff --git a/front/src/components/library/Home.vue b/front/src/components/library/Home.vue index 8ff6b2552..c2bd01223 100644 --- a/front/src/components/library/Home.vue +++ b/front/src/components/library/Home.vue @@ -32,7 +32,7 @@ const labels = computed(() => ({ const isLoading = ref(false) const fetchData = async () => { isLoading.value = true - logger.time('Loading latest artists') + const stop = logger.time('Loading latest artists') const params = { ordering: '-creation_date', @@ -47,7 +47,7 @@ const fetchData = async () => { } isLoading.value = false - logger.timeEnd('Loading latest artists') + stop() } fetchData() diff --git a/front/src/components/library/Podcasts.vue b/front/src/components/library/Podcasts.vue index c01ee6a1c..35a9e4596 100644 --- a/front/src/components/library/Podcasts.vue +++ b/front/src/components/library/Podcasts.vue @@ -74,7 +74,7 @@ const fetchData = async () => { content_category: 'podcast' } - logger.time('Fetching podcasts') + const stop = logger.time('Fetching podcasts') try { const response = await axios.get('artists/', { params, @@ -88,7 +88,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - logger.timeEnd('Fetching podcasts') + stop() isLoading.value = false } } diff --git a/front/src/components/library/Radios.vue b/front/src/components/library/Radios.vue index 9ebb1a02b..145f91116 100644 --- a/front/src/components/library/Radios.vue +++ b/front/src/components/library/Radios.vue @@ -64,7 +64,7 @@ const fetchData = async () => { ordering: orderingString.value } - logger.time('Fetching radios') + const stop = logger.time('Fetching radios') try { const response = await axios.get('radios/radios/', { params @@ -75,7 +75,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - logger.timeEnd('Fetching radios') + stop() isLoading.value = false } } diff --git a/front/src/components/manage/moderation/ReportCard.vue b/front/src/components/manage/moderation/ReportCard.vue index 8305710ab..c68989b40 100644 --- a/front/src/components/manage/moderation/ReportCard.vue +++ b/front/src/components/manage/moderation/ReportCard.vue @@ -15,6 +15,7 @@ import NoteForm from '~/components/manage/moderation/NoteForm.vue' import useReportConfigs from '~/composables/moderation/useReportConfigs' import useErrorHandler from '~/composables/useErrorHandler' import useMarkdown from '~/composables/useMarkdown' +import useLogger from '~/composables/useLogger' interface Events { (e: 'updated', updating: { type: string }): void @@ -29,6 +30,7 @@ const emit = defineEmits() const props = defineProps() const configs = useReportConfigs() +const logger = useLogger() const obj = ref(props.initObj) const summary = useMarkdown(() => obj.value.summary ?? '') @@ -77,11 +79,11 @@ const actions = computed(() => { handler: async () => { try { await axios.delete(deleteUrl) - console.log('Target deleted') + logger.info('Target deleted') obj.value.target = undefined resolveReport(true) } catch (error) { - console.log('Error while deleting target', error) + logger.error('Error while deleting target', error) useErrorHandler(error as Error) } } diff --git a/front/src/composables/audio/player.ts b/front/src/composables/audio/player.ts index d2704e9e4..e9291b3f7 100644 --- a/front/src/composables/audio/player.ts +++ b/front/src/composables/audio/player.ts @@ -9,6 +9,8 @@ import { useStore } from '~/store' import axios from 'axios' import { useClamp } from '@vueuse/math' +import useLogger from '~/composables/useLogger' + // Looping export enum LoopingMode { None, @@ -17,7 +19,6 @@ export enum LoopingMode { } // Pausing - export enum PauseReason { UserInput, EndOfQueue, @@ -26,6 +27,8 @@ export enum PauseReason { EndOfRadio } +const logger = useLogger() + const MODE_MAX = 1 + Math.max(...Object.values(LoopingMode).filter(mode => typeof mode === 'number') as number[]) export const looping: Ref = useStorage('player:looping', LoopingMode.None) @@ -131,12 +134,12 @@ export const usePlayer = createGlobalState(() => { const trackListenSubmissions = () => { const store = useStore() whenever(listenSubmitted, async () => { - console.log('Listening submitted!') + logger.log('Listening submitted!') if (!store.state.auth.authenticated) return if (!currentTrack.value) return await axios.post('history/listenings/', { track: currentTrack.value.id }) - .catch((error) => console.error('Could not record track in history', error)) + .catch((error) => logger.error('Could not record track in history', error)) }) } diff --git a/front/src/composables/audio/queue.ts b/front/src/composables/audio/queue.ts index dd415a371..b906612a4 100644 --- a/front/src/composables/audio/queue.ts +++ b/front/src/composables/audio/queue.ts @@ -11,6 +11,8 @@ import { delMany, getMany, setMany } from '~/composables/data/indexedDB' import { setGain } from '~/composables/audio/audio-api' import { useTracks } from '~/composables/audio/tracks' +import useLogger from '~/composables/useLogger' + import axios from 'axios' export interface QueueTrackSource { @@ -36,6 +38,8 @@ export interface QueueTrack { sources: QueueTrackSource[] } +const logger = useLogger() + // Queue const tracks = useStorage('queue:tracks', [] as number[]) const shuffledIds = useStorage('queue:tracks:shuffled', [] as number[]) @@ -69,7 +73,7 @@ watchEffect(async () => { tracksById.set(track.id, track) } } catch (error) { - console.error(error) + logger.error(error) } finally { fetchingTracks.value = false } @@ -344,7 +348,7 @@ export const useQueue = createGlobalState(() => { const store = useStore() watchEffect(() => { if (store.state.radios.running && currentIndex.value === tracks.value.length - 1) { - console.log('POPULATING QUEUE FROM RADIO') + logger.log('POPULATING QUEUE FROM RADIO') return store.dispatch('radios/populateQueue') } }) @@ -379,7 +383,7 @@ export const useQueue = createGlobalState(() => { currentIndex.value = index delete localStorage.queue - })().catch((error) => console.error('Could not successfully migrate between queue versions', error)) + })().catch((error) => logger.error('Could not successfully migrate between queue versions', error)) } if (localStorage.player) { @@ -389,7 +393,7 @@ export const useQueue = createGlobalState(() => { setGain(volume ?? 0.7) delete localStorage.player } catch (error) { - console.error('Could not successfully migrate between player versions', error) + logger.error('Could not successfully migrate between player versions', error) } } } diff --git a/front/src/composables/audio/tracks.ts b/front/src/composables/audio/tracks.ts index 95b1214bb..8ea991867 100644 --- a/front/src/composables/audio/tracks.ts +++ b/front/src/composables/audio/tracks.ts @@ -11,6 +11,7 @@ import { useQueue } from '~/composables/audio/queue' import { soundImplementation } from '~/api/player' import useLRUCache from '~/composables/data/useLRUCache' +import useLogger from '~/composables/useLogger' import store from '~/store' import axios from 'axios' @@ -18,6 +19,8 @@ import axios from 'axios' const ALLOWED_PLAY_TYPES: (CanPlayTypeResult | undefined)[] = ['maybe', 'probably'] const AUDIO_ELEMENT = document.createElement('audio') +const logger = useLogger() + const soundPromises = new Map>() const soundCache = useLRUCache({ max: 3, @@ -95,7 +98,7 @@ export const useTracks = createGlobalState(() => { const sound = new SoundImplementation(sources) sound.onSoundEnd(() => { - console.log('TRACK ENDED, PLAYING NEXT') + logger.log('TRACK ENDED, PLAYING NEXT') // NOTE: We push it to the end of the job queue setTimeout(() => playNext(), 0) @@ -140,7 +143,7 @@ export const useTracks = createGlobalState(() => { return sound } - console.log('NO TRACK IN CACHE, CREATING', track) + logger.log('NO TRACK IN CACHE, CREATING', track) const soundPromise = createSoundPromise() soundPromises.set(track.id, soundPromise) return soundPromise @@ -171,7 +174,7 @@ export const useTracks = createGlobalState(() => { const { queue, currentIndex } = useQueue() if (queue.value.length <= index || index === -1) return - console.log('LOADING TRACK', index) + logger.log('LOADING TRACK', index) const track = queue.value[index] const sound = await createSound(track) @@ -181,7 +184,7 @@ export const useTracks = createGlobalState(() => { return } - console.log('CONNECTING NODE', sound) + logger.log('CONNECTING NODE', sound) sound.audioNode.disconnect() connectAudioSource(sound.audioNode) diff --git a/front/src/composables/audio/visualizer.ts b/front/src/composables/audio/visualizer.ts index e59f23e13..14c518a29 100644 --- a/front/src/composables/audio/visualizer.ts +++ b/front/src/composables/audio/visualizer.ts @@ -4,6 +4,8 @@ import { AUDIO_CONTEXT, GAIN_NODE } from './audio-api' import { useResizeObserver, useStorage } from '@vueuse/core' import { watchEffect, ref, markRaw } from 'vue' +import useLogger from '~/composables/useLogger' + // @ts-expect-error butterchurn has no typings import butterchurnPresets from 'butterchurn-presets' @@ -11,6 +13,8 @@ import butterchurnPresets from 'butterchurn-presets' import butterchurn from 'butterchurn' export const useMilkDrop = (canvas: Ref) => { + const logger = useLogger() + const presets = Object.keys(butterchurnPresets) const visualizer = ref() @@ -24,7 +28,7 @@ export const useMilkDrop = (canvas: Ref) => { const name = presetName.value if (name === undefined) return - console.log(`Switching to preset: '${name}'`) + logger.log(`Switching to preset: '${name}'`) visualizer.value?.loadPreset(butterchurnPresets[name], 1) }) @@ -67,7 +71,7 @@ export const useMilkDrop = (canvas: Ref) => { try { visualizer.value?.render() } catch (error) { - console.error(error) + logger.error(error) loadRandomPreset() } } diff --git a/front/src/composables/navigation/useOrdering.ts b/front/src/composables/navigation/useOrdering.ts index edb02cff1..d712cf06b 100644 --- a/front/src/composables/navigation/useOrdering.ts +++ b/front/src/composables/navigation/useOrdering.ts @@ -34,7 +34,6 @@ export default (props: OrderingProps) => { }) const queryOrdering = useRouteQuery('ordering', perfOrderingDirection.value + perfOrdering.value) - console.log(queryOrdering.value) watch(queryOrdering, (ordering) => { perfOrderingDirection.value = ordering[0] === '-' ? '-' : '+' diff --git a/front/src/composables/onKeyboardShortcut.ts b/front/src/composables/onKeyboardShortcut.ts index 2f066775e..b54d428d3 100644 --- a/front/src/composables/onKeyboardShortcut.ts +++ b/front/src/composables/onKeyboardShortcut.ts @@ -2,6 +2,8 @@ import { DefaultMagicKeysAliasMap, tryOnScopeDispose, useEventListener } from '@ import { isEqual, isMatch } from 'lodash-es' import { reactive } from 'vue' +import useLogger from './useLogger' + type KeyFilter = string | string[] interface Entry { @@ -10,6 +12,7 @@ interface Entry { __location?: string } +const logger = useLogger() const combinations = reactive(new Map()) const current = new Set() @@ -59,7 +62,7 @@ export default (key: KeyFilter, handler: () => unknown, prevent = false) => { } if (collisions.length) { - console.warn([ + logger.warn([ 'onKeyboardShortcut detected a possible collision in:', `${entry.__location}: ${combination.join(' + ')}`, ...collisions diff --git a/front/src/composables/useLogger.ts b/front/src/composables/useLogger.ts index 660c79385..e6d3942e6 100644 --- a/front/src/composables/useLogger.ts +++ b/front/src/composables/useLogger.ts @@ -1,11 +1,119 @@ -import Logger from 'js-logger' +// import Logger from 'js-logger' +// +// Logger.useDefaults({ +// defaultLevel: import.meta.env.DEV +// ? Logger.DEBUG +// : Logger.WARN +// }) +// +// export default (logger?: string) => logger +// ? Logger.get(logger) +// : Logger -Logger.useDefaults({ - defaultLevel: import.meta.env.DEV - ? Logger.DEBUG - : Logger.WARN -}) +type LogLevel = 'info' | 'warn' | 'error' | 'debug' | 'time' -export default (logger?: string) => logger - ? Logger.get(logger) - : Logger +const LOG_LEVEL_LABELS: Record = { + info: ' INFO', + warn: ' WARN', + error: 'ERROR', + debug: 'DEBUG', + time: ' TIME' +} + +const LOG_LEVEL_BACKGROUND: Record = { + info: '#a6e22e', + warn: '#FF9800', + error: '#F44336', + debug: '#00BCD4', + time: '#00BCD4' +} + +const LOG_LEVEL_COLOR: Record = { + info: '#000', + warn: '#000', + error: '#fff', + debug: '#000', + time: '#000' +} + +const TIMESTAMP_COLOR = '#9E9E9E' + +const FILETYPE_BACKGROUND: Record = { + js: '#f1e05a', + ts: '#2b7489', + vue: '#41b883', + html: '#e34c26', + default: '#ccc' +} + +const FILETYPE_COLOR: Record = { + js: '#000', + ts: '#fff', + vue: '#fff', + html: '#fff', + default: '#000' +} + +const getFile = () => { + const { stack } = new Error() + const line = stack?.split('\n')[2] ?? '' + const [, method, url, lineNo] = line.match(/^(\w+)?(?:\/<)*@(.+?)(?:\?.*)?:(\d+):\d+$/) ?? [] + const file = url.startsWith(location.origin) ? url.slice(location.origin.length) : url + return { method, file, lineNo } +} + +// NOTE: We're pushing all logs to the end of the event loop +const createLoggerFn = (level: LogLevel) => { + return (...args: any[]) => { + const timestamp = new Date().toUTCString() + const { method, file, lineNo } = getFile() + + const ext = file?.split('.').pop() ?? 'default' + + // NOTE: Don't log time and debug in production + if (level === 'time' || level === 'debug') { + if (import.meta.env.PROD) return + } + + console[level === 'time' ? 'debug' : level]( + '%c %c [%s] %c %s %c%s', + `background: ${LOG_LEVEL_BACKGROUND[level]};border-radius:1em`, + `color: ${TIMESTAMP_COLOR}`, + timestamp, + `background: ${LOG_LEVEL_BACKGROUND[level]}; color: ${LOG_LEVEL_COLOR[level]}; border-radius: 1em 0 0 1em`, + LOG_LEVEL_LABELS[level], + `background: ${FILETYPE_BACKGROUND[ext]}; color: ${FILETYPE_COLOR[ext]}; border-radius: 0 1em 1em 0`, + method !== undefined + ? ` ${file}:${lineNo} ${method}() ` + : ` ${file}:${lineNo} `, + ...args + ) + } +} + +const infoLogger = createLoggerFn('info') +const warnLogger = createLoggerFn('warn') +const timeLogger = createLoggerFn('time') + +const errorLogger = createLoggerFn('error') +const debugLogger = createLoggerFn('debug') + +export const logger = { + log: infoLogger, + info: infoLogger, + warn: warnLogger, + error: errorLogger, + debug: debugLogger, + time: (label: string) => { + const now = performance.now() + + timeLogger(`${label}: start`) + + return () => { + const duration = performance.now() - now + timeLogger(`${label}: ${duration.toFixed(2)}ms`) + } + } +} + +export default () => logger diff --git a/front/src/init/axios.ts b/front/src/init/axios.ts index 6b474fd14..35d17deb1 100644 --- a/front/src/init/axios.ts +++ b/front/src/init/axios.ts @@ -118,7 +118,7 @@ export const install: InitModule = ({ store, router }) => { const refreshAuth = async (failedRequest: AxiosError) => { if (store.state.auth.oauth.accessToken) { - console.log('Failed request, refreshing auth…') + logger.warn('Failed request, refreshing auth…') try { // maybe the token was expired, let's try to refresh it diff --git a/front/src/init/webSocket.ts b/front/src/init/webSocket.ts index b8fe0c151..0033a893f 100644 --- a/front/src/init/webSocket.ts +++ b/front/src/init/webSocket.ts @@ -3,9 +3,12 @@ import type { InitModule } from '~/types' import { watchEffect, watch } from 'vue' import { useWebSocket, whenever } from '@vueuse/core' import useWebSocketHandler from '~/composables/useWebSocketHandler' +import useLogger from '~/composables/useLogger' import { CLIENT_RADIOS } from '~/utils/clientRadios' export const install: InitModule = ({ store }) => { + const logger = useLogger() + watch(() => store.state.instance.instanceUrl, () => { const url = store.getters['instance/absoluteUrl']('api/v1/activity') .replace(/^http/, 'ws') @@ -25,7 +28,7 @@ export const install: InitModule = ({ store }) => { }) watchEffect(() => { - console.log('Websocket status:', status.value) + logger.log('Websocket status:', status.value) }) }, { immediate: true }) diff --git a/front/src/router/guards.ts b/front/src/router/guards.ts index f9084416a..46804b98c 100644 --- a/front/src/router/guards.ts +++ b/front/src/router/guards.ts @@ -1,20 +1,23 @@ import type { NavigationGuardNext, RouteLocationNamedRaw, RouteLocationNormalized } from 'vue-router' import type { Permission } from '~/store/auth' +import useLogger from '~/composables/useLogger' import store from '~/store' +const logger = useLogger() + export const hasPermissions = (permission: Permission) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { if (store.state.auth.authenticated && store.state.auth.availablePermissions[permission]) { return next() } - console.log('Not authenticated. Redirecting to library.') + logger.warn('Not authenticated. Redirecting to library.') next({ name: 'library.index' }) } export const requireLoggedIn = (fallbackLocation?: RouteLocationNamedRaw) => (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => { if (store.state.auth.authenticated) return next() - console.log('!', to) + logger.debug('!', to) return next(fallbackLocation ?? { name: 'login', query: { next: to.fullPath } }) } diff --git a/front/src/store/auth.ts b/front/src/store/auth.ts index a8b581890..d2a3f1530 100644 --- a/front/src/store/auth.ts +++ b/front/src/store/auth.ts @@ -168,7 +168,7 @@ const store: Module = { try { await axios.post('users/logout') } catch (error) { - console.log('Error while logging out, probably logged in via oauth') + logger.error('Error while logging out, probably logged in via oauth', error) } const modules = [ @@ -249,11 +249,11 @@ const store: Module = { const redirectUri = encodeURIComponent(`${location.origin}/auth/callback`) const params = `response_type=code&scope=${encodeURIComponent(NEEDED_SCOPES)}&redirect_uri=${redirectUri}&state=${next}&client_id=${state.oauth.clientId}` const authorizeUrl = `${rootState.instance.instanceUrl}authorize?${params}` - console.log('Redirecting user...', authorizeUrl) + logger.log('Redirecting user...', authorizeUrl) window.location.href = authorizeUrl }, async handleOauthCallback ({ state, commit, dispatch }, authorizationCode) { - console.log('Fetching token...') + logger.log('Fetching token...') const payload = { client_id: state.oauth.clientId, client_secret: state.oauth.clientSecret, diff --git a/front/src/store/ui.ts b/front/src/store/ui.ts index 9baf941ce..f7ad005df 100644 --- a/front/src/store/ui.ts +++ b/front/src/store/ui.ts @@ -5,6 +5,8 @@ import type { SUPPORTED_LOCALES } from '~/init/locale' import axios from 'axios' import moment from 'moment' +import useLogger from '~/composables/useLogger' + type SupportedExtension = 'flac' | 'ogg' | 'mp3' | 'opus' | 'aac' | 'm4a' | 'aiff' | 'aif' export type WebSocketEventName = 'inbox.item_added' | 'import.status_updated' | 'mutation.created' | 'mutation.updated' @@ -50,6 +52,8 @@ export interface State { websocketEventsHandlers: Record } +const logger = useLogger() + const store: Module = { namespaced: true, state: { @@ -236,7 +240,7 @@ const store: Module = { websocketEvent ({ state }, event: WebSocketEvent) { const handlers = state.websocketEventsHandlers[event.type] - console.log('Dispatching websocket event', event, handlers) + logger.log('Dispatching websocket event', event, handlers) if (!handlers) { return } diff --git a/front/src/views/Search.vue b/front/src/views/Search.vue index f187894cc..4288e5d97 100644 --- a/front/src/views/Search.vue +++ b/front/src/views/Search.vue @@ -19,6 +19,7 @@ import RadioCard from '~/components/radios/Card.vue' import TagsList from '~/components/tags/List.vue' import useErrorHandler from '~/composables/useErrorHandler' +import useLogger from '~/composables/useLogger' type QueryType = 'artists' | 'albums' | 'tracks' | 'playlists' | 'tags' | 'radios' | 'podcasts' | 'series' | 'rss' @@ -35,6 +36,8 @@ syncRef(pageQuery, page, { direction: 'both' }) +const logger = useLogger() + const q = useRouteQuery('q', '') const query = ref(q.value) syncRef(q, query, { direction: 'ltr' }) @@ -209,8 +212,7 @@ const radioConfig = computed(() => { } as RadioConfig } - // TODO (wvffle): Use logger - console.info('This type is not yet supported for radio') + logger.warn('This type is not yet supported for radio') } return null diff --git a/front/src/views/admin/moderation/ReportsList.vue b/front/src/views/admin/moderation/ReportsList.vue index 40e40e7b9..d1ab1d1e0 100644 --- a/front/src/views/admin/moderation/ReportsList.vue +++ b/front/src/views/admin/moderation/ReportsList.vue @@ -20,6 +20,7 @@ import useSharedLabels from '~/composables/locale/useSharedLabels' import useOrdering from '~/composables/navigation/useOrdering' import useErrorHandler from '~/composables/useErrorHandler' import usePage from '~/composables/navigation/usePage' +import useLogger from '~/composables/useLogger' interface Props extends SmartSearchProps, OrderingProps { mode?: 'card' @@ -37,6 +38,8 @@ const props = withDefaults(defineProps(), { orderingConfigName: undefined }) +const logger = useLogger() + const search = ref() const page = usePage() @@ -68,7 +71,7 @@ const fetchData = async () => { result.value = response.data if (query.value === 'resolved:no') { - console.log('Refreshing sidebar notifications') + logger.log('Refreshing sidebar notifications') store.commit('ui/incrementNotifications', { type: 'pendingReviewReports', value: response.data.count diff --git a/front/src/views/content/remote/Card.vue b/front/src/views/content/remote/Card.vue index 5ed2fa0eb..ef95ba805 100644 --- a/front/src/views/content/remote/Card.vue +++ b/front/src/views/content/remote/Card.vue @@ -12,6 +12,7 @@ import RadioButton from '~/components/radios/Button.vue' import useErrorHandler from '~/composables/useErrorHandler' import useReport from '~/composables/moderation/useReport' +import useLogger from '~/composables/useLogger' interface Emits { (e: 'followed'): void @@ -31,6 +32,8 @@ const props = withDefaults(defineProps(), { displayCopyFid: true }) +const logger = useLogger() + const { report, getReportableObjects } = useReport() const store = useStore() @@ -80,7 +83,7 @@ const follow = async () => { library.value.follow = response.data emit('followed') } catch (error) { - console.error(error) + logger.error(error) store.commit('ui/addMessage', { content: t('views.content.remote.Card.error.follow', { error }), date: new Date() diff --git a/front/src/views/playlists/List.vue b/front/src/views/playlists/List.vue index feba0aeb9..99e4d74be 100644 --- a/front/src/views/playlists/List.vue +++ b/front/src/views/playlists/List.vue @@ -65,7 +65,7 @@ const fetchData = async () => { playable: true } - logger.time('Fetching albums') + const stop = logger.time('Fetching albums') try { const response = await axios.get('playlists/', { params @@ -76,7 +76,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - logger.timeEnd('Fetching albums') + stop() isLoading.value = false } } From d1f9a99e1b35876bcb1b44330e33d0cf9f32c2b6 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Tue, 25 Jul 2023 16:37:48 +0200 Subject: [PATCH 13/50] chore(front): remove unused dependency and add eslint rule to prevent console usage Part-of: --- changes/changelog.d/use-logger.enchancement | 1 + front/.eslintrc.js | 3 +++ front/package.json | 1 - front/src/components/favorites/List.vue | 2 +- front/src/composables/useLogger.ts | 13 +------------ front/yarn.lock | 5 ----- 6 files changed, 6 insertions(+), 19 deletions(-) create mode 100644 changes/changelog.d/use-logger.enchancement diff --git a/changes/changelog.d/use-logger.enchancement b/changes/changelog.d/use-logger.enchancement new file mode 100644 index 000000000..afc450ba8 --- /dev/null +++ b/changes/changelog.d/use-logger.enchancement @@ -0,0 +1 @@ +Use logger composable instead of window.console diff --git a/front/.eslintrc.js b/front/.eslintrc.js index c9ea0eb18..6a2ecc376 100644 --- a/front/.eslintrc.js +++ b/front/.eslintrc.js @@ -26,6 +26,9 @@ module.exports = { // NOTE: Nicer for the eye 'operator-linebreak': ['error', 'before'], + // NOTE: We have a logger instance + 'no-console': 'error', + // NOTE: Handled by typescript '@typescript-eslint/no-unused-vars': 'off', 'no-use-before-define': 'off', diff --git a/front/package.json b/front/package.json index 24fc09dcf..fbb5f8438 100644 --- a/front/package.json +++ b/front/package.json @@ -34,7 +34,6 @@ "fomantic-ui-css": "2.9.2", "howler": "2.2.3", "idb-keyval": "6.2.1", - "js-logger": "1.6.1", "lodash-es": "4.17.21", "lru-cache": "7.14.1", "moment": "2.29.4", diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index cd6a7f540..1c917fc6e 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -64,8 +64,8 @@ const fetchFavorites = async () => { ordering: orderingString.value } + const stop = logger.time('Loading user favorites') try { - const stop = logger.time('Loading user favorites') const response = await axios.get('tracks/', { params }) results.length = 0 diff --git a/front/src/composables/useLogger.ts b/front/src/composables/useLogger.ts index e6d3942e6..169bc7867 100644 --- a/front/src/composables/useLogger.ts +++ b/front/src/composables/useLogger.ts @@ -1,15 +1,3 @@ -// import Logger from 'js-logger' -// -// Logger.useDefaults({ -// defaultLevel: import.meta.env.DEV -// ? Logger.DEBUG -// : Logger.WARN -// }) -// -// export default (logger?: string) => logger -// ? Logger.get(logger) -// : Logger - type LogLevel = 'info' | 'warn' | 'error' | 'debug' | 'time' const LOG_LEVEL_LABELS: Record = { @@ -75,6 +63,7 @@ const createLoggerFn = (level: LogLevel) => { if (import.meta.env.PROD) return } + // eslint-disable-next-line no-console console[level === 'time' ? 'debug' : level]( '%c %c [%s] %c %s %c%s', `background: ${LOG_LEVEL_BACKGROUND[level]};border-radius:1em`, diff --git a/front/yarn.lock b/front/yarn.lock index 300baf3dc..09d25409c 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -4334,11 +4334,6 @@ jquery@^3.4.0: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612" integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ== -js-logger@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/js-logger/-/js-logger-1.6.1.tgz#8f09671b515e4a6f31dced8fdb8923432e2c60af" - integrity sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA== - js-sdsl@^4.1.4: version "4.4.1" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.1.tgz#9e3c7b566d8d9a7e1fe8fc26d00b5ab0f8918ab3" From 9abdcb5ff7104e440d27013515b0a9f70773150c Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Wed, 26 Jul 2023 10:02:53 +0000 Subject: [PATCH 14/50] refactor(front): rename logger timing stop functions to `measureLoading` Part-of: --- front/src/components/favorites/List.vue | 4 ++-- front/src/components/library/Albums.vue | 4 ++-- front/src/components/library/Artists.vue | 4 ++-- front/src/components/library/Home.vue | 4 ++-- front/src/components/library/Podcasts.vue | 4 ++-- front/src/components/library/Radios.vue | 4 ++-- front/src/views/playlists/List.vue | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/front/src/components/favorites/List.vue b/front/src/components/favorites/List.vue index 1c917fc6e..c14d2b0e5 100644 --- a/front/src/components/favorites/List.vue +++ b/front/src/components/favorites/List.vue @@ -64,7 +64,7 @@ const fetchFavorites = async () => { ordering: orderingString.value } - const stop = logger.time('Loading user favorites') + const measureLoading = logger.time('Loading user favorites') try { const response = await axios.get('tracks/', { params }) @@ -81,7 +81,7 @@ const fetchFavorites = async () => { } catch (error) { useErrorHandler(error as Error) } finally { - stop() + measureLoading() isLoading.value = false } } diff --git a/front/src/components/library/Albums.vue b/front/src/components/library/Albums.vue index db9f64271..1e3f5c6b6 100644 --- a/front/src/components/library/Albums.vue +++ b/front/src/components/library/Albums.vue @@ -72,7 +72,7 @@ const fetchData = async () => { content_category: 'music' } - const stop = logger.time('Fetching albums') + const measureLoading = logger.time('Fetching albums') try { const response = await axios.get('albums/', { params, @@ -86,7 +86,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - stop() + measureLoading() isLoading.value = false } } diff --git a/front/src/components/library/Artists.vue b/front/src/components/library/Artists.vue index 8b2e99d7c..17f38ee3e 100644 --- a/front/src/components/library/Artists.vue +++ b/front/src/components/library/Artists.vue @@ -73,7 +73,7 @@ const fetchData = async () => { has_albums: excludeCompilation.value } - const stop = logger.time('Fetching artists') + const measureLoading = logger.time('Fetching artists') try { const response = await axios.get('artists/', { params, @@ -87,7 +87,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - stop() + measureLoading() isLoading.value = false } } diff --git a/front/src/components/library/Home.vue b/front/src/components/library/Home.vue index c2bd01223..49109f610 100644 --- a/front/src/components/library/Home.vue +++ b/front/src/components/library/Home.vue @@ -32,7 +32,7 @@ const labels = computed(() => ({ const isLoading = ref(false) const fetchData = async () => { isLoading.value = true - const stop = logger.time('Loading latest artists') + const measureLoading = logger.time('Loading latest artists') const params = { ordering: '-creation_date', @@ -47,7 +47,7 @@ const fetchData = async () => { } isLoading.value = false - stop() + measureLoading() } fetchData() diff --git a/front/src/components/library/Podcasts.vue b/front/src/components/library/Podcasts.vue index 35a9e4596..0925a802d 100644 --- a/front/src/components/library/Podcasts.vue +++ b/front/src/components/library/Podcasts.vue @@ -74,7 +74,7 @@ const fetchData = async () => { content_category: 'podcast' } - const stop = logger.time('Fetching podcasts') + const measureLoading = logger.time('Fetching podcasts') try { const response = await axios.get('artists/', { params, @@ -88,7 +88,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - stop() + measureLoading() isLoading.value = false } } diff --git a/front/src/components/library/Radios.vue b/front/src/components/library/Radios.vue index 145f91116..f12b41b39 100644 --- a/front/src/components/library/Radios.vue +++ b/front/src/components/library/Radios.vue @@ -64,7 +64,7 @@ const fetchData = async () => { ordering: orderingString.value } - const stop = logger.time('Fetching radios') + const measureLoading = logger.time('Fetching radios') try { const response = await axios.get('radios/radios/', { params @@ -75,7 +75,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - stop() + measureLoading() isLoading.value = false } } diff --git a/front/src/views/playlists/List.vue b/front/src/views/playlists/List.vue index 99e4d74be..bcd463bf7 100644 --- a/front/src/views/playlists/List.vue +++ b/front/src/views/playlists/List.vue @@ -65,7 +65,7 @@ const fetchData = async () => { playable: true } - const stop = logger.time('Fetching albums') + const measureLoading = logger.time('Fetching albums') try { const response = await axios.get('playlists/', { params @@ -76,7 +76,7 @@ const fetchData = async () => { useErrorHandler(error as Error) result.value = undefined } finally { - stop() + measureLoading() isLoading.value = false } } From b719e5eb2c0d80aba4e93b63a1d0007a9e53c48d Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 26 Jul 2023 10:05:30 +0000 Subject: [PATCH 15/50] chore(api): update dependency markdown to v3.4.4 Part-of: --- api/poetry.lock | 9 +++++---- api/pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/api/poetry.lock b/api/poetry.lock index 8c3750f40..34ed06c86 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -2040,20 +2040,21 @@ source = ["Cython (>=0.29.7)"] [[package]] name = "markdown" -version = "3.4.3" +version = "3.4.4" description = "Python implementation of John Gruber's Markdown." category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "Markdown-3.4.3-py3-none-any.whl", hash = "sha256:065fd4df22da73a625f14890dd77eb8040edcbd68794bcd35943be14490608b2"}, - {file = "Markdown-3.4.3.tar.gz", hash = "sha256:8bf101198e004dc93e84a12a7395e31aac6a9c9942848ae1d99b9d72cf9b3520"}, + {file = "Markdown-3.4.4-py3-none-any.whl", hash = "sha256:a4c1b65c0957b4bd9e7d86ddc7b3c9868fb9670660f6f99f6d1bca8954d5a941"}, + {file = "Markdown-3.4.4.tar.gz", hash = "sha256:225c6123522495d4119a90b3a3ba31a1e87a70369e03f14799ea9c0d7183a3d6"}, ] [package.dependencies] importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} [package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.0)", "mkdocs-nature (>=0.4)"] testing = ["coverage", "pyyaml"] [[package]] @@ -4003,4 +4004,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "f35e143d5fb86e57f21c01e9a60f44e6498d377237175b5bb4dd461c38124d62" +content-hash = "ff41ce4e49f43c08f86bbafb25ffad2d88aa978009d6088cc96acd5fdd1c2783" diff --git a/api/pyproject.toml b/api/pyproject.toml index 4010b6f11..fb589d735 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -44,7 +44,7 @@ django-storages = "==1.13.2" django-versatileimagefield = "==2.2" djangorestframework = "==3.14.0" drf-spectacular = "==0.25.1" -markdown = "==3.4.3" +markdown = "==3.4.4" persisting-theory = "==1.0" psycopg2 = "==2.9.6" redis = "==4.5.5" From 0175895afbcf4a108c801737f34aa70035c4d47c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Wed, 26 Jul 2023 10:36:39 +0000 Subject: [PATCH 16/50] chore(api): update dependency prompt-toolkit to v3.0.39 Part-of: --- api/poetry.lock | 8 ++++---- api/pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/poetry.lock b/api/poetry.lock index 34ed06c86..6bfb4ddd9 100644 --- a/api/poetry.lock +++ b/api/poetry.lock @@ -2512,14 +2512,14 @@ files = [ [[package]] name = "prompt-toolkit" -version = "3.0.38" +version = "3.0.39" description = "Library for building powerful interactive command lines in Python" category = "main" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"}, - {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"}, + {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, ] [package.dependencies] @@ -4004,4 +4004,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "ff41ce4e49f43c08f86bbafb25ffad2d88aa978009d6088cc96acd5fdd1c2783" +content-hash = "b7e4142a6fe997e88728d6e99b7f4c95b9eddba9ded476994c7331d7833a0f0d" diff --git a/api/pyproject.toml b/api/pyproject.toml index fb589d735..2ac28350c 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -104,7 +104,7 @@ factory-boy = "==3.2.1" faker = "==15.3.4" flake8 = "==3.9.2" ipdb = "==0.13.13" -prompt-toolkit = "==3.0.38" +prompt-toolkit = "==3.0.39" pytest = "==7.2.1" pytest-asyncio = "==0.20.3" pytest-cov = "==4.0.0" From 7037b708b4390adb087ff31968c01180506af402 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Sat, 5 Aug 2023 14:44:22 +0200 Subject: [PATCH 17/50] fix(front): fix `ordering=+title` Part-of: --- front/package.json | 8 +- .../src/composables/navigation/useOrdering.ts | 93 ++++++++++--------- front/src/composables/useMarkdown.ts | 6 +- front/yarn.lock | 82 ++++++++-------- 4 files changed, 96 insertions(+), 93 deletions(-) diff --git a/front/package.json b/front/package.json index fbb5f8438..6e843fb08 100644 --- a/front/package.json +++ b/front/package.json @@ -20,10 +20,10 @@ "@sentry/tracing": "7.27.0", "@sentry/vue": "7.27.0", "@vue/runtime-core": "3.2.45", - "@vueuse/core": "9.12.0", - "@vueuse/integrations": "9.12.0", - "@vueuse/math": "9.12.0", - "@vueuse/router": "9.12.0", + "@vueuse/core": "10.3.0", + "@vueuse/integrations": "10.3.0", + "@vueuse/math": "10.3.0", + "@vueuse/router": "10.3.0", "axios": "1.2.3", "axios-auth-refresh": "3.3.6", "butterchurn": "3.0.0-beta.4", diff --git a/front/src/composables/navigation/useOrdering.ts b/front/src/composables/navigation/useOrdering.ts index d712cf06b..6e964f1d7 100644 --- a/front/src/composables/navigation/useOrdering.ts +++ b/front/src/composables/navigation/useOrdering.ts @@ -3,70 +3,73 @@ import type { RouteRecordName } from 'vue-router' import { toRefs, useStorage, syncRef } from '@vueuse/core' import { useRouteQuery } from '@vueuse/router' import { useRoute } from 'vue-router' -import { ref, watch } from 'vue' +import { watch, readonly } from 'vue' export interface OrderingProps { orderingConfigName?: RouteRecordName } -export default (props: OrderingProps) => { +export default (props: OrderingProps) => { const route = useRoute() - const preferences = useStorage(`route-preferences:${props.orderingConfigName?.toString() ?? route.name?.toString() ?? '*'}`, { + interface Preferences { + orderingDirection: '-' | '+' + ordering: T + paginateBy: number + } + + const preferences = useStorage(`route-preferences:${props.orderingConfigName?.toString() ?? route.name?.toString() ?? '*'}`, () => ({ orderingDirection: route.meta.orderingDirection ?? '-', ordering: route.meta.ordering ?? 'creation_date', paginateBy: route.meta.paginateBy ?? 50 - }) + })) const { - orderingDirection: perfOrderingDirection, - paginateBy: perfPaginateBy, - ordering: perfOrdering - } = toRefs(preferences) - - const queryPaginateBy = useRouteQuery('paginateBy', perfPaginateBy.value.toString()) - const paginateBy = ref() - syncRef(queryPaginateBy, paginateBy, { - transform: { - ltr: (left) => +left, - rtl: (right) => right.toString() - } + orderingDirection: prefOrderingDirection, + paginateBy: prefPaginateBy, + ordering: prefOrdering + } = toRefs(preferences, { + replaceRef: false }) - const queryOrdering = useRouteQuery('ordering', perfOrderingDirection.value + perfOrdering.value) + const normalizeDirection = (direction: string) => direction === '+' ? '' : '-' + const queryOrdering = useRouteQuery( + 'ordering', + normalizeDirection(prefOrderingDirection.value) + prefOrdering.value, + { transform: (value) => value.trim() } + ) + + const queryPaginateBy = useRouteQuery('paginateBy', prefPaginateBy.value, { + transform: Number + }) + + // NOTE: Sync paginateBy in query string and preferences. We're using `flush: 'post'` to make sure that we sync after all updates are done + syncRef(queryPaginateBy, prefPaginateBy, { + flush: 'post' + }) + + // NOTE: Sync ordering from preferences to query string + watch([prefOrderingDirection, prefOrdering], () => { + queryOrdering.value = normalizeDirection(prefOrderingDirection.value) + prefOrdering.value.trim() + }) + + // NOTE: Sync ordering from query string to preferences watch(queryOrdering, (ordering) => { - perfOrderingDirection.value = ordering[0] === '-' ? '-' : '+' - perfOrdering.value = ordering[0] === '-' || ordering[0] === '+' - ? ordering.slice(1) - : ordering + prefOrderingDirection.value = ordering[0] === '-' ? '-' : '+' + prefOrdering.value = ordering.replace(/^[+-]/, '') + }, { immediate: true }) + + // NOTE: We're using `flush: 'post'` to make sure that the `onOrderingUpdate` callback is called after all updates are done + const onOrderingUpdate = (fn: () => void) => watch(preferences, fn, { + flush: 'post' }) - watch(perfOrderingDirection, (direction) => { - if (direction === '-') { - queryOrdering.value = direction + perfOrdering.value - return - } - - queryOrdering.value = perfOrdering.value - }) - - watch(perfOrdering, (field) => { - const direction = perfOrderingDirection.value - queryOrdering.value = (direction === '-' ? '-' : '') + field - }) - - watch(queryPaginateBy, (paginateBy) => { - perfPaginateBy.value = +paginateBy - }) - - const onOrderingUpdate = (fn: () => void) => watch(preferences, fn) - return { - paginateBy, - ordering: perfOrdering, - orderingDirection: perfOrderingDirection, - orderingString: queryOrdering, + paginateBy: prefPaginateBy, + ordering: prefOrdering, + orderingDirection: prefOrderingDirection, + orderingString: readonly(queryOrdering), onOrderingUpdate } } diff --git a/front/src/composables/useMarkdown.ts b/front/src/composables/useMarkdown.ts index f1ab9e7ab..1f4269826 100644 --- a/front/src/composables/useMarkdown.ts +++ b/front/src/composables/useMarkdown.ts @@ -1,6 +1,6 @@ -import type { MaybeComputedRef } from '@vueuse/core' +import type { MaybeRefOrGetter } from '@vueuse/core' -import { resolveUnref } from '@vueuse/core' +import { toValue } from '@vueuse/core' import { computed } from 'vue' import showdown from 'showdown' @@ -51,6 +51,6 @@ const markdown = new showdown.Converter({ }) export const useMarkdownRaw = (md: string) => markdown.makeHtml(md) -export const useMarkdownComputed = (md: MaybeComputedRef) => computed(() => useMarkdownRaw(resolveUnref(md))) +export const useMarkdownComputed = (md: MaybeRefOrGetter) => computed(() => useMarkdownRaw(toValue(md))) export default useMarkdownComputed diff --git a/front/yarn.lock b/front/yarn.lock index 09d25409c..9ffe62769 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -1946,10 +1946,10 @@ resolved "https://registry.yarnpkg.com/@earltp/vue-virtual-scroller/-/vue-virtual-scroller-1.0.1.tgz#75116ef9b091457a654d92ff0688e991b3cd9e8a" integrity sha512-7UsmP2JALnkfWlheuWRDywuBUTLJcVPE86X5ogA3djUmYFybE6qximgQ7OgyJnrKLteWR7+1Cp0GUXHhdDKaDQ== -"@types/web-bluetooth@^0.0.16": - version "0.0.16" - resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8" - integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ== +"@types/web-bluetooth@^0.0.17": + version "0.0.17" + resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz#5c9f3c617f64a9735d7b72a7cc671e166d900c40" + integrity sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA== "@typescript-eslint/eslint-plugin@5.48.2": version "5.48.2" @@ -2414,52 +2414,52 @@ resolved "https://registry.yarnpkg.com/@vue/tsconfig/-/tsconfig-0.1.3.tgz#4a61dbd29783d01ddab504276dcf0c2b6988654f" integrity sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg== -"@vueuse/core@9.12.0": - version "9.12.0" - resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-9.12.0.tgz#e5b20f901e081c7ae5fe0e5f3af217929034eefe" - integrity sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg== +"@vueuse/core@10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.3.0.tgz#b2dab7821ef206811b925fc935163c38056fd82b" + integrity sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q== dependencies: - "@types/web-bluetooth" "^0.0.16" - "@vueuse/metadata" "9.12.0" - "@vueuse/shared" "9.12.0" - vue-demi "*" + "@types/web-bluetooth" "^0.0.17" + "@vueuse/metadata" "10.3.0" + "@vueuse/shared" "10.3.0" + vue-demi ">=0.14.5" -"@vueuse/integrations@9.12.0": - version "9.12.0" - resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-9.12.0.tgz#bd28cbab8afccc96b122bb44750b24b6d1b1496a" - integrity sha512-bu0hOQAqg7A8S33RHpr49LuzVQJ4tK4oyimEfhPFGUVqmz/MMcwPH8Lde+MbVXvfYh2hrtwNv9S38pCmonRx4w== +"@vueuse/integrations@10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@vueuse/integrations/-/integrations-10.3.0.tgz#765e9505358590f21531998194c6e60a8b23655c" + integrity sha512-Jgiv7oFyIgC6BxmDtiyG/fxyGysIds00YaY7sefwbhCZ2/tjEx1W/1WcsISSJPNI30in28+HC2J4uuU8184ekg== dependencies: - "@vueuse/core" "9.12.0" - "@vueuse/shared" "9.12.0" - vue-demi "*" + "@vueuse/core" "10.3.0" + "@vueuse/shared" "10.3.0" + vue-demi ">=0.14.5" -"@vueuse/math@9.12.0": - version "9.12.0" - resolved "https://registry.yarnpkg.com/@vueuse/math/-/math-9.12.0.tgz#d7233840a7f6a1cc50357df02224745d9976f4a7" - integrity sha512-i4N67Ib+FXh/cdwK1J7hijSy8QXBKGqy492SvVBd6UjPPeCSIkkd4veO2Lsj0gMeRfObFsVdY0+1jW+kTRcJMw== +"@vueuse/math@10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@vueuse/math/-/math-10.3.0.tgz#5f7243498164403b1ad88cc0733f9dcb8710faed" + integrity sha512-egJN5b7Ks1s92XS/DuP/irxC2GyR59BfLm19aeWDHbAXhDgK9L+X/z9fZGobI9U7dZ/2A9nlqf0FeMDgh+oWEA== dependencies: - "@vueuse/shared" "9.12.0" - vue-demi "*" + "@vueuse/shared" "10.3.0" + vue-demi ">=0.14.5" -"@vueuse/metadata@9.12.0": - version "9.12.0" - resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-9.12.0.tgz#19a0fefcba6a66a2382af10a7a67ebad6eec1f27" - integrity sha512-9oJ9MM9lFLlmvxXUqsR1wLt1uF7EVbP5iYaHJYqk+G2PbMjY6EXvZeTjbdO89HgoF5cI6z49o2zT/jD9SVoNpQ== +"@vueuse/metadata@10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.3.0.tgz#14fe6cc909573785f73a56e4d9351edf3830b796" + integrity sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw== -"@vueuse/router@9.12.0": - version "9.12.0" - resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-9.12.0.tgz#985759be6fb4a55609942b300e62c4023a47612e" - integrity sha512-I3TaWrsxEdANrgJjNEeRTbOMGS+uYjB5zHoyayhFgk1SY1ytDw51tgXr6n4n9fVqglorvhKdX5rFDvBAbeQ+Xw== +"@vueuse/router@10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@vueuse/router/-/router-10.3.0.tgz#f0cd64fddba1b2a5af261e933c53808f0faa78f8" + integrity sha512-WCx/BAxO0eInuOcyNRBxDLS16tnNqzdaR6/babg6AUgAIL0TCfmHBh46wJa6hhg+NMGjd6HzCaktxBasp+0c0A== dependencies: - "@vueuse/shared" "9.12.0" - vue-demi "*" + "@vueuse/shared" "10.3.0" + vue-demi ">=0.14.5" -"@vueuse/shared@9.12.0": - version "9.12.0" - resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-9.12.0.tgz#e6597da80084cba8fc3d6545f4c2fa9817b80428" - integrity sha512-TWuJLACQ0BVithVTRbex4Wf1a1VaRuSpVeyEd4vMUWl54PzlE0ciFUshKCXnlLuD0lxIaLK4Ypj3NXYzZh4+SQ== +"@vueuse/shared@10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.3.0.tgz#ce6b4b6860e14aaa293025dcf0cbe1036a25869f" + integrity sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg== dependencies: - vue-demi "*" + vue-demi ">=0.14.5" abab@^2.0.6: version "2.0.6" @@ -5767,7 +5767,7 @@ vitest@0.25.8: tinyspy "^1.0.2" vite "^3.0.0 || ^4.0.0" -vue-demi@*: +vue-demi@>=0.14.5: version "0.14.5" resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.5.tgz#676d0463d1a1266d5ab5cba932e043d8f5f2fbd9" integrity sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA== From e6672c72ee2719c3e4638b62f137a81346d7520a Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Sat, 5 Aug 2023 14:47:58 +0200 Subject: [PATCH 18/50] chore: add changelog snippet Part-of: --- changes/changelog.d/fix-ordering.bugfix | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changes/changelog.d/fix-ordering.bugfix diff --git a/changes/changelog.d/fix-ordering.bugfix b/changes/changelog.d/fix-ordering.bugfix new file mode 100644 index 000000000..594b5f356 --- /dev/null +++ b/changes/changelog.d/fix-ordering.bugfix @@ -0,0 +1,2 @@ +Fix ordering when querystring contains `+` prefix +Resolve multiple updates to ordering fields From ae2402618846d414cb1b4e7237c4ce43d8c8837c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Ainsworth?= Date: Fri, 11 Aug 2023 11:36:00 +0200 Subject: [PATCH 19/50] docs: Fix broken upgrade documentation link Part-of: --- CHANGELOG | 64 ++++++++++++++--------------- changes/changelog.d/upgradelink.doc | 1 + changes/template.rst | 2 +- docs/redirects.txt | 1 + 4 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 changes/changelog.d/upgradelink.doc diff --git a/CHANGELOG b/CHANGELOG index ad1a092a6..0982d846c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,7 +14,7 @@ This changelog is viewable on the web at https://docs.funkwhale.audio/changelog. ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -86,7 +86,7 @@ Committers: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Update instructions: @@ -508,7 +508,7 @@ Committers: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -550,7 +550,7 @@ Contributors to our Merge Requests: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Features: @@ -609,7 +609,7 @@ Contributors to our Merge Requests: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -634,7 +634,7 @@ Contributors to our Merge Requests: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -686,7 +686,7 @@ Contributors to our Merge Requests: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -738,7 +738,7 @@ Contributors to our Merge Requests: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -784,7 +784,7 @@ Committers: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -843,7 +843,7 @@ Committers ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -900,7 +900,7 @@ Committers ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -931,7 +931,7 @@ nztvar ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html 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 @@ -1133,7 +1133,7 @@ thanksd ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html - Pinned version of asgiref to avoid trouble with latest release. For further information, see #1516 @@ -1141,7 +1141,7 @@ https://docs.funkwhale.audio/admin/upgrading.html ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1160,7 +1160,7 @@ Bugfixes: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1179,7 +1179,7 @@ Bugfixes: ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1199,7 +1199,7 @@ Bugfixes: ---------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1285,7 +1285,7 @@ x -------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Bugfixes: @@ -1299,7 +1299,7 @@ Bugfixes: -------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1361,7 +1361,7 @@ Contributors to this release (development, documentation, reviews): ------------------ Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1386,7 +1386,7 @@ Contributors to this release (development, documentation, reviews): ---------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Dropped python 3.5 support [manual action required, non-docker only] @@ -1530,7 +1530,7 @@ Contributors to this release (translation, development, documentation, reviews, ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -1562,7 +1562,7 @@ Contributors to this release (development, documentation, reviews): ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Features: @@ -1627,7 +1627,7 @@ This 0.21 release is dedicated to Agate, to thank her, for both having created t We are truly grateful as well to the dozens of people who contributed to this release with translations, development, documentation, reviews, design, testing, feedback, financial support, third-party projects and integrations… You made it possible! Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html, there are also additional operations you need to execute, listed in the changelog below (search "Manual action"). +https://docs.funkwhale.audio/administrator/upgrade/index.html, there are also additional operations you need to execute, listed in the changelog below (search "Manual action"). Channels and podcasts ^^^^^^^^^^^^^^^^^^^^^ @@ -1938,7 +1938,7 @@ Contributors to this release (translation, development, documentation, reviews, ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Denormalized audio permission logic in a separate table to enhance performance @@ -2003,7 +2003,7 @@ Contributors to this release (translation, development, documentation, reviews, ----------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Support for genres via tags @@ -2328,7 +2328,7 @@ Contributors to this release (translation, development, documentation, reviews, ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -2377,7 +2377,7 @@ Contributors to this release (committers and reviewers): ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Edits on tracks, albums and artists @@ -2597,7 +2597,7 @@ Contributors to this release (committers and translators): ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Avoid mixed content when deploying mono-container behind proxy [Manual action required] @@ -2648,7 +2648,7 @@ Documentation: ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Enhancements: @@ -2669,7 +2669,7 @@ Bugfixes: ------------------- Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html Fix Gzip compression to avoid BREACH exploit [security] [manual action required] @@ -2791,7 +2791,7 @@ Many thanks to the dozens of people that contributed to this release: translator bug hunters, admins and backers. You made it possible! Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html, ensure you also execute the instructions +https://docs.funkwhale.audio/administrator/upgrade/index.html, ensure you also execute the instructions marked with ``[manual action required]`` and ``[manual action suggested]``. See ``Full changelog`` below for an exhaustive list of changes! diff --git a/changes/changelog.d/upgradelink.doc b/changes/changelog.d/upgradelink.doc new file mode 100644 index 000000000..9151f2e69 --- /dev/null +++ b/changes/changelog.d/upgradelink.doc @@ -0,0 +1 @@ +Fixed incorrect upgrade instructions link in docs. diff --git a/changes/template.rst b/changes/template.rst index 6db6631dc..c344bc878 100644 --- a/changes/template.rst +++ b/changes/template.rst @@ -2,7 +2,7 @@ {{ top_underline * ((versiondata.version + versiondata.date)|length + 3)}} Upgrade instructions are available at -https://docs.funkwhale.audio/admin/upgrading.html +https://docs.funkwhale.audio/administrator/upgrade/index.html {% for section, _ in sections.items() %} {% if sections[section] %} diff --git a/docs/redirects.txt b/docs/redirects.txt index 7870d7da3..1203aae41 100644 --- a/docs/redirects.txt +++ b/docs/redirects.txt @@ -41,6 +41,7 @@ admin/commands.html, ../administrator/manage-script/index.html admin/mrf.html, ../administrator/configuration/mrf.html admin/url.html, ../administrator/configuration/change-url.html admin/optimization.html, ../administrator/configuration/optimize.html +admin/upgrading.html, ../administrator/upgrade/index.html architecture.html, ../developer/architecture.html contributing.html, ../developer/index.html api.html, ../developer/api/index.html From 91840b8763b0ca3df43ec8c779ac0426b43fa1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Ainsworth?= Date: Wed, 16 Aug 2023 16:50:10 +0200 Subject: [PATCH 20/50] docs: resolve broken links Part-of: --- CONTRIBUTING.md | 2 +- README.md | 2 +- api/Readme.md | 2 +- docs/redirects.txt | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 168456188..8ec7c2bdb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ The Funkwhale software is the core of the community project. While we have a cor Funkwhale's backend is written in [Python](https://www.python.org/) using [Django](https://www.djangoproject.com) and [Django REST framework](https://www.django-rest-framework.org/). Our web app is written in [Vue.js](https://vuejs.org/) and [Typescript](https://typescriptlang.org). -Whether you're an experienced developer or you're just learning, check out our [developer guide](https://docs.funkwhale.audio/developers/index.html) to get started. +Whether you're an experienced developer or you're just learning, check out our [developer guide](https://docs.funkwhale.audio/developer/index.html) to get started. ## Document Funkwhale diff --git a/README.md b/README.md index 14dde4835..361e9a1fc 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Want to help make Funkwhale even better? We welcome contributions from across th You can find contribution information in our [documentation hub](https://docs.funkwhale.audio). -- [Developer guides](https://docs.funkwhale.audio/developers/index.html) +- [Developer guides](https://docs.funkwhale.audio/developer/index.html) - [Contributor guides](https://docs.funkwhale.audio/contributing.html) ## Get help diff --git a/api/Readme.md b/api/Readme.md index 005368b99..6ed9a57fc 100644 --- a/api/Readme.md +++ b/api/Readme.md @@ -32,7 +32,7 @@ Each API call returns HTTP headers to pass the following information: - How many more requests in the scope can be made within the rate-limit timeframe (`X-RateLimit-Remaining`) - How much time does the client need to wait to send another request (`Retry-After`) -For more information, check our [rate limit documentation](https://docs.funkwhale.audio/admin/configuration.html#api-configuration) +For more information, check our [rate limit documentation](https://docs.funkwhale.audio/developer/api/rate-limit.html) ## Resources diff --git a/docs/redirects.txt b/docs/redirects.txt index 1203aae41..7d4074b9b 100644 --- a/docs/redirects.txt +++ b/docs/redirects.txt @@ -54,3 +54,6 @@ translators.html, ../contributor/translation.html federation.html, ../developer/federation/index.html upgrading.html, ../administrator/upgrade/index.html administrator_documentation/upgrade_docs/docker.html, ../../administrator/upgrade/docker.html +upgrading/0.17.html, ../user/libraries/index.html +admin/external-storages.html, ../../administrator/configuration/object-storage.html +admin/external-storage.html#no-resolver-found, ../../administrator/configuration/object-storage.html#troubleshooting From 9125bac98377d8e5d532ef291de63ba2388b57ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Ainsworth?= Date: Tue, 22 Aug 2023 00:43:21 +0200 Subject: [PATCH 21/50] fix: fix link to ID3 spec Part-of: --- docs/user/libraries/content/tag.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/libraries/content/tag.md b/docs/user/libraries/content/tag.md index 4f38caba1..c850fc465 100644 --- a/docs/user/libraries/content/tag.md +++ b/docs/user/libraries/content/tag.md @@ -1,6 +1,6 @@ # Tag your content with Picard -Funkwhale relies on [ID3 tags](https://id3.org/) to sort audio content. ID3 tags tell Funkwhale information about your files. Funkwhale uses this information to display your content in your {term}`pod`. +Funkwhale relies on [ID3 tags](https://en.wikipedia.org/wiki/ID3) to sort audio content. ID3 tags tell Funkwhale information about your files. Funkwhale uses this information to display your content in your {term}`pod`. We recommend using [MusicBrainz Picard](https://picard.musicbrainz.org/) to tag your content. MusicBrainz Picard is free and open source software that connects to [MusicBrainz](https://musicbrainz.org). Funkwhale uses MusicBrainz as its primary data source. From 66a363014dfb6c411d57106a8ecd17ad2a537fac Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Tue, 25 Jul 2023 16:55:15 +0200 Subject: [PATCH 22/50] feat(front): enable sourcemap generation Part-of: --- changes/changelog.d/sourcemaps.enchancement | 1 + front/vite.config.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changes/changelog.d/sourcemaps.enchancement diff --git a/changes/changelog.d/sourcemaps.enchancement b/changes/changelog.d/sourcemaps.enchancement new file mode 100644 index 000000000..52a0ebacc --- /dev/null +++ b/changes/changelog.d/sourcemaps.enchancement @@ -0,0 +1 @@ +Enable sourcemaps for production builds diff --git a/front/vite.config.ts b/front/vite.config.ts index 86382f293..449a2a700 100644 --- a/front/vite.config.ts +++ b/front/vite.config.ts @@ -12,6 +12,9 @@ const port = +(process.env.VUE_PORT ?? 8080) // https://vitejs.dev/config/ export default defineConfig(({ mode }) => ({ envPrefix: ['VUE_', 'FUNKWHALE_SENTRY_'], + build: { + sourcemap: true + }, plugins: [ // https://github.com/vitejs/vite/tree/main/packages/plugin-vue Vue(), @@ -55,7 +58,7 @@ export default defineConfig(({ mode }) => ({ }, setupFiles: [ './test/setup/mock-audio-context.ts', - './test/setup/mock-vue-i18n.ts', + './test/setup/mock-vue-i18n.ts' ] } })) From 78be3d8febe7e388dd2028e68b45eb951db7b6f7 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Thu, 27 Jul 2023 00:38:47 +0200 Subject: [PATCH 23/50] ci: increase node max memory usage Part-of: --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 158948bb5..9a227848b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,6 +51,7 @@ review_front: VUE_APP_ROUTER_BASE_URL: /-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/front-review/ VUE_APP_INSTANCE_URL: https://demo.funkwhale.audio NODE_ENV: review + NODE_OPTIONS: --max-old-space-size=4096 before_script: - apk add --no-cache jq bash coreutils python3 - rm -rf front-review @@ -311,6 +312,7 @@ build_front: image: node:18-alpine variables: <<: *keep_git_files_permissions + NODE_OPTIONS: --max-old-space-size=4096 before_script: - apk add --no-cache jq bash coreutils python3 - cd front From fc979983ca9805e8404ac2e771edb82c5d889c63 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Mon, 14 Aug 2023 15:52:54 +0200 Subject: [PATCH 24/50] fix(logger): don't color when running tests Part-of: --- front/src/composables/useLogger.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/front/src/composables/useLogger.ts b/front/src/composables/useLogger.ts index 169bc7867..e98c54718 100644 --- a/front/src/composables/useLogger.ts +++ b/front/src/composables/useLogger.ts @@ -52,6 +52,9 @@ const getFile = () => { // NOTE: We're pushing all logs to the end of the event loop const createLoggerFn = (level: LogLevel) => { + // NOTE: We don't want to handle logs ourselves in tests + if (import.meta.env.VITEST) return console[level] + return (...args: any[]) => { const timestamp = new Date().toUTCString() const { method, file, lineNo } = getFile() From b64ca34fd7cf24bf1d683885d2fed066bfe4d890 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Mon, 14 Aug 2023 15:54:27 +0200 Subject: [PATCH 25/50] fix(useMarkdown): fix parsing multiple links Part-of: --- front/src/composables/useMarkdown.ts | 6 ++--- .../specs/composables/useMarkdown.test.ts | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 front/test/specs/composables/useMarkdown.test.ts diff --git a/front/src/composables/useMarkdown.ts b/front/src/composables/useMarkdown.ts index 1f4269826..2fbf0c8a7 100644 --- a/front/src/composables/useMarkdown.ts +++ b/front/src/composables/useMarkdown.ts @@ -6,8 +6,8 @@ import showdown from 'showdown' showdown.extension('openExternalInNewTab', { type: 'output', - regex: //g, - replace (text: string) { + regex: //g, + replace(text: string) { const matches = text.match(/href="(.+)">/) ?? [] const url = matches[1] ?? './' @@ -26,7 +26,7 @@ showdown.extension('openExternalInNewTab', { showdown.extension('linkifyTags', { type: 'language', regex: /#[^\W]+/g, - replace (text: string) { + replace(text: string) { return `${text}` } }) diff --git a/front/test/specs/composables/useMarkdown.test.ts b/front/test/specs/composables/useMarkdown.test.ts new file mode 100644 index 000000000..bb3b558ed --- /dev/null +++ b/front/test/specs/composables/useMarkdown.test.ts @@ -0,0 +1,25 @@ +import { useMarkdownRaw } from '~/composables/useMarkdown' + +describe('useMarkdownRaw', () => { + describe('anchors', () => { + it('should add target="_blank" to external links', () => { + const html = useMarkdownRaw('https://open.audio') + expect(html).toBe('

https://open.audio

') + }) + + it('should not link raw path', () => { + const html = useMarkdownRaw('/library/tags') + expect(html).toBe('

/library/tags

') + }) + + it('should not add target="_blank" to internal links', () => { + const html = useMarkdownRaw('[/library/tags](/library/tags)') + expect(html).toBe('

/library/tags

') + }) + + it('should handle multiple links', () => { + const html = useMarkdownRaw('https://open.audio https://funkwhale.audio') + expect(html).toBe('

https://open.audio https://funkwhale.audio

') + }) + }) +}) From b047c50284281e49872883a02a1fd110a99c4e2a Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Mon, 14 Aug 2023 16:06:18 +0200 Subject: [PATCH 26/50] fix(podcasts): fix short description (#2206) Part-of: --- front/src/components/audio/podcast/Row.vue | 76 ++++++---------------- 1 file changed, 20 insertions(+), 56 deletions(-) diff --git a/front/src/components/audio/podcast/Row.vue b/front/src/components/audio/podcast/Row.vue index 27def91bd..5dc4d39e5 100644 --- a/front/src/components/audio/podcast/Row.vue +++ b/front/src/components/audio/podcast/Row.vue @@ -13,6 +13,7 @@ import PlayButton from '~/components/audio/PlayButton.vue' import useMarkdown from '~/composables/useMarkdown' import usePlayOptions from '~/composables/audio/usePlayOptions' import useErrorHandler from '~/composables/useErrorHandler' +import SanitizedHtml from '~/components/SanitizedHtml.vue' interface Props extends PlayOptionsProps { tracks: Track[] @@ -67,69 +68,32 @@ await fetchData() From 2803bc790a790c9615b4007ffa5b1c31852d5894 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Mon, 14 Aug 2023 16:25:19 +0200 Subject: [PATCH 27/50] feat(front): add vue macros Part-of: --- front/package.json | 2 + front/tsconfig.json | 17 +- front/vite.config.ts | 10 +- front/yarn.lock | 459 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 476 insertions(+), 12 deletions(-) diff --git a/front/package.json b/front/package.json index 6e843fb08..bc2347a1c 100644 --- a/front/package.json +++ b/front/package.json @@ -71,6 +71,7 @@ "@typescript-eslint/eslint-plugin": "5.48.2", "@vitejs/plugin-vue": "4.0.0", "@vitest/coverage-c8": "0.25.8", + "@vue-macros/volar": "0.13.3", "@vue/compiler-sfc": "3.2.47", "@vue/eslint-config-standard": "8.0.1", "@vue/eslint-config-typescript": "11.0.2", @@ -91,6 +92,7 @@ "sinon": "15.0.1", "standardized-audio-context-mock": "9.6.18", "typescript": "4.9.4", + "unplugin-vue-macros": "2.4.6", "utility-types": "3.10.0", "vite": "4.0.4", "vite-plugin-pwa": "0.14.1", diff --git a/front/tsconfig.json b/front/tsconfig.json index 767184e85..bd858b045 100644 --- a/front/tsconfig.json +++ b/front/tsconfig.json @@ -10,7 +10,8 @@ "vitest/globals", "vite/client", "vue/ref-macros", - "vite-plugin-pwa/client" + "vite-plugin-pwa/client", + "unplugin-vue-macros/macros-global" ], "paths": { "#/*": ["src/worker/*"], @@ -24,5 +25,17 @@ "src/**/*.vue", "vite.config.ts", "test/**/*.ts" - ] + ], + "vueCompilerOptions": { + "plugins": [ + "@vue-macros/volar/define-options", + "@vue-macros/volar/define-models", + "@vue-macros/volar/define-props", + "@vue-macros/volar/define-props-refs", + "@vue-macros/volar/short-vmodel", + "@vue-macros/volar/define-slots", + "@vue-macros/volar/export-props", + "@vue-macros/volar/jsx-directive" + ] + } } diff --git a/front/vite.config.ts b/front/vite.config.ts index 449a2a700..dc5e1ba45 100644 --- a/front/vite.config.ts +++ b/front/vite.config.ts @@ -6,6 +6,7 @@ import VueI18n from '@intlify/unplugin-vue-i18n/vite' import manifest from './pwa-manifest.json' import Vue from '@vitejs/plugin-vue' +import VueMacros from 'unplugin-vue-macros/vite' const port = +(process.env.VUE_PORT ?? 8080) @@ -16,8 +17,13 @@ export default defineConfig(({ mode }) => ({ sourcemap: true }, plugins: [ - // https://github.com/vitejs/vite/tree/main/packages/plugin-vue - Vue(), + // https://vue-macros.sxzz.moe/ + VueMacros({ + plugins: { + // https://github.com/vitejs/vite/tree/main/packages/plugin-vue + vue: Vue(), + } + }), // https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n VueI18n({ diff --git a/front/yarn.lock b/front/yarn.lock index 9ffe62769..9b188850d 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -10,6 +10,11 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@antfu/utils@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.5.tgz#c36f37add92a7de57b9c29ae0c1f399706bff345" + integrity sha512-dlR6LdS+0SzOAPx/TPRhnoi7hE251OVeT2Snw0RguNbBSbjUHdWr0l3vcUUDg26rEysT89kCbtw1lVorBXLLCg== + "@apideck/better-ajv-errors@^0.3.1": version "0.3.6" resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz#957d4c28e886a64a8141f7522783be65733ff097" @@ -279,6 +284,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== +"@babel/parser@^7.22.7": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55" + integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" @@ -1400,7 +1410,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -1434,6 +1444,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@rollup/plugin-babel@^5.2.0": version "5.3.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" @@ -1496,6 +1511,15 @@ estree-walker "^2.0.2" picomatch "^2.3.1" +"@rollup/pluginutils@^5.0.2": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.3.tgz#183126d69aeb1cfa23401d5a71cb4b8c16c4a4e0" + integrity sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + "@sentry/browser@7.27.0": version "7.27.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.27.0.tgz#540d292d418abbf0ac7cabb39fe1863b8fa0c85f" @@ -2129,6 +2153,13 @@ "@volar/source-map" "1.0.24" muggle-string "^0.1.0" +"@volar/language-core@1.10.0", "@volar/language-core@~1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-1.10.0.tgz#fb6b3ad22e75c53a1ae4d644c4a788b47d411b9d" + integrity sha512-ddyWwSYqcbEZNFHm+Z3NZd6M7Ihjcwl/9B5cZd8kECdimVXUFdFi60XHWD27nrWtUQIsUYIG7Ca1WBwV2u2LSQ== + dependencies: + "@volar/source-map" "1.10.0" + "@volar/source-map@1.0.24": version "1.0.24" resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-1.0.24.tgz#ad4c827fea5c26b4bf38a86d983e7deb65b1c61e" @@ -2136,6 +2167,13 @@ dependencies: muggle-string "^0.1.0" +"@volar/source-map@1.10.0", "@volar/source-map@~1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-1.10.0.tgz#2413eb190ce69fc1a382f58524a3f82306668024" + integrity sha512-/ibWdcOzDGiq/GM1JU2eX8fH1bvAhl66hfe8yEgLEzg9txgr6qb5sQ/DEz5PcDL75tF5H5sCRRwn8Eu8ezi9mw== + dependencies: + muggle-string "^0.3.1" + "@volar/typescript@1.0.24": version "1.0.24" resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-1.0.24.tgz#f934eda9774b31abdff53efc56782cd2623723d5" @@ -2165,6 +2203,220 @@ "@volar/typescript" "1.0.24" "@volar/vue-language-core" "1.0.24" +"@vue-macros/api@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@vue-macros/api/-/api-0.8.3.tgz#16b9c907ddac65d226f958af5c7d82109846a723" + integrity sha512-qpKB+2YnhRBMoz/FaDEJZfH2x7t3M72lHFdfrjIVeGvQzhOO5wMNY3fNjmRRB9tGJM8SSGd1gUYPZHK0ZSOVIw== + dependencies: + "@babel/types" "^7.22.5" + "@vue-macros/common" "1.7.0" + resolve.exports "^2.0.2" + +"@vue-macros/better-define@1.6.9": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@vue-macros/better-define/-/better-define-1.6.9.tgz#27aca6f97a184c76c59b676ed2aa2150f97f2762" + integrity sha512-3D4P+J7BX0UKckMC1Fbz+JmgTTJ/hKC0RrhHZIMqfjgjVQI1UDxLMb8a02gBSVyI+4OyX1KotHnahYAtwj7plw== + dependencies: + "@vue-macros/api" "0.8.3" + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/chain-call@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@vue-macros/chain-call/-/chain-call-0.1.3.tgz#a0b65f8848105296ca047d6132338da04ce54f69" + integrity sha512-5AZ6duwVecJ0FDg1LiwMt1sjOiPERSup4mF1v+X4CzQIqmG/0XkntbeLgJLVstXw87fgyZNOXkzoeXf9n0OPyw== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/common@1.7.0", "@vue-macros/common@~1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@vue-macros/common/-/common-1.7.0.tgz#67e4ee8831ad70383c9496cebeb23850e6a6e3c5" + integrity sha512-177tzAjvEiFxAsOM+zd8EWCfAdneePoZroGg6R5QhMcycC28r+2k4wyzrjupjkDBgx7KAZkJ/KzkSfuEi31U0A== + dependencies: + "@babel/types" "^7.22.5" + "@rollup/pluginutils" "^5.0.2" + "@vue/compiler-sfc" "^3.3.4" + ast-kit "^0.9.5" + local-pkg "^0.4.3" + magic-string-ast "^0.3.0" + +"@vue-macros/define-emit@^0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@vue-macros/define-emit/-/define-emit-0.1.13.tgz#44acb6ad49f1138a9549aac8a9ce0274d55b2224" + integrity sha512-D0QWYOzsDXWiXYIxCHoHTWtfYVk/mmKWliE2e/WIKlSOUpQB8pdwFOw8FksLRgXBCQq3pGnKauf6mG43C+AiiQ== + dependencies: + "@vue-macros/api" "0.8.3" + "@vue-macros/common" "1.7.0" + rollup "^3.27.2" + unplugin "^1.4.0" + +"@vue-macros/define-models@1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@vue-macros/define-models/-/define-models-1.0.13.tgz#c7af107e92b78366223a635253be4f3e9851ab09" + integrity sha512-1GphMtJsR5+Dqcarm3f8pKYMHSigEiqGqijPp4njQT6O+H+i5Ja6kcqtqre5N1/fNRRgxe4l2KGKyk44IstmMA== + dependencies: + "@vue-macros/common" "1.7.0" + ast-walker-scope "^0.5.0" + unplugin "^1.4.0" + +"@vue-macros/define-prop@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@vue-macros/define-prop/-/define-prop-0.2.4.tgz#af1d2a07e28747f6a899be906c3a7535be69e93e" + integrity sha512-TOoTIcHQ/G8PI7jaVsnHSBbZjPl3ChEAgaWp7bEiOOODU2RAQfA8k7KuB04WVppeenR/rqA1UZMdcKexM9G3Fg== + dependencies: + "@vue-macros/api" "0.8.3" + "@vue-macros/common" "1.7.0" + rollup "^3.27.2" + unplugin "^1.4.0" + +"@vue-macros/define-props-refs@1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@vue-macros/define-props-refs/-/define-props-refs-1.1.7.tgz#989d5418f738eb78d1736999c3c646421f97506c" + integrity sha512-EO0V/mJa38KySRKB9k1zVcCplSim/wSNZlBJEkSSO+s1LATPmb26NFGLa5vIOzfUdYbGZ3gqTFINa+lWorPf6g== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/define-props@1.0.17": + version "1.0.17" + resolved "https://registry.yarnpkg.com/@vue-macros/define-props/-/define-props-1.0.17.tgz#7aff839a643394f7a3511256a8b92e1a6bbb6341" + integrity sha512-vHan0LXzl+igYLEQKntvaXH7bfGMZTFp3kTgRpj40nohcYIgDWw53s9wwsTJebo49eFHNXWSZDR4UXdye+Akeg== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/define-render@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@vue-macros/define-render/-/define-render-1.4.0.tgz#8936c2eb1021205f9e7aff7cf211fa450f72b90d" + integrity sha512-RLETg7Lu8BQx0ArYTLF14nS1UB/a1dGwbe/yyJLVmmwW1On/TbGzfR2ibSJNe7B6kNWfxN8cPxqLID8IehTP2w== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/define-slots@1.0.12": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@vue-macros/define-slots/-/define-slots-1.0.12.tgz#a4a0a863c774e7071497e48323eee991899ba39d" + integrity sha512-q7zW5hj3QxFbAzl7as5CjPzILAjM9nKk7dpirgF18YT/gWVnIEwapx9HFyvw/L6CxIA5ErBcMWRKTyYL68mDgg== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/devtools@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@vue-macros/devtools/-/devtools-0.1.3.tgz#05108904369160d8446628d4d7f35d8d412c6e2b" + integrity sha512-aQRC9/TfmQajTMbZZ1BJn61rrraQztJqf64JdXRIpotbGR+xufLY/KIyTTB4SgL1pE1eW/ar5FaZTSjMqyVGIg== + dependencies: + sirv "^2.0.3" + vue "^3.3.4" + +"@vue-macros/export-expose@0.0.10": + version "0.0.10" + resolved "https://registry.yarnpkg.com/@vue-macros/export-expose/-/export-expose-0.0.10.tgz#98fbe9e99b2d817970d2215d3156e1f7fdd3c520" + integrity sha512-ZlFwS6gWxtbmmOA1Lb3+9ehCxDRwcBL+2XjXaeD8gjct8dvsnWXMO5TRU0sKYO09unj3bkQd3mSF050/R27DYw== + dependencies: + "@vue-macros/common" "1.7.0" + "@vue/compiler-sfc" "^3.3.4" + unplugin "^1.4.0" + +"@vue-macros/export-props@0.3.15": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@vue-macros/export-props/-/export-props-0.3.15.tgz#750c1e9416acd9032ba5d51b13b7d329bc0e3110" + integrity sha512-a0bhLt0lhmshuEsiPpaCn1kw6Qv/f7iQsEFTSnMgNvFXRrziv/YcEHoz9PZ79f4HAKwLgsj9AQfRyABJl3B9wg== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/hoist-static@1.4.9": + version "1.4.9" + resolved "https://registry.yarnpkg.com/@vue-macros/hoist-static/-/hoist-static-1.4.9.tgz#a8d13d9d0166cd057c819cf0b2546c68891a76e5" + integrity sha512-STxtEXmGFoERW/jvDw/uS7Ds5tR9U8dlTsTu1m3LTQKiWANzu33WICRFifVI39cUL5TVFujN3yEcdIGvtfbRqw== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/jsx-directive@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@vue-macros/jsx-directive/-/jsx-directive-0.5.0.tgz#d3cafddd74370935244d4bff833b52a2287190df" + integrity sha512-mrajG1U5zpi3yvUVvu2fw70DMc91qw3Vura8n4Ktoqk35bEAnus7r4+HijYH7Wsc421M5BmbQlPNu3U1S3sLuQ== + dependencies: + "@vue-macros/common" "~1.7.0" + unplugin "^1.4.0" + +"@vue-macros/named-template@0.3.16": + version "0.3.16" + resolved "https://registry.yarnpkg.com/@vue-macros/named-template/-/named-template-0.3.16.tgz#3840c1151ff921c6831c42f3f63242c71dc1ec81" + integrity sha512-/VCHjs6teUa7YntAEY7Iz1f+EvrVcG2KkzlUPS8EB/g8lM8Z2inyFEB3ohD8c4gGM6hKg3LtwUsWaWGaFHEmDg== + dependencies: + "@vue-macros/common" "1.7.0" + "@vue/compiler-dom" "^3.3.4" + unplugin "^1.4.0" + +"@vue-macros/reactivity-transform@0.3.19": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@vue-macros/reactivity-transform/-/reactivity-transform-0.3.19.tgz#466b4001c200d885778ef87de820bd32226c7c0e" + integrity sha512-HUqMu8GyGJG89K3a64OxZJknT/Jii8sTcA1fB6ommTU2T7eSGkBalipsSRvbJAhAkl4SYcVLJk0HX18hv+GA+g== + dependencies: + "@babel/parser" "^7.22.7" + "@vue-macros/common" "1.7.0" + "@vue/compiler-core" "^3.3.4" + "@vue/shared" "^3.3.4" + magic-string "^0.30.2" + unplugin "^1.4.0" + +"@vue-macros/setup-block@0.2.15": + version "0.2.15" + resolved "https://registry.yarnpkg.com/@vue-macros/setup-block/-/setup-block-0.2.15.tgz#98251a5ac6b85e281134129a0e93ebadedd19528" + integrity sha512-rhbJrxXFJ+GRqrR5NnqU8pMELLbAz80xc/+USGu4KzsuVyiklyQpy7jVEKRXDrm9rqlL09ia/sLrn375eCQDtA== + dependencies: + "@vue-macros/common" "1.7.0" + "@vue/compiler-dom" "^3.3.4" + unplugin "^1.4.0" + +"@vue-macros/setup-component@0.16.16": + version "0.16.16" + resolved "https://registry.yarnpkg.com/@vue-macros/setup-component/-/setup-component-0.16.16.tgz#191c798942403d61b17944b6993d379c6203f7e1" + integrity sha512-oscrS6MlCAbvmtXxhgQdKRPNoa+5cCaNM43XUjvMb84OGtzFRB3rvRlDOVh+ylW3EdGkuqAIlpS0ZBHdntlw5Q== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/setup-sfc@0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@vue-macros/setup-sfc/-/setup-sfc-0.16.0.tgz#e41db3e68d07dd45c798990af0d1d74d31a2734e" + integrity sha512-H/bOmDXYGA4sFQRQmCAw8oCkgthdc8i6/VjLgQGngwAFGNUYf8Fin3mQs6r8L1N3jXsnu7nfnUFDsc8JYyOllg== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/short-emits@1.4.7": + version "1.4.7" + resolved "https://registry.yarnpkg.com/@vue-macros/short-emits/-/short-emits-1.4.7.tgz#4bbdeed1dd5616e5509f2b862f3c0cdbf1f0cd70" + integrity sha512-yWrQO2g+VTrWXeaG7bcwQh+T5AvirFAyAyDS3fzzfa17HRI2Oj9d8t584xqBpr4u+m3rjs/wLgR4S3U0EZd1Mg== + dependencies: + "@vue-macros/common" "1.7.0" + unplugin "^1.4.0" + +"@vue-macros/short-vmodel@1.2.15": + version "1.2.15" + resolved "https://registry.yarnpkg.com/@vue-macros/short-vmodel/-/short-vmodel-1.2.15.tgz#094c6dfe3dc762a7e340d55c80d74810bc2e0d9f" + integrity sha512-mcTaoRUgiM9exCvzxkOJC7JQgfiDs2kcWxF4XoI9d24GBCcldpIoLNmJ71OPihGg9LvJUR7Lgr2F6c4ewaxkiQ== + dependencies: + "@vue-macros/common" "1.7.0" + "@vue/compiler-core" "^3.3.4" + +"@vue-macros/volar@0.13.3": + version "0.13.3" + resolved "https://registry.yarnpkg.com/@vue-macros/volar/-/volar-0.13.3.tgz#4cb1e08cbf3aa056bb2ea6588bf96b5f302a8ddb" + integrity sha512-gvM3UVnV1I0MIMJoY8o0c3ZWjfbX7n3ilEXUdy5kgASwu57yREjUTVWgihKBDqEuBszy2H49SYJgFziuhZ1r1Q== + dependencies: + "@rollup/pluginutils" "^5.0.2" + "@volar/language-core" "1.10.0" + "@vue-macros/common" "1.7.0" + "@vue-macros/define-props" "1.0.17" + "@vue-macros/short-vmodel" "1.2.15" + "@vue/language-core" "1.8.8" + "@vue/compiler-core@3.2.45": version "3.2.45" resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.45.tgz#d9311207d96f6ebd5f4660be129fb99f01ddb41b" @@ -2185,7 +2437,7 @@ estree-walker "^2.0.2" source-map "^0.6.1" -"@vue/compiler-core@3.3.4": +"@vue/compiler-core@3.3.4", "@vue/compiler-core@^3.3.4": version "3.3.4" resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.3.4.tgz#7fbf591c1c19e1acd28ffd284526e98b4f581128" integrity sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g== @@ -2211,7 +2463,7 @@ "@vue/compiler-core" "3.2.47" "@vue/shared" "3.2.47" -"@vue/compiler-dom@3.3.4", "@vue/compiler-dom@^3.2.45": +"@vue/compiler-dom@3.3.4", "@vue/compiler-dom@^3.2.45", "@vue/compiler-dom@^3.3.0", "@vue/compiler-dom@^3.3.4": version "3.3.4" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz#f56e09b5f4d7dc350f981784de9713d823341151" integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w== @@ -2251,7 +2503,7 @@ postcss "^8.1.10" source-map "^0.6.1" -"@vue/compiler-sfc@^3.2.45": +"@vue/compiler-sfc@3.3.4", "@vue/compiler-sfc@^3.2.45", "@vue/compiler-sfc@^3.3.4": version "3.3.4" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz#b19d942c71938893535b46226d602720593001df" integrity sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ== @@ -2317,6 +2569,20 @@ "@typescript-eslint/parser" "^5.0.0" vue-eslint-parser "^9.0.0" +"@vue/language-core@1.8.8": + version "1.8.8" + resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-1.8.8.tgz#5a8aa8363f4dfacdfcd7808a9926744d7c310ae6" + integrity sha512-i4KMTuPazf48yMdYoebTkgSOJdFraE4pQf0B+FTOFkbB+6hAfjrSou/UmYWRsWyZV6r4Rc6DDZdI39CJwL0rWw== + dependencies: + "@volar/language-core" "~1.10.0" + "@volar/source-map" "~1.10.0" + "@vue/compiler-dom" "^3.3.0" + "@vue/reactivity" "^3.3.0" + "@vue/shared" "^3.3.0" + minimatch "^9.0.0" + muggle-string "^0.3.1" + vue-template-compiler "^2.7.14" + "@vue/reactivity-transform@3.2.45": version "3.2.45" resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.45.tgz#07ac83b8138550c83dfb50db43cde1e0e5e8124d" @@ -2357,7 +2623,7 @@ dependencies: "@vue/shared" "3.2.45" -"@vue/reactivity@^3.2.45": +"@vue/reactivity@3.3.4", "@vue/reactivity@^3.2.45", "@vue/reactivity@^3.3.0": version "3.3.4" resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.3.4.tgz#a27a29c6cd17faba5a0e99fbb86ee951653e2253" integrity sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ== @@ -2372,6 +2638,14 @@ "@vue/reactivity" "3.2.45" "@vue/shared" "3.2.45" +"@vue/runtime-core@3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.3.4.tgz#4bb33872bbb583721b340f3088888394195967d1" + integrity sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA== + dependencies: + "@vue/reactivity" "3.3.4" + "@vue/shared" "3.3.4" + "@vue/runtime-dom@3.2.45": version "3.2.45" resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.45.tgz#1a2ef6ee2ad876206fbbe2a884554bba2d0faf59" @@ -2381,6 +2655,15 @@ "@vue/shared" "3.2.45" csstype "^2.6.8" +"@vue/runtime-dom@3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz#992f2579d0ed6ce961f47bbe9bfe4b6791251566" + integrity sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ== + dependencies: + "@vue/runtime-core" "3.3.4" + "@vue/shared" "3.3.4" + csstype "^3.1.1" + "@vue/server-renderer@3.2.45": version "3.2.45" resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.45.tgz#ca9306a0c12b0530a1a250e44f4a0abac6b81f3f" @@ -2389,6 +2672,14 @@ "@vue/compiler-ssr" "3.2.45" "@vue/shared" "3.2.45" +"@vue/server-renderer@3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.3.4.tgz#ea46594b795d1536f29bc592dd0f6655f7ea4c4c" + integrity sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ== + dependencies: + "@vue/compiler-ssr" "3.3.4" + "@vue/shared" "3.3.4" + "@vue/shared@3.2.45": version "3.2.45" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.45.tgz#a3fffa7489eafff38d984e23d0236e230c818bc2" @@ -2399,7 +2690,7 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c" integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ== -"@vue/shared@3.3.4", "@vue/shared@^3.2.45": +"@vue/shared@3.3.4", "@vue/shared@^3.2.45", "@vue/shared@^3.3.0", "@vue/shared@^3.3.4": version "3.3.4" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.3.4.tgz#06e83c5027f464eef861c329be81454bc8b70780" integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ== @@ -2494,6 +2785,11 @@ acorn@^8.1.0, acorn@^8.5.0, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== +acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -2607,6 +2903,23 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +ast-kit@^0.9.4, ast-kit@^0.9.5: + version "0.9.5" + resolved "https://registry.yarnpkg.com/ast-kit/-/ast-kit-0.9.5.tgz#88c0ba76b6f7f24c04ccf9ae778e33afc187dc80" + integrity sha512-kbL7ERlqjXubdDd+szuwdlQ1xUxEz9mCz1+m07ftNVStgwRb2RWw+U6oKo08PAvOishMxiqz1mlJyLl8yQx2Qg== + dependencies: + "@babel/parser" "^7.22.7" + "@rollup/pluginutils" "^5.0.2" + pathe "^1.1.1" + +ast-walker-scope@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/ast-walker-scope/-/ast-walker-scope-0.5.0.tgz#87e0ca4f34394d11ec4dea5925b8bda80b811819" + integrity sha512-NsyHMxBh4dmdEHjBo1/TBZvCKxffmZxRYhmclfu0PP6Aftre47jOHYaYaNqJcV0bxihxFXhDkzLHUwHc0ocd0Q== + dependencies: + "@babel/parser" "^7.22.7" + ast-kit "^0.9.4" + async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" @@ -3010,6 +3323,11 @@ csstype@^2.6.8: resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== +csstype@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + data-urls@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" @@ -4506,7 +4824,7 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -local-pkg@^0.4.2: +local-pkg@^0.4.2, local-pkg@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.4.3.tgz#0ff361ab3ae7f1c19113d9bb97b98b905dbc4963" integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g== @@ -4579,6 +4897,13 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +magic-string-ast@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/magic-string-ast/-/magic-string-ast-0.3.0.tgz#8fc83ac6d084c5a342645a30354184a6e0ab4382" + integrity sha512-0shqecEPgdFpnI3AP90epXyxZy9g6CRZ+SZ7BcqFwYmtFEnZ1jpevcV5HoyVnlDS9gCnc1UIg3Rsvp3Ci7r8OA== + dependencies: + magic-string "^0.30.2" + magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -4600,6 +4925,13 @@ magic-string@^0.30.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" +magic-string@^0.30.2: + version "0.30.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.2.tgz#dcf04aad3d0d1314bc743d076c50feb29b3c7aca" + integrity sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -4651,6 +4983,13 @@ minimatch@^5.0.1, minimatch@^5.1.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.0: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -4666,6 +5005,11 @@ moment@2.29.4: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +mrmime@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -4686,6 +5030,11 @@ muggle-string@^0.1.0: resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.1.0.tgz#1fda8a281c8b27bb8b70466dbc9f27586a8baa6c" integrity sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg== +muggle-string@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.3.1.tgz#e524312eb1728c63dd0b2ac49e3282e6ed85963a" + integrity sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg== + nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" @@ -4876,7 +5225,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathe@^1.0.0: +pathe@^1.0.0, pathe@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a" integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q== @@ -5059,6 +5408,11 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve.exports@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + resolve@^1.10.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.22.2: version "1.22.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" @@ -5104,6 +5458,13 @@ rollup@^3.21.0, rollup@^3.7.0, rollup@^3.7.2: optionalDependencies: fsevents "~2.3.2" +rollup@^3.27.2: + version "3.28.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.28.0.tgz#a3c70004b01934760c0cb8df717c7a1d932389a2" + integrity sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw== + optionalDependencies: + fsevents "~2.3.2" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -5227,6 +5588,15 @@ sinon@^15.0.4: nise "^5.1.4" supports-color "^7.2.0" +sirv@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.3.tgz#ca5868b87205a74bef62a469ed0296abceccd446" + integrity sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^3.0.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -5476,6 +5846,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" @@ -5645,6 +6020,53 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unplugin-combine@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/unplugin-combine/-/unplugin-combine-0.7.0.tgz#d76fa67c18070016dd6c43e72757957fb2ce862a" + integrity sha512-Pxa8ovANAUN/bz/pzGN8xnTqFfSJndIJAttXS4/BdVq7mxtKB65RVa2UxAnLmEzgwvtefXAjZgyx9fk5Bv0vEA== + dependencies: + "@antfu/utils" "^0.7.5" + unplugin "^1.3.2" + +unplugin-vue-define-options@1.3.15: + version "1.3.15" + resolved "https://registry.yarnpkg.com/unplugin-vue-define-options/-/unplugin-vue-define-options-1.3.15.tgz#ad592f132dcce82792e731b8a2eadda4928f8a3b" + integrity sha512-SrNVpWtQXHxnLEpkCvEdhLdVepBIVFuj5Y8qY2bq45NdgBA4Obsq+8NtEP2lzdr0AlQlhgqUE8dxhuqu1mYEzw== + dependencies: + "@vue-macros/common" "1.7.0" + ast-walker-scope "^0.5.0" + unplugin "^1.4.0" + +unplugin-vue-macros@2.4.6: + version "2.4.6" + resolved "https://registry.yarnpkg.com/unplugin-vue-macros/-/unplugin-vue-macros-2.4.6.tgz#42c1cf1193d306eec47f7e041aa066478570419e" + integrity sha512-df8ZxlrFK+rcoDEdNyjdmw14qR7soeeIvnodBXyZg2GauVf8zRBV7nY6NLfMmrdLHiMNpgUPL1WhQMJDxobNAg== + dependencies: + "@vue-macros/better-define" "1.6.9" + "@vue-macros/chain-call" "^0.1.3" + "@vue-macros/common" "1.7.0" + "@vue-macros/define-emit" "^0.1.13" + "@vue-macros/define-models" "1.0.13" + "@vue-macros/define-prop" "^0.2.4" + "@vue-macros/define-props" "1.0.17" + "@vue-macros/define-props-refs" "1.1.7" + "@vue-macros/define-render" "1.4.0" + "@vue-macros/define-slots" "1.0.12" + "@vue-macros/devtools" "^0.1.3" + "@vue-macros/export-expose" "0.0.10" + "@vue-macros/export-props" "0.3.15" + "@vue-macros/hoist-static" "1.4.9" + "@vue-macros/jsx-directive" "0.5.0" + "@vue-macros/named-template" "0.3.16" + "@vue-macros/reactivity-transform" "0.3.19" + "@vue-macros/setup-block" "0.2.15" + "@vue-macros/setup-component" "0.16.16" + "@vue-macros/setup-sfc" "0.16.0" + "@vue-macros/short-emits" "1.4.7" + unplugin "^1.4.0" + unplugin-combine "^0.7.0" + unplugin-vue-define-options "1.3.15" + unplugin@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.3.1.tgz#7af993ba8695d17d61b0845718380caf6af5109f" @@ -5655,6 +6077,16 @@ unplugin@^1.0.0: webpack-sources "^3.2.3" webpack-virtual-modules "^0.5.0" +unplugin@^1.3.2, unplugin@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.4.0.tgz#b771373aa1bc664f50a044ee8009bd3a7aa04d85" + integrity sha512-5x4eIEL6WgbzqGtF9UV8VEC/ehKptPXDS6L2b0mv4FRMkJxRtjaJfOWDd6a8+kYbqsjklix7yWP0N3SUepjXcg== + dependencies: + acorn "^8.9.0" + chokidar "^3.5.3" + webpack-sources "^3.2.3" + webpack-virtual-modules "^0.5.0" + upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" @@ -5885,6 +6317,17 @@ vue@3.2.45: "@vue/server-renderer" "3.2.45" "@vue/shared" "3.2.45" +vue@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/vue/-/vue-3.3.4.tgz#8ed945d3873667df1d0fcf3b2463ada028f88bd6" + integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw== + dependencies: + "@vue/compiler-dom" "3.3.4" + "@vue/compiler-sfc" "3.3.4" + "@vue/runtime-dom" "3.3.4" + "@vue/server-renderer" "3.3.4" + "@vue/shared" "3.3.4" + vuedraggable@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-4.1.0.tgz#edece68adb8a4d9e06accff9dfc9040e66852270" From 1cbc7e49519f8bf87a08c6c575e0c691657bc45e Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Mon, 14 Aug 2023 16:25:58 +0200 Subject: [PATCH 28/50] fix(podcasts): make pagination reactive Part-of: --- front/src/components/audio/ChannelEntries.vue | 45 +++----------- front/src/components/audio/podcast/Table.vue | 61 ++++--------------- 2 files changed, 20 insertions(+), 86 deletions(-) diff --git a/front/src/components/audio/ChannelEntries.vue b/front/src/components/audio/ChannelEntries.vue index 2336e3592..1feefde84 100644 --- a/front/src/components/audio/ChannelEntries.vue +++ b/front/src/components/audio/ChannelEntries.vue @@ -62,46 +62,17 @@ watch(page, fetchData, { immediate: true })