From 288e61dfdf782cf28164d6e90ef20ee7e2c5769d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 11:57:12 +0100 Subject: [PATCH 01/13] fix(deps): update dependency sass to v1.85.1 (#33998) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 65ddac8e4..0d78276bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15526,8 +15526,8 @@ __metadata: linkType: hard "sass@npm:^1.62.1": - version: 1.85.0 - resolution: "sass@npm:1.85.0" + version: 1.85.1 + resolution: "sass@npm:1.85.1" dependencies: "@parcel/watcher": "npm:^2.4.1" chokidar: "npm:^4.0.0" @@ -15538,7 +15538,7 @@ __metadata: optional: true bin: sass: sass.js - checksum: 10c0/a1af0c0596ae1904f66337d0c70a684db6e12210f97be4326cc3dcf18b0f956d7bc45ab2bcc7a8422d433d3eb3c9cb2cc8e60b2dafbdd01fb1ae5a23f5424690 + checksum: 10c0/f843aa1df1dca2f0e9cb2fb247e4939fd514ae4c182cdd1900a0622c0d71b40dfb1c4225f78b78e165a318287ca137ec597695db3e496408bd16a921a2bc2b3f languageName: node linkType: hard From 298ca5359330563130dd84cdde427c3ee040d13b Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 25 Feb 2025 11:58:11 +0100 Subject: [PATCH 02/13] Add choice of law to terms of service generator (#33994) --- app/models/terms_of_service/generator.rb | 1 + app/views/admin/terms_of_service/generates/show.html.haml | 3 +++ config/locales/simple_form.en.yml | 2 ++ config/templates/terms-of-service.md | 2 +- .../admin/terms_of_service/generates_controller_spec.rb | 1 + 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/terms_of_service/generator.rb b/app/models/terms_of_service/generator.rb index 83c229720..6fcfb0115 100644 --- a/app/models/terms_of_service/generator.rb +++ b/app/models/terms_of_service/generator.rb @@ -13,6 +13,7 @@ class TermsOfService::Generator dmca_email domain jurisdiction + choice_of_law ).freeze attr_accessor(*VARIABLES) diff --git a/app/views/admin/terms_of_service/generates/show.html.haml b/app/views/admin/terms_of_service/generates/show.html.haml index 46737e835..0a67aba29 100644 --- a/app/views/admin/terms_of_service/generates/show.html.haml +++ b/app/views/admin/terms_of_service/generates/show.html.haml @@ -22,6 +22,9 @@ .fields-group = form.input :jurisdiction, wrapper: :with_label + .fields-group + = form.input :choice_of_law, wrapper: :with_label + .fields-group = form.input :admin_email, wrapper: :with_label diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index edf0a29a3..d59235222 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -137,6 +137,7 @@ en: admin_email: Legal notices include counternotices, court orders, takedown requests, and law enforcement requests. arbitration_address: Can be the same as Physical address above, or “N/A” if using email arbitration_website: Can be a web form, or “N/A” if using email + choice_of_law: City, region, territory or state the internal substantive laws of which shall govern any and all claims. dmca_address: For US operators, use the address registered in the DMCA Designated Agent Directory. A P.O. Box listing is available upon direct request, use the DMCA Designated Agent Post Office Box Waiver Request to email the Copyright Office and describe that you are a home-based content moderator who fears revenge or retribution for your actions and need to use a P.O. Box to remove your home address from public view. dmca_email: Can be the same email used for “Email address for legal notices” above domain: Unique identification of the online service you are providing. @@ -338,6 +339,7 @@ en: admin_email: Email address for legal notices arbitration_address: Physical address for arbitration notices arbitration_website: Website for submitting arbitration notices + choice_of_law: Choice of Law dmca_address: Physical address for DMCA/copyright notices dmca_email: Email address for DMCA/copyright notices domain: Domain diff --git a/config/templates/terms-of-service.md b/config/templates/terms-of-service.md index 4b11a9897..0a96b1a60 100644 --- a/config/templates/terms-of-service.md +++ b/config/templates/terms-of-service.md @@ -249,7 +249,7 @@ individual basis. ## Choice of Law Any and all claims related to or arising out of your use of, or access to the -Instance shall be governed by internal substantive laws of New York in all +Instance shall be governed by internal substantive laws of %{choice_of_law} in all respects, without regard for the jurisdiction or forum in which you are domiciled, reside, or located at the time of such access or use. diff --git a/spec/controllers/admin/terms_of_service/generates_controller_spec.rb b/spec/controllers/admin/terms_of_service/generates_controller_spec.rb index c1fc7faef..b528bfb57 100644 --- a/spec/controllers/admin/terms_of_service/generates_controller_spec.rb +++ b/spec/controllers/admin/terms_of_service/generates_controller_spec.rb @@ -33,6 +33,7 @@ RSpec.describe Admin::TermsOfService::GeneratesController do dmca_email: 'dmca@host.example', domain: 'host.example', jurisdiction: 'Europe', + choice_of_law: 'New York', }, } end From 6405883eed6023be6d3e9d02075afa2a60d8b603 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:02:29 +0100 Subject: [PATCH 03/13] chore(deps): update dependency haml_lint to v0.61.0 (#33995) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index b2b53c5ea..e5dc64a5b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -273,7 +273,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.60.0) + haml_lint (0.61.0) haml (>= 5.0) parallel (~> 1.10) rainbow From 93f0427b8a84faf68d5d02cdf9a26f98fae16f2b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:02:42 +0100 Subject: [PATCH 04/13] chore(deps): update dependency oj to v3.16.10 (#33997) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index e5dc64a5b..513b69d9c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -432,7 +432,7 @@ GEM nokogiri (1.18.3) mini_portile2 (~> 2.8.2) racc (~> 1.4) - oj (3.16.9) + oj (3.16.10) bigdecimal (>= 3.0) ostruct (>= 0.2) omniauth (2.1.2) From 33643c4c072fc29382e3d395466adfd63a16742c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 14:08:40 +0100 Subject: [PATCH 05/13] New Crowdin Translations (automated) (#33996) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/ast.json | 84 ++++++++++++---------- app/javascript/mastodon/locales/en-GB.json | 1 + app/javascript/mastodon/locales/nn.json | 1 + config/locales/ast.yml | 54 +++++++------- config/locales/doorkeeper.fr.yml | 2 +- config/locales/simple_form.ast.yml | 8 +-- 6 files changed, 82 insertions(+), 68 deletions(-) diff --git a/app/javascript/mastodon/locales/ast.json b/app/javascript/mastodon/locales/ast.json index 440ae8889..2d639fb1e 100644 --- a/app/javascript/mastodon/locales/ast.json +++ b/app/javascript/mastodon/locales/ast.json @@ -4,15 +4,16 @@ "about.disclaimer": "Mastodon ye software gratuito y de códigu llibre, y una marca rexistrada de Mastodon gGmbH.", "about.domain_blocks.no_reason_available": "El motivu nun ta disponible", "about.domain_blocks.preamble": "Polo xeneral, Mastodon permítete ver el conteníu ya interactuar colos perfiles d'otros sirvidores nel fediversu. Estes son les esceiciones que se ficieron nesti sirvidor.", - "about.domain_blocks.silenced.explanation": "Polo xeneral, nun ves los perfiles ya'l conteníu d'esti sirvidor sacante que los busques o decidas siguilos.", + "about.domain_blocks.silenced.explanation": "Polo xeneral, nun ves los perfiles y el conteníu d'esti sirvidor sacante que los busques o decidas siguilos.", "about.domain_blocks.silenced.title": "Llendóse", - "about.domain_blocks.suspended.explanation": "Nun se procesa, atroxa nin intercambia nengún datu d'esti sirvidor, lo que fai que cualesquier interaición o comunicación colos sos perfiles seya imposible.", + "about.domain_blocks.suspended.explanation": "Nun se procesa, atroxa nin intercambia nengún datu d'esti sirvidor, lo que fai imposible cualesquier interaición o comunicación colos sos perfiles.", "about.domain_blocks.suspended.title": "Suspendióse", "about.not_available": "Esta información nun ta disponible nesti sirvidor.", "about.powered_by": "Una rede social descentralizada que tien la teunoloxía de {mastodon}", "about.rules": "Normes del sirvidor", "account.account_note_header": "Nota personal", "account.add_or_remove_from_list": "Amestar o quitar de les llistes", + "account.badges.bot": "Automatizóse", "account.badges.group": "Grupu", "account.block": "Bloquiar a @{name}", "account.block_domain": "Bloquiar el dominiu {domain}", @@ -25,7 +26,7 @@ "account.edit_profile": "Editar el perfil", "account.enable_notifications": "Avisame cuando @{name} espublice artículos", "account.endorse": "Destacar nel perfil", - "account.featured_tags.last_status_never": "Nun hai nengún artículu", + "account.featured_tags.last_status_never": "Nun hai nenguna publicación", "account.featured_tags.title": "Etiquetes destacaes de: {name}", "account.follow": "Siguir", "account.follow_back": "Siguir tamién", @@ -107,6 +108,7 @@ "column.domain_blocks": "Dominios bloquiaos", "column.edit_list": "Editar la llista", "column.favourites": "Favoritos", + "column.firehose": "Feed en direuto", "column.follow_requests": "Solicitúes de siguimientu", "column.home": "Aniciu", "column.lists": "Llistes", @@ -126,9 +128,9 @@ "community.column_settings.remote_only": "Namás lo remoto", "compose.language.change": "Camudar la llingua", "compose.language.search": "Buscar llingües…", - "compose.published.body": "Espublizóse l'artículu.", + "compose.published.body": "Publicóse la publicación.", "compose.published.open": "Abrir", - "compose.saved.body": "Post guardáu.", + "compose.saved.body": "Guardóse la publicación.", "compose_form.direct_message_warning_learn_more": "Saber más", "compose_form.encryption_warning": "Los artículos de Mastodon nun tán cifraos de puntu a puntu. Nun compartas nengún tipu d'información sensible per Mastodon.", "compose_form.lock_disclaimer": "La to cuenta nun ye {locked}. Cualesquier perfil pue siguite pa ver los artículos que son namás pa siguidores.", @@ -137,34 +139,33 @@ "compose_form.poll.option_placeholder": "Opción {number}", "compose_form.poll.type": "Tipu", "compose_form.publish": "Espublizar", - "compose_form.publish_form": "Artículu nuevu", + "compose_form.publish_form": "Publicación nueva", "compose_form.reply": "Responder", "confirmation_modal.cancel": "Encaboxar", "confirmations.block.confirm": "Bloquiar", "confirmations.delete.confirm": "Desaniciar", - "confirmations.delete.message": "¿De xuru que quies desaniciar esti artículu?", - "confirmations.delete.title": "¿Desaniciar l'artículu?", + "confirmations.delete.message": "¿De xuru que quies desaniciar esta publicación?", + "confirmations.delete.title": "¿Quies desaniciar esta publicación?", "confirmations.delete_list.confirm": "Desaniciar", "confirmations.delete_list.message": "¿De xuru que quies desaniciar permanentemente esta llista?", - "confirmations.delete_list.title": "¿Desaniciar la llista?", + "confirmations.delete_list.title": "¿Quies desaniciar la llista?", "confirmations.discard_edit_media.confirm": "Escartar", "confirmations.edit.confirm": "Editar", "confirmations.edit.message": "La edición va sobrescribir el mensaxe que tas escribiendo. ¿De xuru que quies siguir?", "confirmations.follow_to_list.title": "¿Siguir al usuariu?", "confirmations.logout.confirm": "Zarrar la sesión", "confirmations.logout.message": "¿De xuru que quies zarrar la sesión?", - "confirmations.logout.title": "¿Zarrar la sesión?", + "confirmations.logout.title": "¿Quies zarrar la sesión?", "confirmations.missing_alt_text.confirm": "Amestar testu alternativu", "confirmations.missing_alt_text.title": "¿Quies amestar testu alternativu?", "confirmations.redraft.confirm": "Desaniciar y reeditar", - "confirmations.redraft.message": "¿De xuru que quies desaniciar esti artículu y reeditalu? Van perdese los favoritos y comparticiones, y les rempuestes al artículu orixinal van quedar güérfanes.", - "confirmations.redraft.title": "¿Desaniciar ya reeditar l'artículu?", + "confirmations.redraft.title": "¿Desaniciar y reeditar la publicación?", "confirmations.reply.confirm": "Responder", "confirmations.reply.message": "Responder agora va sobrescribir el mensaxe que tas componiendo anguaño. ¿De xuru que quies siguir?", "confirmations.unfollow.confirm": "Dexar de siguir", "confirmations.unfollow.message": "¿De xuru que quies dexar de siguir a {name}?", "confirmations.unfollow.title": "¿Dexar de siguir al usuariu?", - "content_warning.hide": "Anubrir l'artículu", + "content_warning.hide": "Esconder la publicación", "content_warning.show": "Amosar de toes toes", "content_warning.show_more": "Amosar más", "conversation.delete": "Desaniciar la conversación", @@ -186,7 +187,7 @@ "domain_block_modal.title": "Bloquiar el dominiu?", "domain_pill.server": "Sirvidor", "domain_pill.username": "Nome d'usuariu", - "embed.instructions": "Empotra esti artículu nel to sitiu web copiando'l códigu d'abaxo.", + "embed.instructions": "Empotra esta publicación nel to sitiu web copiando'l códigu d'abaxo.", "embed.preview": "Va apaecer asina:", "emoji_button.activity": "Actividá", "emoji_button.flags": "Banderes", @@ -201,9 +202,9 @@ "emoji_button.symbols": "Símbolos", "emoji_button.travel": "Viaxes y llugares", "empty_column.account_suspended": "Cuenta suspendida", - "empty_column.account_timeline": "¡Equí nun hai nengún artículu!", + "empty_column.account_timeline": "¡Equí nun hai nenguna publicación!", "empty_column.blocks": "Nun bloquiesti a nengún perfil.", - "empty_column.bookmarked_statuses": "Nun tienes nengún artículu en Marcadores. Cuando amiestes dalgún, apaez equí.", + "empty_column.bookmarked_statuses": "Nun tienes nenguna publicación en Marcadores. Cuando amiestes dalguna, va apaecer equí.", "empty_column.direct": "Nun tienes nenguna mención privada. Cuando unvies o recibas dalguna, apaez equí.", "empty_column.domain_blocks": "Nun hai nengún dominiu bloquiáu.", "empty_column.explore_statuses": "Agora nun hai nada en tendencia. ¡Volvi equí dempués!", @@ -223,21 +224,21 @@ "explore.trending_links": "Noticies", "explore.trending_statuses": "Artículos", "explore.trending_tags": "Etiquetes", - "filter_modal.added.context_mismatch_explanation": "Esta categoría de peñera nun s'aplica al contestu nel qu'accediesti a esti artículu. Si tamién quies que se peñere l'artículu nesti contestu, tienes d'editar la peñera.", + "filter_modal.added.context_mismatch_explanation": "Esta categoría de peñera nun s'aplica al contestu nel qu'accediesti a esta publicación. Si tamién quies que se peñere la publicación nesti contestu, tienes d'editar la peñera.", "filter_modal.added.context_mismatch_title": "¡El contestu nun coincide!", "filter_modal.added.expired_explanation": "Esta categoría de peñera caducó, tienes de camudar la so data de caducidá p'aplicala.", "filter_modal.added.expired_title": "¡La peñera caducó!", "filter_modal.added.review_and_configure": "Pa revisar y configurar a fondu esta categoría de peñera, vete a la {settings_link}.", "filter_modal.added.review_and_configure_title": "Configuración de la peñera", "filter_modal.added.settings_link": "páxina de configuración", - "filter_modal.added.short_explanation": "Esti artículu amestóse a la categoría de peñera siguiente: {title}.", + "filter_modal.added.short_explanation": "Esta publicación amestóse a la categoría de peñera siguiente: {title}.", "filter_modal.added.title": "¡Amestóse la peñera!", "filter_modal.select_filter.expired": "caducó", "filter_modal.select_filter.prompt_new": "Categoría nueva: {name}", "filter_modal.select_filter.search": "Buscar o crear", "filter_modal.select_filter.subtitle": "Usa una categoría esistente o créala", - "filter_modal.select_filter.title": "Peñerar esti artículu", - "filter_modal.title.status": "Peñera d'un artículu", + "filter_modal.select_filter.title": "Peñerar esta publicación", + "filter_modal.title.status": "Peñera d'una publicación", "firehose.all": "Tolos sirvidores", "firehose.local": "Esti sirvidor", "firehose.remote": "Otros sirvidores", @@ -285,20 +286,20 @@ "interaction_modal.on_another_server": "N'otru sirvidor", "interaction_modal.on_this_server": "Nesti sirvidor", "interaction_modal.title.follow": "Siguir a {name}", - "interaction_modal.title.reply": "Rempuesta al artículu de: {name}", + "interaction_modal.title.reply": "Rempuesta a la publicación de: {name}", "interaction_modal.title.vote": "Vota na encuesta de {name}", "intervals.full.days": "{number, plural, one {# día} other {# díes}}", "intervals.full.hours": "{number, plural, one {# hora} other {# hores}}", "intervals.full.minutes": "{number, plural, one {# minutu} other {# minutos}}", "keyboard_shortcuts.back": "Dir p'atrás", "keyboard_shortcuts.blocked": "Abrir la llista de perfiles bloquiaos", - "keyboard_shortcuts.boost": "Compartir un artículu", + "keyboard_shortcuts.boost": "Compartir una publicación", "keyboard_shortcuts.column": "Enfocar una columna", "keyboard_shortcuts.compose": "Enfocar l'área de composición", "keyboard_shortcuts.description": "Descripción", "keyboard_shortcuts.direct": "p'abrir la columna de les menciones privaes", "keyboard_shortcuts.down": "Baxar na llista", - "keyboard_shortcuts.enter": "Abrir un artículu", + "keyboard_shortcuts.enter": "Abrir una publicación", "keyboard_shortcuts.federated": "Abrir la llinia de tiempu federada", "keyboard_shortcuts.heading": "Atayos del tecláu", "keyboard_shortcuts.home": "Abrir la llinia de tiempu del aniciu", @@ -312,12 +313,12 @@ "keyboard_shortcuts.open_media": "Abrir el conteníu mutimedia", "keyboard_shortcuts.pinned": "Abrir la llista d'artículos fixaos", "keyboard_shortcuts.profile": "Abrir el perfil del autor/a", - "keyboard_shortcuts.reply": "Responder a un artículu", + "keyboard_shortcuts.reply": "Responder a una publicación", "keyboard_shortcuts.requests": "Abrir la llista de solicitúes de siguimientu", "keyboard_shortcuts.search": "Enfocar la barra de busca", "keyboard_shortcuts.start": "Abrir la columna «Entamar»", "keyboard_shortcuts.toggle_sensitivity": "Amosar/esconder el conteníu multimedia", - "keyboard_shortcuts.toot": "Comenzar un artículu nuevu", + "keyboard_shortcuts.toot": "Escribir una publicación nueva", "keyboard_shortcuts.unfocus": "Desenfocar l'área de composición/busca", "keyboard_shortcuts.up": "Xubir na llista", "lightbox.close": "Zarrar", @@ -377,9 +378,9 @@ "notification.mentioned_you": "{name} mentóte", "notification.moderation-warning.learn_more": "Deprender más", "notification.poll": "Finó una encuesta na que votesti", - "notification.reblog": "{name} compartió'l to artículu", + "notification.reblog": "{name} compartió la to publicación", "notification.status": "{name} ta acabante d'espublizar", - "notification.update": "{name} editó un artículu", + "notification.update": "{name} editó una publicación", "notification_requests.edit_selection": "Editar", "notification_requests.exit_selection": "Fecho", "notifications.clear": "Borrar los avisos", @@ -421,9 +422,10 @@ "poll.votes": "{votes, plural, one {# votu} other {# votos}}", "poll_button.add_poll": "Amestar una encuesta", "poll_button.remove_poll": "Quitar la encuesta", - "privacy.change": "Configurar la privacidá del artículu", + "privacy.change": "Configurar la privacidá de la publicación", + "privacy.direct.short": "Mención privada", "privacy.private.short": "Siguidores", - "privacy.public.short": "Artículu públicu", + "privacy.public.short": "Publicación pública", "privacy_policy.last_updated": "Data del últimu anovamientu: {date}", "privacy_policy.title": "Política de privacidá", "refresh": "Anovar", @@ -447,7 +449,7 @@ "report.category.subtitle": "Escueyi la meyor opción", "report.category.title": "Dinos qué pasa con esti {type}", "report.category.title_account": "perfil", - "report.category.title_status": "artículu", + "report.category.title_status": "publicación", "report.close": "Fecho", "report.comment.title": "¿Hai daqué más qu'habríemos saber?", "report.forward": "Reunviar a {target}", @@ -467,7 +469,7 @@ "report.rules.subtitle": "Seleiciona tolo que s'axuste", "report.rules.title": "¿Qué normes s'incumplen?", "report.statuses.subtitle": "Seleiciona tolo que s'axuste", - "report.statuses.title": "¿Hai dalgún artículu qu'apoye esti informe?", + "report.statuses.title": "¿Hai dalguna publicación qu'apoye esti informe?", "report.submit": "Unviar", "report.target": "Informe de: {target}", "report.thanks.take_action": "Equí tienes les opciones pa controlar qué ves en Mastodon:", @@ -476,7 +478,7 @@ "report.thanks.title_actionable": "Gracies pol informe, el casu yá ta n'investigación.", "report.unfollow": "Dexar de siguir a @{name}", "report.unfollow_explanation": "Sigues a esta cuenta. Pa dexar de ver los sos artículos nel to feed d'aniciu, dexa de siguila.", - "report_notification.attached_statuses": "{count, plural, one {Axuntóse {count} artículu} other {Axuntáronse {count} artículos}}", + "report_notification.attached_statuses": "{count, plural, one {Axuntóse {count} publicación} other {Axuntáronse {count} publicaciones}}", "report_notification.categories.legal": "Llegal", "report_notification.categories.legal_sentence": "conteníu illegal", "report_notification.categories.spam": "Spam", @@ -489,6 +491,7 @@ "search.quick_action.go_to_hashtag": "Dir a la etiqueta {x}", "search.quick_action.status_search": "Artículos que concasen con {x}", "search.search_or_paste": "Busca o apiega una URL", + "search_popout.full_text_search_disabled_message": "Nun ta disponible nel dominiu {domain}.", "search_popout.language_code": "códigu de llingua ISO", "search_popout.options": "Opciones de busca", "search_popout.quick_actions": "Aiciones rápides", @@ -500,22 +503,25 @@ "search_results.hashtags": "Etiquetes", "search_results.see_all": "Ver too", "search_results.statuses": "Artículos", + "server_banner.is_one_of_many": "{domain} ye unu de los munchos sirvidores independientes de Mastodon que pues usar pa participar nel fediversu.", "server_banner.server_stats": "Estadístiques del sirvidor:", "sign_in_banner.create_account": "Crear una cuenta", + "sign_in_banner.mastodon_is": "Mastodon ye la meyor manera de siguir al momentu qué pasa.", + "sign_in_banner.sign_in": "Aniciar la sesión", "sign_in_banner.sso_redirect": "Aniciar la sesión o rexistrase", "status.admin_account": "Abrir la interfaz de moderación pa @{name}", "status.admin_domain": "Abrir la interfaz de moderación pa «{domain}»", - "status.admin_status": "Abrir esti artículu na interfaz de moderación", + "status.admin_status": "Abrir esta publicación na interfaz de moderación", "status.block": "Bloquiar a @{name}", "status.bookmark": "Meter en Marcadores", - "status.cannot_reblog": "Esti artículu nun se pue compartir", - "status.copy": "Copiar l'enllaz al artículu", + "status.cannot_reblog": "Esta publicación nun se pue compartir", + "status.copy": "Copiar l'enllaz a la publicación", "status.delete": "Desaniciar", "status.direct": "Mentar a @{name} per privao", "status.direct_indicator": "Mención privada", "status.edited_x_times": "Editóse {count, plural, one {{count} vegada} other {{count} vegaes}}", "status.embed": "Consiguir el códigu pa empotrar", - "status.filter": "Peñerar esti artículu", + "status.filter": "Peñerar esta publicación", "status.history.created": "{name} creó {date}", "status.history.edited": "{name} editó {date}", "status.load_more": "Cargar más", @@ -524,13 +530,13 @@ "status.more": "Más", "status.mute": "Desactivar los avisos de @{name}", "status.mute_conversation": "Desactivar los avisos de la conversación", - "status.open": "Espander esti artículu", + "status.open": "Espander esta publicación", "status.pin": "Fixar nel perfil", - "status.pinned": "Artículu fixáu", + "status.pinned": "Publicación fixada", "status.read_more": "Lleer más", "status.reblog": "Compartir", "status.reblogged_by": "{name} compartió", - "status.reblogs.empty": "Naide nun compartió esti artículu. Cuando daquién lo faiga, apaez equí.", + "status.reblogs.empty": "Naide nun compartió esta publicación. Cuando daquién lo faiga, va apaecer equí.", "status.redraft": "Desaniciar y reeditar", "status.remove_bookmark": "Desaniciar el marcador", "status.replied_to": "En rempuesta a {name}", diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index 54dda38db..2af100a56 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -697,6 +697,7 @@ "poll_button.remove_poll": "Remove poll", "privacy.change": "Change post privacy", "privacy.direct.long": "Everyone mentioned in the post", + "privacy.direct.short": "Private mention", "privacy.private.long": "Only your followers", "privacy.private.short": "Followers", "privacy.public.long": "Anyone on and off Mastodon", diff --git a/app/javascript/mastodon/locales/nn.json b/app/javascript/mastodon/locales/nn.json index 60481f8cc..c0a3ec183 100644 --- a/app/javascript/mastodon/locales/nn.json +++ b/app/javascript/mastodon/locales/nn.json @@ -697,6 +697,7 @@ "poll_button.remove_poll": "Fjern rundspørjing", "privacy.change": "Endre personvernet på innlegg", "privacy.direct.long": "Alle nemnde i innlegget", + "privacy.direct.short": "Privat omtale", "privacy.private.long": "Berre dei som fylgjer deg", "privacy.private.short": "Fylgjarar", "privacy.public.long": "Kven som helst på og av Mastodon", diff --git a/config/locales/ast.yml b/config/locales/ast.yml index 6c2ebbfd7..83d158766 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -9,8 +9,8 @@ ast: last_active: última actividá nothing_here: "¡Equí nun hai nada!" posts: - one: Artículu - other: Artículos + one: Publicación + other: Publicaciones posts_tab_heading: Artículos admin: account_actions: @@ -76,7 +76,7 @@ ast: destroy_announcement_html: "%{name} desanició l'anunciu «%{target}»" destroy_custom_emoji_html: "%{name} desanició'l fustaxe %{target}" destroy_domain_block_html: "%{name} desbloquió'l dominiu %{target}" - destroy_status_html: "%{name} quitó l'artículu de: %{target}" + destroy_status_html: "%{name} quitó la publicación de: %{target}" destroy_user_role_html: "%{name} desanició'l rol %{target}" disable_custom_emoji_html: "%{name} desactivó'l fustaxe «%{target}»" enable_custom_emoji_html: "%{name} activó'l fustaxe «%{target}»" @@ -87,7 +87,7 @@ ast: unblock_email_account_html: "%{name} desbloquió la direición de corréu electrónicu de: %{target}" update_announcement_html: "%{name} anovó l'anunciu «%{target}»" update_custom_emoji_html: "%{name} anovó'l fustaxe «%{target}»" - update_status_html: "%{name} anovó l'artículu de: %{target}" + update_status_html: "%{name} anovó la publicación de: %{target}" update_user_role_html: "%{name} camudó'l rol %{target}" empty: Nun s'atopó nengún rexistru. announcements: @@ -100,7 +100,7 @@ ast: create: Crear l'anunciu title: Anunciu nuevu publish: Espublizar - published_msg: "¡L'anunciu espublizóse correutamente!" + published_msg: "¡L'anunciu publicóse correutamente!" scheduled_msg: "¡Programóse l'espublizamientu del anunciu!" title: Anuncios unpublish: Dexar d'espublizar @@ -347,14 +347,14 @@ ast: back_to_account: Volver a la páxina de la cuenta language: Llingua metadata: Metadatos - original_status: Artículu orixinal + original_status: Publicación orixinal visibility: Visibilidá with_media: Con elementos multimedia strikes: actions: - delete_statuses: "%{name} desanició l'artículu de: %{target}" + delete_statuses: "%{name} desanició la publicación de: %{target}" disable: "%{name} conxeló la cuenta de: %{target}" - mark_statuses_as_sensitive: "%{name} marcó l'artículu de %{target} como sensible" + mark_statuses_as_sensitive: "%{name} marcó la publicación de %{target} como sensible" none: "%{name} unvió una alvertencia a %{target}" sensitive: "%{name} marcó la cuenta de %{target} como sensible" suspend: "%{name} suspendió la cuenta de: %{target}" @@ -375,8 +375,8 @@ ast: preview_card_providers: title: Espublizadores statuses: - allow: Permitir l'artículu - disallow: Refugar l'artículu + allow: Permitir la publicación + disallow: Refugar la publicación title: Artículos en tendencia tags: current_score: 'Puntuación total: %{score}' @@ -459,6 +459,10 @@ ast: logout: Zarrar la sesión migrate_account: Cambéu de cuenta migrate_account_html: Si quies redirixir esta cuenta a otra diferente, pues configurar esta opción equí. + progress: + confirm: Confirmación del corréu electrónicu + details: Los tos detalles + rules: Aceptación de normes providers: cas: CAS saml: SAML @@ -470,6 +474,8 @@ ast: security: Seguranza setup: link_not_received: "¿Nun consiguiesti l'enllaz?" + sign_in: + preamble_html: Anicia la sesión coles credenciales del dominiu %{domain}. Si la to cuenta ta agospiada n'otru sirvidor, nun vas ser a aniciar la sesión equí. sign_up: title: 'Creación d''una cuenta en: %{domain}.' status: @@ -515,8 +521,8 @@ ast: created_at: Data recipient: Dirixóse a reject_appeal: Refugar l'apellación - status: 'Artículu #%{id}' - status_removed: L'artículu yá se quitó del sistema + status: 'Publicación #%{id}' + status_removed: La publicación yá se quitó del sistema your_appeal_approved: Aprobóse la to apellación your_appeal_pending: Unviesti una apellación your_appeal_rejected: Refugóse la to apellación @@ -572,8 +578,8 @@ ast: one: "%{count} pallabra clave" other: "%{count} pallabres claves" statuses: - one: "%{count} artículu" - other: "%{count} artículos" + one: "%{count} publicación" + other: "%{count} publicaciones" title: Peñeres new: title: Amestar una peñera @@ -637,7 +643,7 @@ ast: successful_sign_in_html: Anicióse correutamente la sesión col métodu «%{method}» dende %{ip} (%{browser}) media_attachments: validations: - images_and_video: Nun se pue axuntar nengún videu a un artículu que yá contién imáxenes + images_and_video: Nun se pue axuntar nengún videu a una publicación que yá contién imáxenes too_many: Nun se puen axuntar más de 4 ficheros migrations: errors: @@ -654,7 +660,7 @@ ast: sign_up: subject: "%{name} rexistróse" favourite: - subject: "%{name} marcó'l to artículu como favoritu" + subject: "%{name} marcó la to publicación como favorita" follow: body: "¡Agora %{name} siguete!" subject: "%{name} ta siguiéndote" @@ -666,10 +672,10 @@ ast: subject: "%{name} mentóte" title: Mención nueva reblog: - body: "%{name} compartió'l to artículu:" - subject: "%{name} compartió'l to artículu" + body: "%{name} compartió la to publicación:" + subject: "%{name} compartió la to publicación" update: - subject: "%{name} editó un artículu" + subject: "%{name} editó una publicación" notifications: email_events_hint: 'Seleiciona los eventos de los que quies recibir avisos:' number: @@ -798,12 +804,12 @@ ast: other: "%{count} vídeos" default_language: La mesma que la de la interfaz errors: - in_reply_not_found: L'artículu al que tentes de responder paez que nun esiste. + in_reply_not_found: La publicación a la que tentes de responder paez que nun esiste. pin_errors: direct: Nun se puen fixar los artículos que son visibles namás pa los usuarios mentaos limit: Yá fixesti'l númberu máximu d'artículos - ownership: Nun se pue fixar l'artículu d'otru perfil - reblog: Nun se pue fixar un artículu compartíu + ownership: Nun se pue fixar la publicación d'otru perfil + reblog: Nun se pue fixar una publicación compartida title: "%{name}: «%{quote}»" visibilities: direct: Mensaxe direutu @@ -817,12 +823,12 @@ ast: keep_direct: Caltener los mensaxes direutos keep_direct_hint: Nun desanicia nengún mensaxe direutu keep_media: Caltener los artículos con elementos multimedia - keep_media_hint: Nun desanicia nengún artículu de to que contenta elementos multimedia + keep_media_hint: Nun desanicia nenguna publicación de to que contenta elementos multimedia keep_pinned: Caltener los artículos fixaos keep_polls: Caltener les encuestes keep_polls_hint: Nun desanicia nenguna encuesta de to keep_self_bookmark: Caltener los artículos que metieres en Marcadores - keep_self_bookmark_hint: Nun desanicia nengún artículu que metieres en Marcadores + keep_self_bookmark_hint: Nun desanicia nenguna publicación que metieres en Marcadores min_age: '1209600': 2 selmanes '15778476': 6 meses diff --git a/config/locales/doorkeeper.fr.yml b/config/locales/doorkeeper.fr.yml index 71c9605d8..d956225db 100644 --- a/config/locales/doorkeeper.fr.yml +++ b/config/locales/doorkeeper.fr.yml @@ -25,7 +25,7 @@ fr: edit: Modifier submit: Envoyer confirmations: - destroy: En êtes-vous sûr ? + destroy: En êtes-vous certain ? edit: title: Modifier l’application form: diff --git a/config/locales/simple_form.ast.yml b/config/locales/simple_form.ast.yml index 997423449..9e5db2ba3 100644 --- a/config/locales/simple_form.ast.yml +++ b/config/locales/simple_form.ast.yml @@ -104,11 +104,11 @@ ast: setting_aggregate_reblogs: Agrupar los artículos compartíos nes llinies de tiempu setting_always_send_emails: Unviar siempre los avisos per corréu electrónicu setting_auto_play_gif: Reproducir automáticamente los GIFs - setting_boost_modal: Amosar el diálogu de confirmación enantes de compartir un artículu + setting_boost_modal: Amosar el diálogu de confirmación enantes de compartir una publicación setting_default_language: Llingua de los artículos setting_default_privacy: Privacidá de los artículos setting_default_sensitive: Marcar siempre tol conteníu como sensible - setting_delete_modal: Amosar el diálogu de confirmación enantes de desaniciar un artículu + setting_delete_modal: Amosar el diálogu de confirmación enantes de desaniciar una publicación setting_disable_hover_cards: Desactivar la previsualización de perfiles al pasar el mur penriba setting_disable_swiping: Desactivar el movimientu de desplazamientu setting_display_media: Conteníu multimedia @@ -160,12 +160,12 @@ ast: sign_up_block: Bloquiar el rexistru de cuentes nueves sign_up_requires_approval: Llendar les cuentes rexistraes nueves notification_emails: - favourite: Daquién marcó como favoritu'l to artículu + favourite: Daquién marcó como favorita la to publicación follow: Daquién te sigue follow_request: Daquién solicitó siguite mention: Daquién te mentó pending_account: Una cuenta nueva precisa una revisión - reblog: Daquién compartió'l to artículu + reblog: Daquién compartió la to publicación report: Unvióse un informe nuevu software_updates: label: Hai disponible un anovamientu de Mastodon From 20531d1e078a27116dea53ce21c1b32bf3774eca Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 25 Feb 2025 15:37:44 +0100 Subject: [PATCH 06/13] Fix `GET /api/v2/notifications/:id` and `POST /api/v2/notifications/:id/dismiss` for ungrouped notifications (#33990) --- .../api/v2/notifications_controller.rb | 4 +-- app/models/concerns/notification/groups.rb | 4 +++ spec/requests/api/v2/notifications_spec.rb | 25 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/v2/notifications_controller.rb b/app/controllers/api/v2/notifications_controller.rb index cc38b9511..848c361cf 100644 --- a/app/controllers/api/v2/notifications_controller.rb +++ b/app/controllers/api/v2/notifications_controller.rb @@ -46,7 +46,7 @@ class Api::V2::NotificationsController < Api::BaseController end def show - @notification = current_account.notifications.without_suspended.find_by!(group_key: params[:group_key]) + @notification = current_account.notifications.without_suspended.by_group_key(params[:group_key]).take! presenter = GroupedNotificationsPresenter.new(NotificationGroup.from_notifications([@notification])) render json: presenter, serializer: REST::DedupNotificationGroupSerializer end @@ -57,7 +57,7 @@ class Api::V2::NotificationsController < Api::BaseController end def dismiss - current_account.notifications.where(group_key: params[:group_key]).destroy_all + current_account.notifications.by_group_key(params[:group_key]).destroy_all render_empty end diff --git a/app/models/concerns/notification/groups.rb b/app/models/concerns/notification/groups.rb index 2f29bd9ce..914910e8f 100644 --- a/app/models/concerns/notification/groups.rb +++ b/app/models/concerns/notification/groups.rb @@ -7,6 +7,10 @@ module Notification::Groups GROUPABLE_NOTIFICATION_TYPES = %i(favourite reblog follow).freeze MAXIMUM_GROUP_SPAN_HOURS = 12 + included do + scope :by_group_key, ->(group_key) { group_key&.start_with?('ungrouped-') ? where(id: group_key.delete_prefix('ungrouped-')) : where(group_key: group_key) } + end + def set_group_key! return if filtered? || GROUPABLE_NOTIFICATION_TYPES.exclude?(type) diff --git a/spec/requests/api/v2/notifications_spec.rb b/spec/requests/api/v2/notifications_spec.rb index b2f6d71b5..a7608e141 100644 --- a/spec/requests/api/v2/notifications_spec.rb +++ b/spec/requests/api/v2/notifications_spec.rb @@ -365,6 +365,18 @@ RSpec.describe 'Notifications' do .to start_with('application/json') end + context 'with an ungrouped notification' do + let(:notification) { Fabricate(:notification, account: user.account, type: :favourite) } + + it 'returns http success' do + get "/api/v2/notifications/ungrouped-#{notification.id}", headers: headers + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + end + end + context 'when notification belongs to someone else' do let(:notification) { Fabricate(:notification, group_key: 'foobar') } @@ -396,6 +408,19 @@ RSpec.describe 'Notifications' do expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound) end + context 'with an ungrouped notification' do + let(:notification) { Fabricate(:notification, account: user.account, type: :favourite) } + + it 'destroys the notification' do + post "/api/v2/notifications/ungrouped-#{notification.id}/dismiss", headers: headers + + expect(response).to have_http_status(200) + expect(response.content_type) + .to start_with('application/json') + expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + context 'when notification belongs to someone else' do let(:notification) { Fabricate(:notification, group_key: 'foobar') } From ebde60ca82318d20628b591ef31ab15aa92edd3a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 25 Feb 2025 16:30:46 +0100 Subject: [PATCH 07/13] Refactor `
` into TypeScript (#33956) --- app/javascript/mastodon/actions/accounts.js | 7 + .../mastodon/components/follow_button.tsx | 2 +- .../features/account/components/header.jsx | 528 -------- .../features/account_gallery/index.jsx | 4 +- .../components/account_header.tsx | 1057 +++++++++++++++++ .../account_timeline/components/header.jsx | 155 --- .../containers/header_container.jsx | 153 --- .../features/account_timeline/index.jsx | 6 +- .../mastodon/features/followers/index.jsx | 6 +- .../mastodon/features/following/index.jsx | 6 +- .../mastodon/models/dropdown_menu.ts | 24 + app/javascript/mastodon/selectors/accounts.ts | 14 + app/javascript/mastodon/selectors/index.js | 18 +- 13 files changed, 1121 insertions(+), 859 deletions(-) delete mode 100644 app/javascript/mastodon/features/account/components/header.jsx create mode 100644 app/javascript/mastodon/features/account_timeline/components/account_header.tsx delete mode 100644 app/javascript/mastodon/features/account_timeline/components/header.jsx delete mode 100644 app/javascript/mastodon/features/account_timeline/containers/header_container.jsx create mode 100644 app/javascript/mastodon/models/dropdown_menu.ts diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index 3d0e8b8c9..d821381ce 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -142,6 +142,13 @@ export function fetchAccountFail(id, error) { }; } +/** + * @param {string} id + * @param {Object} options + * @param {boolean} [options.reblogs] + * @param {boolean} [options.notify] + * @returns {function(): void} + */ export function followAccount(id, options = { reblogs: true }) { return (dispatch, getState) => { const alreadyFollowing = getState().getIn(['relationships', id, 'following']); diff --git a/app/javascript/mastodon/components/follow_button.tsx b/app/javascript/mastodon/components/follow_button.tsx index a21317e52..f49abfd2b 100644 --- a/app/javascript/mastodon/components/follow_button.tsx +++ b/app/javascript/mastodon/components/follow_button.tsx @@ -55,7 +55,7 @@ export const FollowButton: React.FC<{ ); } - if (!relationship) return; + if (!relationship || !accountId) return; if (accountId === me) { return; diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx deleted file mode 100644 index 003845c32..000000000 --- a/app/javascript/mastodon/features/account/components/header.jsx +++ /dev/null @@ -1,528 +0,0 @@ -import PropTypes from 'prop-types'; - -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; - -import classNames from 'classnames'; -import { Helmet } from 'react-helmet'; -import { NavLink, withRouter } from 'react-router-dom'; - -import { isFulfilled, isRejected } from '@reduxjs/toolkit'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; - -import CheckIcon from '@/material-icons/400-24px/check.svg?react'; -import LockIcon from '@/material-icons/400-24px/lock.svg?react'; -import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; -import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react'; -import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react'; -import ShareIcon from '@/material-icons/400-24px/share.svg?react'; -import { Avatar } from 'mastodon/components/avatar'; -import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge'; -import { Button } from 'mastodon/components/button'; -import { CopyIconButton } from 'mastodon/components/copy_icon_button'; -import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters'; -import { Icon } from 'mastodon/components/icon'; -import { IconButton } from 'mastodon/components/icon_button'; -import { LoadingIndicator } from 'mastodon/components/loading_indicator'; -import { ShortNumber } from 'mastodon/components/short_number'; -import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; -import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; -import { autoPlayGif, me, domain as localDomain } from 'mastodon/initial_state'; -import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; -import { WithRouterPropTypes } from 'mastodon/utils/react_router'; - -import AccountNoteContainer from '../containers/account_note_container'; -import FollowRequestNoteContainer from '../containers/follow_request_note_container'; - -import { DomainPill } from './domain_pill'; - -const messages = defineMessages({ - unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, - follow: { id: 'account.follow', defaultMessage: 'Follow' }, - followBack: { id: 'account.follow_back', defaultMessage: 'Follow back' }, - mutual: { id: 'account.mutual', defaultMessage: 'Mutual' }, - cancel_follow_request: { id: 'account.cancel_follow_request', defaultMessage: 'Withdraw follow request' }, - requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' }, - unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, - edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, - linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' }, - account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' }, - mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, - direct: { id: 'account.direct', defaultMessage: 'Privately mention @{name}' }, - unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, - block: { id: 'account.block', defaultMessage: 'Block @{name}' }, - mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, - report: { id: 'account.report', defaultMessage: 'Report @{name}' }, - share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, - copy: { id: 'account.copy', defaultMessage: 'Copy link to profile' }, - media: { id: 'account.media', defaultMessage: 'Media' }, - blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' }, - unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, - hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, - showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, - enableNotifications: { id: 'account.enable_notifications', defaultMessage: 'Notify me when @{name} posts' }, - disableNotifications: { id: 'account.disable_notifications', defaultMessage: 'Stop notifying me when @{name} posts' }, - pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned posts' }, - preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, - follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, - favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' }, - lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, - followed_tags: { id: 'navigation_bar.followed_tags', defaultMessage: 'Followed hashtags' }, - blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, - domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Blocked domains' }, - mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, - endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, - unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, - add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, - admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, - admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' }, - languages: { id: 'account.languages', defaultMessage: 'Change subscribed languages' }, - openOriginalPage: { id: 'account.open_original_page', defaultMessage: 'Open original page' }, -}); - -const titleFromAccount = account => { - const displayName = account.get('display_name'); - const acct = account.get('acct') === account.get('username') ? `${account.get('username')}@${localDomain}` : account.get('acct'); - const prefix = displayName.trim().length === 0 ? account.get('username') : displayName; - - return `${prefix} (@${acct})`; -}; - -const messageForFollowButton = relationship => { - if(!relationship) return messages.follow; - - if (relationship.get('following') && relationship.get('followed_by')) { - return messages.mutual; - } else if (relationship.get('following') || relationship.get('requested')) { - return messages.unfollow; - } else if (relationship.get('followed_by')) { - return messages.followBack; - } else { - return messages.follow; - } -}; - -const dateFormatOptions = { - month: 'short', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', -}; - -class Header extends ImmutablePureComponent { - - static propTypes = { - identity: identityContextPropShape, - account: ImmutablePropTypes.record, - identity_props: ImmutablePropTypes.list, - onFollow: PropTypes.func.isRequired, - onBlock: PropTypes.func.isRequired, - onMention: PropTypes.func.isRequired, - onDirect: PropTypes.func.isRequired, - onReblogToggle: PropTypes.func.isRequired, - onNotifyToggle: PropTypes.func.isRequired, - onReport: PropTypes.func.isRequired, - onMute: PropTypes.func.isRequired, - onBlockDomain: PropTypes.func.isRequired, - onUnblockDomain: PropTypes.func.isRequired, - onEndorseToggle: PropTypes.func.isRequired, - onAddToList: PropTypes.func.isRequired, - onEditAccountNote: PropTypes.func.isRequired, - onChangeLanguages: PropTypes.func.isRequired, - onInteractionModal: PropTypes.func.isRequired, - onOpenAvatar: PropTypes.func.isRequired, - onOpenURL: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - domain: PropTypes.string.isRequired, - hidden: PropTypes.bool, - ...WithRouterPropTypes, - }; - - setRef = c => { - this.node = c; - }; - - openEditProfile = () => { - window.open('/settings/profile', '_blank'); - }; - - isStatusesPageActive = (match, location) => { - if (!match) { - return false; - } - - return !location.pathname.match(/\/(followers|following)\/?$/); - }; - - handleMouseEnter = ({ currentTarget }) => { - if (autoPlayGif) { - return; - } - - const emojis = currentTarget.querySelectorAll('.custom-emoji'); - - for (var i = 0; i < emojis.length; i++) { - let emoji = emojis[i]; - emoji.src = emoji.getAttribute('data-original'); - } - }; - - handleMouseLeave = ({ currentTarget }) => { - if (autoPlayGif) { - return; - } - - const emojis = currentTarget.querySelectorAll('.custom-emoji'); - - for (var i = 0; i < emojis.length; i++) { - let emoji = emojis[i]; - emoji.src = emoji.getAttribute('data-static'); - } - }; - - handleAvatarClick = e => { - if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - this.props.onOpenAvatar(); - } - }; - - handleShare = () => { - const { account } = this.props; - - navigator.share({ - url: account.get('url'), - }).catch((e) => { - if (e.name !== 'AbortError') console.error(e); - }); - }; - - handleHashtagClick = e => { - const { history } = this.props; - const value = e.currentTarget.textContent.replace(/^#/, ''); - - if (history && e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - history.push(`/tags/${value}`); - } - }; - - handleMentionClick = e => { - const { history, onOpenURL } = this.props; - - if (history && e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - - const link = e.currentTarget; - - onOpenURL(link.href).then((result) => { - if (isFulfilled(result)) { - if (result.payload.accounts[0]) { - history.push(`/@${result.payload.accounts[0].acct}`); - } else if (result.payload.statuses[0]) { - history.push(`/@${result.payload.statuses[0].account.acct}/${result.payload.statuses[0].id}`); - } else { - window.location = link.href; - } - } else if (isRejected(result)) { - window.location = link.href; - } - }).catch(() => { - // Nothing - }); - } - }; - - _attachLinkEvents () { - const node = this.node; - - if (!node) { - return; - } - - const links = node.querySelectorAll('a'); - - let link; - - for (var i = 0; i < links.length; ++i) { - link = links[i]; - - if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) { - link.addEventListener('click', this.handleHashtagClick, false); - } else if (link.classList.contains('mention')) { - link.addEventListener('click', this.handleMentionClick, false); - } - } - } - - componentDidMount () { - this._attachLinkEvents(); - } - - componentDidUpdate () { - this._attachLinkEvents(); - } - - render () { - const { account, hidden, intl } = this.props; - const { signedIn, permissions } = this.props.identity; - - if (!account) { - return null; - } - - const suspended = account.get('suspended'); - const isRemote = account.get('acct') !== account.get('username'); - const remoteDomain = isRemote ? account.get('acct').split('@')[1] : null; - - let actionBtn, bellBtn, lockedIcon, shareBtn; - - let info = []; - let menu = []; - - if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) { - info.push(); - } - - if (me !== account.get('id') && account.getIn(['relationship', 'muting'])) { - info.push(); - } else if (me !== account.get('id') && account.getIn(['relationship', 'domain_blocking'])) { - info.push(); - } - - if (account.getIn(['relationship', 'requested']) || account.getIn(['relationship', 'following'])) { - bellBtn = ; - } - - if ('share' in navigator) { - shareBtn = ; - } else { - shareBtn = ; - } - - if (me !== account.get('id')) { - if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded - actionBtn = ; - } else if (!account.getIn(['relationship', 'blocking'])) { - actionBtn = + ); + } else if (!relationship?.blocking) { + actionBtn = ( +