From bda433b00634fd0c029c17d4544c05fc26b25a9e Mon Sep 17 00:00:00 2001 From: solidsanek Date: Sat, 29 Oct 2022 20:50:31 +0000 Subject: [PATCH 01/22] Add mfm autocomplete (#183) I thought it could be neat to have an autocomplete like Misskey has for MFM. A condition was removed that prevented autocomplete to actually autocomplete stuff when only the first character was entered. It doesn't affect the other autocompletes since none of them display their elements if nothing was actually searched. (in that case MFM returns the full list of elements) Co-authored-by: solidsanek Reviewed-on: https://akkoma.dev/AkkomaGang/pleroma-fe/pulls/183 Reviewed-by: floatingghost Co-authored-by: solidsanek Co-committed-by: solidsanek --- src/components/emoji_input/emoji_input.js | 3 +-- src/components/emoji_input/emoji_input.vue | 2 +- src/components/emoji_input/suggestor.js | 7 +++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 78e75880..846274b8 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -178,7 +178,7 @@ const EmojiInput = { textAtCaret: async function (newWord) { const firstchar = newWord.charAt(0) this.suggestions = [] - if (newWord === firstchar) return + if (newWord === firstchar && firstchar !== '$') return const matchedSuggestions = await this.suggest(newWord) // Async: cancel if textAtCaret has changed during wait if (this.textAtCaret !== newWord) return @@ -277,7 +277,6 @@ const EmojiInput = { }, replaceText (e, suggestion) { const len = this.suggestions.length || 0 - if (this.textAtCaret.length === 1) { return } if (len > 0 || suggestion) { const chosenSuggestion = suggestion || this.suggestions[this.highlighted] const replacement = chosenSuggestion.replacement diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 7d95ab7e..078253c2 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -42,7 +42,7 @@ :class="{ highlighted: index === highlighted }" @click.stop.prevent="onClick($event, suggestion)" > - + ({ displayText: tag, detailText: '$[' + tag + ' ]', replacement: '$[' + tag + ' ]', mfm: true })) + /** * suggest - generates a suggestor function to be used by emoji-input * data: object providing source information for specific types of suggestions: @@ -21,6 +24,10 @@ export default data => { if (firstChar === '@' && usersCurry) { return usersCurry(input) } + if (firstChar === '$') { + return MFM_TAGS + .filter(({ replacement }) => replacement.toLowerCase().indexOf(input) !== -1) + } return [] } } From 04c744e764887a4c738dc0c347cfd3645a20c466 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sat, 29 Oct 2022 21:56:58 +0100 Subject: [PATCH 02/22] Stop stopGifs option from instance --- src/boot/after_store.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 9f0ff4d3..41c7b73e 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -148,6 +148,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { copyInstanceOption('showWiderShortcuts') copyInstanceOption('showNavShortcuts') copyInstanceOption('showPanelNavShortcuts') + copyInstanceOption('stopGifs') copyInstanceOption('logo') store.dispatch('setInstanceOption', { From d8643b5b4ae4341b1afe45e96a2f1cc57168d8a2 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Sat, 29 Oct 2022 22:08:25 +0100 Subject: [PATCH 03/22] Take instance stopGifs value --- src/modules/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/config.js b/src/modules/config.js index 8adc76b4..038ec35a 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -55,7 +55,7 @@ export const defaultState = { alwaysShowNewPostButton: false, autohideFloatingPostButton: false, pauseOnUnfocused: true, - stopGifs: true, + stopGifs: undefined, replyVisibility: 'all', thirdColumnMode: 'notifications', notificationVisibility: { From 469063ff52792f75fa194a4b85147bfa151a668e Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Wed, 2 Nov 2022 22:08:58 +0000 Subject: [PATCH 04/22] Debounce word filters Fixes #182 --- src/components/settings_modal/tabs/filtering_tab.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js index 73413b48..d3bb40c3 100644 --- a/src/components/settings_modal/tabs/filtering_tab.js +++ b/src/components/settings_modal/tabs/filtering_tab.js @@ -1,4 +1,4 @@ -import { filter, trim } from 'lodash' +import { filter, trim, debounce } from 'lodash' import BooleanSetting from '../helpers/boolean_setting.vue' import ChoiceSetting from '../helpers/choice_setting.vue' import IntegerSetting from '../helpers/integer_setting.vue' @@ -27,13 +27,13 @@ const FilteringTab = { get () { return this.muteWordsStringLocal }, - set (value) { + set: debounce(function (value) { this.muteWordsStringLocal = value this.$store.dispatch('setOption', { name: 'muteWords', value: filter(value.split('\n'), (word) => trim(word).length > 0) }) - } + }, 500) } }, // Updating nested properties From 5c288650180e80e3e8a829bddd9486216fc1c0a5 Mon Sep 17 00:00:00 2001 From: Weblate Date: Wed, 2 Nov 2022 22:09:52 +0000 Subject: [PATCH 05/22] Translated using Weblate (Catalan) Currently translated at 100.0% (997 of 997 strings) Co-authored-by: Weblate Co-authored-by: sola Translate-URL: http://translate.akkoma.dev/projects/akkoma/pleroma-fe/ca/ Translation: Pleroma fe/pleroma-fe --- src/i18n/ca.json | 182 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 164 insertions(+), 18 deletions(-) diff --git a/src/i18n/ca.json b/src/i18n/ca.json index 405f6bef..e2cd094a 100644 --- a/src/i18n/ca.json +++ b/src/i18n/ca.json @@ -164,6 +164,74 @@ "load_older": "Carrega interaccions més antigues", "moves": "Migracions d'usuari" }, + "languages": { + "ar": "Àrab", + "az": "Azerbaidjanès", + "bg": "Búlgar", + "cs": "Txec", + "da": "Danès", + "de": "Alemany", + "el": "Grec", + "en": "Anglès", + "eo": "Esperanto", + "es": "Espanyol", + "fa": "Persa", + "fi": "Finès", + "fr": "Francès", + "ga": "Irlandès", + "he": "Hebreu", + "hi": "Indi", + "hu": "Hungarès", + "id": "Indonesi", + "it": "Italià", + "ja": "Japonès", + "ko": "Coreà", + "lt": "Lituà", + "lv": "Latvià", + "nl": "Holandès", + "pl": "Polonès", + "pt": "Portuguès", + "ru": "Rus", + "sk": "Eslovè", + "sv": "Suec", + "tr": "Turc", + "translated_from": { + "ar": "Traduït de @:languages.ar", + "az": "Traduït de @:languages.az", + "bg": "Traduït de @:languages.bg", + "cs": "Traduït de @:languages.cs", + "da": "Traduït de @:languages.da", + "de": "Traduït de @:languages.de", + "el": "Traduït de @:languages.el", + "en": "Traduït de @:languages.en", + "eo": "Traduït de @:languages.eo", + "es": "Traduït de @:languages.es", + "fa": "Traduït de @:languages.fa", + "fi": "Traduït de @:languages.en", + "fr": "Traduït de @:languages.fr", + "ga": "Traduït de @:languages.ga", + "he": "Traduït de @:languages.he", + "hi": "Traduït de @:languages.hi", + "hu": "Traduït de @:languages.hu", + "id": "Traduït de @:languages.id", + "it": "Traduït de @:languages.it", + "ja": "Traduït de @:languages.ja", + "ko": "Traduït de @:languages.ko", + "lt": "Traduït de @:languages.lt", + "lv": "Traduït de @:languages.lv", + "nl": "Traduït de @:languages.nl", + "pl": "Traduït de @:languages.pl", + "pt": "Traduït de @:languages.pt", + "ru": "Traduït de @:languages.ru", + "sk": "Traduït de @:languages.sk", + "sv": "Traduït de @:languages.sv", + "tr": "Traduït de @:languages.fr", + "uk": "Traduït de @:languages.uk", + "zh": "Traduït de @:languages.zh" + }, + "uk": "Ucraïnès", + "zh": "Xinès" + }, "lists": { "create": "Crea", "delete": "Esborra la llista", @@ -279,10 +347,13 @@ "text/plain": "Text pla", "text/x.misskeymarkdown": "MFM" }, - "content_warning": "Assumpte (opcional)", + "content_warning": "Avís de contingut (opcional)", "default": "Just ara he arribat a Catalunya", "direct_warning_to_all": "Aquest apunt serà visible per a tots els usuaris mencionats.", "direct_warning_to_first_only": "Aquest apunt només serà visible per als usuaris mencionats al principi del missatge.", + "edit_remote_warning": "Els canvis fets en aquest apunt poden no ser visibles en algunes instàncies!", + "edit_status": "Edita l'apunt", + "edit_unsupported_warning": "Les enquestes i les mencions no es canviaran al editar.", "empty_status_error": "No es pot enviar un apunt buit i sense fitxers adjunts", "media_description": "Descripció multimèdia", "media_description_error": "Ha fallat la pujada del Mèdia, prova de nou", @@ -313,7 +384,7 @@ "email": "Adreça de Correu", "email_language": "En quina llengua vols rebre els correus del servidor?", "fullname": "Nom a mostrar", - "fullname_placeholder": "p. ex. Lain Iwakura", + "fullname_placeholder": "p. ex. Atsuko Kagari", "new_captcha": "Clica a la imatge per a obtenir un nou captcha", "password_confirm": "Confirma la contrasenya", "reason": "Raó per a registrar-se", @@ -321,7 +392,7 @@ "register": "Registre", "registration": "Registre", "token": "Codi d'invitació", - "username_placeholder": "p. ex. lain", + "username_placeholder": "p. ex. akko", "validations": { "email_required": "no es pot deixar en blanc", "fullname_required": "no es pot deixar en blanc", @@ -392,9 +463,19 @@ "changed_password": "S'ha canviat la contrasenya correctament!", "chatMessageRadius": "Missatge de xat", "checkboxRadius": "Caselles", - "collapse_subject": "Replega els apunts amb assumpte", + "collapse_subject": "Replega els apunts amb avís de contingut", + "columns": "Columnes", "composing": "Composant", + "confirm_dialogs": "Requereix confirmació per:", + "confirm_dialogs_approve_follow": "Acceptant peticions de seguiment", + "confirm_dialogs_block": "Bloquejant algú", + "confirm_dialogs_delete": "Esborrant un apunt", + "confirm_dialogs_deny_follow": "Rebutjant una sol·licitud de seguiment", + "confirm_dialogs_mute": "Silenciant algú", + "confirm_dialogs_repeat": "Repetint un apunt", + "confirm_dialogs_unfollow": "Deixant de seguir a algú", "confirm_new_password": "Confirma la nova contrasenya", + "confirmation_dialogs": "Opcions de confirmació", "conversation_display": "Estil de visualització de la conversa", "conversation_display_linear": "Estil linear", "conversation_display_tree": "Estil d'arbre", @@ -426,8 +507,8 @@ "backup_settings_theme": "Còpia de seguretat de la configuració i tema a un fitxer", "errors": { "file_slightly_new": "La versió menor del fitxer és diferent, alguns paràmetres podrien no carregar-se", - "file_too_new": "Versió important incompatible: {fileMajor}, aquest PleromaFE (configuració versió {feMajor}) és massa antiga per gestionar-lo", - "file_too_old": "Versió important incompatible: {fileMajor}, la versió del fitxer és massa antiga i no està suportada (min. set. ver. {feMajor})", + "file_too_new": "Versió major incompatible: {fileMajor}, aquest PleromaFE (configuració versió {feMajor}) és massa antiga per gestionar-lo", + "file_too_old": "Versió major incompatible: {fileMajor}, la versió del fitxer és massa antiga i no està suportada (min. set. ver. {feMajor})", "invalid_file": "El fitxer seleccionat no és suportat per Akkoma com a còpia de seguretat de la configuració. No s'ha realitzat cap canvi." }, "restore_settings": "Restaurar configuració des d'un fitxer" @@ -520,7 +601,7 @@ "more_settings": "Més opcions", "move_account": "Mou el compte", "move_account_error": "Error al moure el compte: {error}", - "move_account_notes": "Si vols moure el compte a un altre lloc has d'anar a aquest altre compte i afegir un àlies que apunti a aquest.", + "move_account_notes": "Si vols moure aquest compte a un altre lloc, has d'anar a aquest altre compte i afegir un àlies que apunti a aquest.", "move_account_target": "Compte destí (p.ex. {example})", "moved_account": "El compte s'ha mogut.", "mute_bot_posts": "Silencia apunts de bots", @@ -604,7 +685,7 @@ "security": "Seguretat", "security_tab": "Seguretat", "sensitive_by_default": "Marca apunts com a sensibles per defecte", - "sensitive_if_subject": "Marca automàticament les imatges com a sensibles si s'ha especificat la línia assumpte", + "sensitive_if_subject": "Marca automàticament les imatges com a sensibles si s'ha especificat un avís de contingut", "set_new_avatar": "Establir un nou avatar", "set_new_mascot": "Establir una nova mascota", "set_new_profile_background": "Canvia el fons del perfil", @@ -612,6 +693,19 @@ "setting_changed": "La configuració és diferent a la predeterminada", "setting_server_side": "Aquest ajust està lligat al teu perfil i afectarà a totes les sessions i clients", "settings": "Configuració", + "settings_profile": "Perfils de configuracions", + "settings_profile_creation": "Crea nou perfil", + "settings_profile_creation_new_name_label": "Nom", + "settings_profile_creation_submit": "Crea", + "settings_profile_currently": "Actualment usant {name} (versió: {version})", + "settings_profile_delete": "Esborra", + "settings_profile_delete_confirm": "Vols de debò esborrar aquest perfil?", + "settings_profile_force_sync": "Sincronitza", + "settings_profile_in_use": "En ús", + "settings_profile_use": "Usa", + "settings_profiles_refresh": "Recarrega els perfils de configuracions", + "settings_profiles_show": "Mostra tots els perfils de configuracions", + "settings_profiles_unshow": "Amaga tots els perfils de configuracions", "show_admin_badge": "Mostra l'insígnia \"Administrador\" en el meu perfil", "show_moderator_badge": "Mostra l'insígnia \"Moderador\" en el meu perfil", "show_nav_shortcuts": "Mostra els accessos directes addicionals en el panell superior", @@ -767,9 +861,9 @@ "use_source": "Nova versió" } }, - "subject_input_always_show": "Sempre mostrar el camp del assumpte", - "subject_line_behavior": "Copiar l'assumpte en les respostes", - "subject_line_email": "Com a l'email: \"re: assumpte\"", + "subject_input_always_show": "Sempre mostra el camp d'avís de contingut", + "subject_line_behavior": "Copiar l'avís de contingut en les respostes", + "subject_line_email": "Com en el correu: \"re: avís\"", "subject_line_mastodon": "Com a mastodon: copiar com és", "subject_line_noop": "No copiar", "text": "Text", @@ -783,7 +877,8 @@ "third_column_mode_postform": "Formulari de publicació principal i navegació", "token": "Token", "tooltipRadius": "Globus/alertes", - "tree_advanced": "Permet una navegació més flexible en la vista d'arbre", + "translation_language": "Traducció Automàtica de la Llengua", + "tree_advanced": "Mostra els botons extra per a obrir i tancar les cadenes en els fils", "tree_fade_ancestors": "Mostra els avantpassats del apunt actual en text dèbil", "type_domains_to_mute": "Buscar dominis per a silenciar", "upload_a_photo": "Pujar una foto", @@ -793,6 +888,7 @@ "use_contain_fit": "No retallar els adjunts en miniatures", "use_one_click_nsfw": "Obre els adjunts NSFW amb només un clic", "user_mutes": "Usuaris", + "user_profile_default_tab": "Pestanya per defecte en el Perfil d'Usuari", "user_profiles": "Perfils d'usuari", "user_settings": "Configuració d'usuari", "valid_until": "Vàlid fins", @@ -809,6 +905,12 @@ "word_filter": "Filtre de paraules", "wordfilter": "Filtre de paraules" }, + "settings_profile": { + "creating": "Creant nou perfil de configuracions \"{profile}\"...", + "synchronization_error": "No s'han pogut sincronitzar les configuracions: {err}", + "synchronized": "Configuracions sincronitzades!", + "synchronizing": "Sincronitzant el perfil de configuració \"{profile}\"..." + }, "status": { "ancestor_follow": "Veure {numReplies} altres respostes sota aquest apunt | Veure {numReplies} altres respostes sota aquest apunt", "ancestor_follow_with_icon": "{icon} {text}", @@ -818,12 +920,19 @@ "copy_link": "Copia l'enllaç a l'apunt", "delete": "Esborra l'apunt", "delete_confirm": "Segur que vols esborrar aquest apunt?", + "delete_confirm_accept_button": "Sí, esborra'l", + "delete_confirm_cancel_button": "No, desa'l", + "delete_confirm_title": "Confirma esborrat", + "edit": "Edita", + "edit_history": "Historial d'edició", + "edit_history_modal_title": "Editat {historyCount} vegada | Editat {historyCount} vegades", + "edited_at": "Editat {time}", "expand": "Expandeix", "external_source": "Font externa", "favorites": "Favorits", "hide_attachment": "Amaga l'adjunt", "hide_content": "Amaga el contingut", - "hide_full_subject": "Amaga tot l'assumpte", + "hide_full_subject": "Amaga tot l'avís de contingut", "many_attachments": "L'apunt té {number} adjunt | L'apunt té {number} adjunts", "mentions": "Menciona", "move_down": "Mou l'adjunt a la dreta", @@ -831,32 +940,44 @@ "mute_conversation": "Silencia la conversa", "nsfw": "No segur per a entorns laborals", "open_gallery": "Obre la galeria", + "override_translation_source_language": "Anul·la la llengua d'origen", "pin": "Destaca al perfil", "pinned": "Destacat", "plus_more": "+{number} més", + "redraft": "Esborra i torna a escriure", + "redraft_confirm": "De debò vols esborrar i tornar a escriure aquest apunt? Les interaccions del apunt original no es mantindran.", + "redraft_confirm_accept_button": "Sí, esborra i redacta de nou", + "redraft_confirm_cancel_button": "No, manté l'original", + "redraft_confirm_title": "Confirma esborra i re escriu", "remove_attachment": "Elimina l'adjunt", + "repeat_confirm": "Vols de debò repetir aquest apunt?", + "repeat_confirm_accept_button": "Sí, repeteix-lo", + "repeat_confirm_cancel_button": "No, no el repeteixis", + "repeat_confirm_title": "Confirma repetició", "repeats": "Repeticions", "replies_list": "Respostes:", - "replies_list_with_others": "Respostes (+{numReplies} altre): | Respostes (+{numReplies} altres):", + "replies_list_with_others": "Veure (+{numReplies} resposta més): | Veure (+{numReplies} respostes més):", "reply_to": "Respon a", "show_all_attachments": "Mostra tots els adjunts", "show_all_conversation": "Mostra la conversa sencera ({numStatus} altre apunt) | Mostra la conversa sencera ({numStatus} altres apunts)", "show_all_conversation_with_icon": "{icon} {text}", "show_attachment_description": "Descripció prèvia (obre l'adjunt per a descripció sencera)", - "show_attachment_in_modal": "Mostra en el modal de Mèdia", + "show_attachment_in_modal": "Mostra l'adjunt en un finestra", "show_content": "Mostra el contingut", - "show_full_subject": "Mostra tot l'assumpte", + "show_full_subject": "Mostra tot l'avís de contingut", "show_only_conversation_under_this": "Només mostra respostes a aquest apunt", "status_deleted": "Aquest apunt ha estat esborrat", "status_unavailable": "Apunt no disponible", - "thread_follow": "Mira la part restant d'aquest fil ({numStatus} apunt en total) | Mira la part restant d'aquest fil ({numStatus} apunts en total)", + "thread_follow": "Veure {numStatus} resposta més | Veure {numStatus} respostes més", "thread_follow_with_icon": "{icon} {text}", "thread_hide": "Amaga aquest fil", "thread_muted": "Fil silenciat", "thread_muted_and_words": ", té les paraules:", "thread_show": "Mostra aquest fil", - "thread_show_full": "Mostra-ho tot sota aquest fil ({numStatus} apunt en total, màx. profunditat {depth}) | Mostra-ho tot sota aquest fil ({numStatus} apunts en total, màx. profunditat {depth})", + "thread_show_full": "Mostra {numStatus} resposta | Mostra totes {numStatus} respostes", "thread_show_full_with_icon": "{icon} {text}", + "translate": "Tradueix", + "translated_from": "Tradueix des de {language}", "unbookmark": "Desmarca", "unmute_conversation": "Deixa de silenciar la conversa", "unpin": "Deixa de destacar al perfil", @@ -899,6 +1020,9 @@ "socket_reconnected": "Connexió a temps real establerta", "up_to_date": "Actualitzat" }, + "toast": { + "no_translation_target_set": "No s'ha configurat una llengua objectiu -això podria fallar. Si us plau configura una llengua objectiu en la teva configuració." + }, "tool_tip": { "accept_follow_request": "Accepta la sol·licitud de seguiment", "add_reaction": "Reacciona", @@ -947,12 +1071,24 @@ "strip_media": "Esborra els Mèdia dels apunts" }, "approve": "Aprova", + "approve_confirm": "Estàs segur que vols deixar que et segueixi aquest usuari?", + "approve_confirm_accept_button": "Sí, accepta", + "approve_confirm_cancel_button": "No, cancel·la", + "approve_confirm_title": "Aprova la sol·licitud de seguiment", "block": "Bloqueja", + "block_confirm": "Estàs segur que vols bloquejar a {user}?", + "block_confirm_accept_button": "Sí, bloqueja'l", + "block_confirm_cancel_button": "No, no el bloquegis", + "block_confirm_title": "Bloqueja l'usuari", "block_progress": "Bloquejant…", "blocked": "Bloquejat!", "bot": "Bot", "deactivated": "Desactivat", "deny": "Denega", + "deny_confirm": "Estàs segur que vols denegar la sol·licitud de seguiment d'aquest usuari?", + "deny_confirm_accept_button": "Sí, denega", + "deny_confirm_cancel_button": "No, cancel·la", + "deny_confirm_title": "Denega sol·licitud de seguiment", "domain_muted": "Desbloqueja el domini", "edit_profile": "Edita el perfil", "favorites": "Favorits", @@ -978,18 +1114,28 @@ "mention": "Menció", "message": "Missatge", "mute": "Silencia", + "mute_confirm": "Estàs segur que vols silenciar a {user}?", + "mute_confirm_accept_button": "Sí, silencia'l", + "mute_confirm_cancel_button": "No, no el silenciïs", + "mute_confirm_title": "Silencia usuari", "mute_domain": "Bloqueja el domini", "mute_progress": "Silenciant…", "muted": "Silenciat", "note": "Nota privada", "per_day": "per dia", "remote_follow": "Seguiment remot", + "remove_follower": "Esborra seguidor", + "replies": "Amb respostes", "report": "Informa", "show_repeats": "Mostra les repeticions", "statuses": "Apunts", "subscribe": "Subscriu-te", "unblock": "Desbloqueja", "unblock_progress": "Desbloquejant…", + "unfollow_confirm": "Estàs segur que vols deixar de seguir a {user}?", + "unfollow_confirm_accept_button": "Sí, deixa'l de seguir", + "unfollow_confirm_cancel_button": "No, no el deixis de seguir", + "unfollow_confirm_title": "Deixa de seguir l'usuari", "unmute": "Deixa de silenciar", "unmute_progress": "Deixant de silenciar…", "unsubscribe": "Anul·la la subscripció" From 8bd18643e47502eacc44cef568a8702364721bf6 Mon Sep 17 00:00:00 2001 From: Weblate Date: Wed, 2 Nov 2022 22:09:52 +0000 Subject: [PATCH 06/22] Translated using Weblate (French) Currently translated at 100.0% (997 of 997 strings) Co-authored-by: Thomate Translate-URL: http://translate.akkoma.dev/projects/akkoma/pleroma-fe/fr/ Translation: Pleroma fe/pleroma-fe --- src/i18n/fr.json | 60 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 0bec8163..47570d6f 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -273,23 +273,23 @@ "back": "Retour", "bookmarks": "Marques-Pages", "bubble_timeline": "Flux de cette bulle", - "bubble_timeline_description": "Les status des instances proches de celle-ci, choisies par l'administration", + "bubble_timeline_description": "Les statuts des instances proches de celle-ci, choisies par l'administration", "chats": "Chats", "dms": "Messages directs", "friend_requests": "Demandes de suivi", "home_timeline": "Flux personnel", - "home_timeline_description": "Les status de vos abonnements", + "home_timeline_description": "Les statuts de vos abonnements", "interactions": "Interactions", "lists": "Listes", "mentions": "Mentions", "preferences": "Préférences", - "public_timeline_description": "Tous les status publics de cette instance", + "public_timeline_description": "Tous les statuts publics de cette instance", "public_tl": "Flux publique", "search": "Recherche", "timeline": "Flux personnel", "timelines": "Flux", "twkn": "Réseau connu", - "twkn_timeline_description": "Les status du réseau entier", + "twkn_timeline_description": "Les statuts du réseau entier", "user_search": "Recherche de comptes", "who_to_follow": "Suggestion de suivi" }, @@ -337,7 +337,7 @@ "votes_count": "{count} vote | {count} votes" }, "post_status": { - "account_not_locked_warning": "Votre compte n'est pas {0}. N'importe qui peut vous suivre pour voir vos billets en Abonné·e·s uniquement.", + "account_not_locked_warning": "Votre compte n'est pas {0}. N'importe qui peut vous suivre et voir vos statuts réservés aux abonné·es.", "account_not_locked_warning_link": "verrouillé", "attachments_sensitive": "Marquer les pièce-jointes comme sensible", "content_type": { @@ -693,6 +693,19 @@ "setting_changed": "Préférence modifiée", "setting_server_side": "Modifier cette préférence répercute sur tous vos clients", "settings": "Paramètres", + "settings_profile": "Profils de paramètres", + "settings_profile_creation": "Créer un profil", + "settings_profile_creation_new_name_label": "Nom", + "settings_profile_creation_submit": "Créer", + "settings_profile_currently": "Profil actuel : {name} (version {version})", + "settings_profile_delete": "Supprimer", + "settings_profile_delete_confirm": "Voulez-vous vraiment supprimer ce profil ?", + "settings_profile_force_sync": "Synchroniser", + "settings_profile_in_use": "Actuel", + "settings_profile_use": "Utiliser", + "settings_profiles_refresh": "Recharger", + "settings_profiles_show": "Afficher touts les profils", + "settings_profiles_unshow": "Cacher les profils", "show_admin_badge": "Afficher le badge d'Admin sur mon profil", "show_moderator_badge": "Afficher le badge de Modo' sur mon profil", "show_nav_shortcuts": "Afficher plus de raccourcis de navigations dans le panneau supérieur", @@ -892,6 +905,12 @@ "word_filter": "Filtrage par mots", "wordfilter": "Filtrage par mot-clé" }, + "settings_profile": { + "creating": "Création du profil « {profil} » …", + "synchronization_error": "Impossible de synchroniser les paramètres : {err}", + "synchronized": "Paramètres synchronisés !", + "synchronizing": "Synchronisation du profil « {profile} » …" + }, "status": { "ancestor_follow": "Voir {numReplies} autre réponse en dessous de ce status | Voir {numReplies} autres réponses en dessous de ce status", "ancestor_follow_with_icon": "{icon} {text}", @@ -925,6 +944,11 @@ "pin": "Agrafer sur le profil", "pinned": "Agraffé", "plus_more": "+{number} autre | +{number} autres", + "redraft": "Supprimer et réécrire", + "redraft_confirm": "Supprimer et réécrire ce status ? Les interactions avec l'original seront perdues.", + "redraft_confirm_accept_button": "Oui : supprimer et réécrire", + "redraft_confirm_cancel_button": "Non : garder l'original", + "redraft_confirm_title": "Confirmer la suppression et réécriture", "remove_attachment": "Supprimer la pièce jointe", "repeat_confirm": "Partager ce statut ?", "repeat_confirm_accept_button": "Partager", @@ -1047,12 +1071,24 @@ "strip_media": "Supprimer les medias des statuts" }, "approve": "Accepter", + "approve_confirm": "Voulez-vous vraiment approuver cet abonnement ?", + "approve_confirm_accept_button": "Oui : accepter", + "approve_confirm_cancel_button": "Non : rejeter", + "approve_confirm_title": "Approuver une demande d'abonnement", "block": "Bloquer", + "block_confirm": "Êtes-vous sûr de vouloir bloquer {user} ?", + "block_confirm_accept_button": "Oui", + "block_confirm_cancel_button": "Non", + "block_confirm_title": "Bloquer l'utilisateur", "block_progress": "Blocage…", "blocked": "Bloqué !", "bot": "Robot", "deactivated": "Désactivé", "deny": "Rejeter", + "deny_confirm": "Êtes-vous sûr de vouloir rejeter cette demande d'abonnement ?", + "deny_confirm_accept_button": "Oui : rejeter", + "deny_confirm_cancel_button": "Non : annuler", + "deny_confirm_title": "Rejeter une demande d'abonnement", "domain_muted": "Débloquer la domaine", "edit_profile": "Éditer le profil", "favorites": "Favoris", @@ -1061,8 +1097,8 @@ "follow_progress": "Demande en cours…", "follow_sent": "Demande envoyée !", "follow_unfollow": "Désabonner", - "followees": "Suivis", - "followers": "Vous suivent", + "followees": "Abonnements", + "followers": "Abonné·es", "following": "Suivi !", "follows_you": "Vous suit !", "hidden": "Caché", @@ -1078,18 +1114,28 @@ "mention": "Mention", "message": "Message", "mute": "Masquer", + "mute_confirm": "Êtes-vous sûr de vouloir masquer {user} ?", + "mute_confirm_accept_button": "Oui", + "mute_confirm_cancel_button": "Non", + "mute_confirm_title": "Masquer", "mute_domain": "Bloquer la domaine", "mute_progress": "Masquage…", "muted": "Masqué", "note": "Note privée", "per_day": "par jour", "remote_follow": "Suivre d'une autre instance", + "remove_follower": "Désabonner", + "replies": "Statuts et réponses", "report": "Signalement", "show_repeats": "Montrer les partages", "statuses": "Statuts", "subscribe": "Abonner", "unblock": "Débloquer", "unblock_progress": "Déblocage…", + "unfollow_confirm": "Êtes-vous sûr de vouloir vous désabonner de {user} ?", + "unfollow_confirm_accept_button": "Oui : me désabonner", + "unfollow_confirm_cancel_button": "Non : garder l'abonnement", + "unfollow_confirm_title": "Désabonner", "unmute": "Démasquer", "unmute_progress": "Démasquage…", "unsubscribe": "Désabonner" From ffac376b5aba6eb5b4da3a4cd7d936d844d02e0c Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Wed, 2 Nov 2022 22:33:54 +0000 Subject: [PATCH 07/22] Ensure MFM scaling is ignored when rendering is disabled Fixes #173 --- src/components/rich_content/rich_content.jsx | 10 +++++----- src/components/status_body/status_body.vue | 2 +- src/components/status_content/status_content.vue | 7 +++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx index 0d4127b6..072e0960 100644 --- a/src/components/rich_content/rich_content.jsx +++ b/src/components/rich_content/rich_content.jsx @@ -130,11 +130,11 @@ export default { codeblocks.forEach((pre) => { content = content.replace(pre, pre.replaceAll('
', '\n') - .replaceAll('&', '&') - .replaceAll('<', '<') - .replaceAll('>', '>') - .replaceAll('"', '"') - .replaceAll(''', "'") + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll(''', "'") ) }) } diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue index 509aa856..dc281f65 100644 --- a/src/components/status_body/status_body.vue +++ b/src/components/status_body/status_body.vue @@ -1,7 +1,7 @@ diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 41c7b73e..986cd356 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -397,6 +397,7 @@ const afterStoreSetup = async ({ store, i18n }) => { // Start fetching things that don't need to block the UI store.dispatch('fetchMutes') store.dispatch('startFetchingAnnouncements') + store.dispatch('startFetchingReports') getTOS({ store }) getStickers({ store }) diff --git a/src/components/desktop_nav/desktop_nav.js b/src/components/desktop_nav/desktop_nav.js index 9ba5abc4..78e93f0e 100644 --- a/src/components/desktop_nav/desktop_nav.js +++ b/src/components/desktop_nav/desktop_nav.js @@ -16,7 +16,8 @@ import { faUsers, faCommentMedical, faBookmark, - faInfoCircle + faInfoCircle, + faUserTie } from '@fortawesome/free-solid-svg-icons' library.add( @@ -34,7 +35,8 @@ library.add( faUsers, faCommentMedical, faBookmark, - faInfoCircle + faInfoCircle, + faUserTie ) export default { @@ -109,6 +111,9 @@ export default { }, openSettingsModal () { this.$store.dispatch('openSettingsModal') + }, + openModModal () { + this.$store.dispatch('openModModal') } } } diff --git a/src/components/desktop_nav/desktop_nav.vue b/src/components/desktop_nav/desktop_nav.vue index 9dc02e68..0c592326 100644 --- a/src/components/desktop_nav/desktop_nav.vue +++ b/src/components/desktop_nav/desktop_nav.vue @@ -151,6 +151,18 @@ :title="$t('nav.preferences')" /> + import('./mod_modal_content.vue'), + { + loadingComponent: PanelLoading, + errorComponent: AsyncComponentError, + delay: 0 + } + ) + }, + methods: { + closeModal () { + this.$store.dispatch('closeModModal') + }, + peekModal () { + this.$store.dispatch('togglePeekModModal') + } + }, + computed: { + moderator () { + return this.$store.state.users.currentUser && + (this.$store.state.users.currentUser.role === 'admin' || + this.$store.state.users.currentUser.role === 'moderator') + }, + modalActivated () { + return this.$store.state.interface.modModalState !== 'hidden' + }, + modalOpenedOnce () { + return this.$store.state.interface.modModalLoaded + }, + modalPeeked () { + return this.$store.state.interface.modModalState === 'minimized' + } + } +} + +export default ModModal diff --git a/src/components/mod_modal/mod_modal.scss b/src/components/mod_modal/mod_modal.scss new file mode 100644 index 00000000..4821df74 --- /dev/null +++ b/src/components/mod_modal/mod_modal.scss @@ -0,0 +1,44 @@ +@import 'src/_variables.scss'; +.mod-modal { + overflow: hidden; + + &.peek { + .mod-modal-panel { + /* Explanation: + * Modal is positioned vertically centered. + * 100vh - 100% = Distance between modal's top+bottom boundaries and screen + * (100vh - 100%) / 2 = Distance between bottom (or top) boundary and screen + * + 100% - we move modal completely off-screen, it's top boundary touches + * bottom of the screen + * - 50px - leaving tiny amount of space so that titlebar + tiny amount of modal is visible + */ + transform: translateY(calc(((100vh - 100%) / 2 + 100%) - 50px)); + + @media all and (max-width: 800px) { + /* For mobile, the modal takes 100% of the available screen. + This ensures the minimized modal is always 50px above the browser bottom bar regardless of whether or not it is visible. + */ + transform: translateY(calc(100% - 50px)); + } + } + } + + .mod-modal-panel { + overflow: hidden; + transition: transform; + transition-timing-function: ease-in-out; + transition-duration: 300ms; + width: 1000px; + max-width: 90vw; + height: 90vh; + + @media all and (max-width: 800px) { + max-width: 100vw; + height: 100%; + } + + .panel-body { + height: inherit; + } + } +} diff --git a/src/components/mod_modal/mod_modal.vue b/src/components/mod_modal/mod_modal.vue new file mode 100644 index 00000000..64bbf021 --- /dev/null +++ b/src/components/mod_modal/mod_modal.vue @@ -0,0 +1,43 @@ + + + + diff --git a/src/components/mod_modal/mod_modal_content.js b/src/components/mod_modal/mod_modal_content.js new file mode 100644 index 00000000..e0ba6259 --- /dev/null +++ b/src/components/mod_modal/mod_modal_content.js @@ -0,0 +1,63 @@ +import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx' + +import ReportsTab from './tabs/reports_tab/reports_tab.vue' +// import StatusesTab from './tabs/statuses_tab.vue' +// import UsersTab from './tabs/users_tab.vue' + +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faFlag, + faMessage, + faUsers +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faFlag, + faMessage, + faUsers +) + +const ModModalContent = { + components: { + TabSwitcher, + + ReportsTab + // StatusesTab, + // UsersTab + }, + computed: { + open () { + return this.$store.state.interface.modModalState !== 'hidden' + }, + bodyLock () { + return this.$store.state.interface.modModalState === 'visible' + } + }, + methods: { + onOpen () { + const targetTab = this.$store.state.interface.modModalTargetTab + // We're being told to open in specific tab + if (targetTab) { + const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => { + return elm.props && elm.props['data-tab-name'] === targetTab + }) + if (tabIndex >= 0) { + this.$refs.tabSwitcher.setTab(tabIndex) + } + } + // Clear the state of target tab, so that next time moderation is opened + // it doesn't force it. + this.$store.dispatch('clearModModalTargetTab') + } + }, + mounted () { + this.onOpen() + }, + watch: { + open: function (value) { + if (value) this.onOpen() + } + } +} + +export default ModModalContent diff --git a/src/components/mod_modal/mod_modal_content.scss b/src/components/mod_modal/mod_modal_content.scss new file mode 100644 index 00000000..b1aeba38 --- /dev/null +++ b/src/components/mod_modal/mod_modal_content.scss @@ -0,0 +1,21 @@ +@import 'src/_variables.scss'; +.mod_tab-switcher { + height: 100%; + + .content { + margin: 1em 1em 1.4em; + + > div { + margin-bottom: .5em; + &:last-child { + margin-bottom: 0; + } + } + + textarea { + width: 100%; + max-width: 100%; + height: 100px; + } + } +} diff --git a/src/components/mod_modal/mod_modal_content.vue b/src/components/mod_modal/mod_modal_content.vue new file mode 100644 index 00000000..6fa32be1 --- /dev/null +++ b/src/components/mod_modal/mod_modal_content.vue @@ -0,0 +1,20 @@ + + + + diff --git a/src/components/mod_modal/tabs/reports_tab/report_card.js b/src/components/mod_modal/tabs/reports_tab/report_card.js new file mode 100644 index 00000000..6e6bfdae --- /dev/null +++ b/src/components/mod_modal/tabs/reports_tab/report_card.js @@ -0,0 +1,124 @@ +import Popover from 'src/components/popover/popover.vue' +import Status from 'src/components/status/status.vue' +import UserAvatar from 'src/components/user_avatar/user_avatar.vue' +import ReportNote from './report_note.vue' + +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faChevronDown, + faChevronUp +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faChevronDown, + faChevronUp +) + +const FORCE_NSFW = 'mrf_tag:media-force-nsfw' +const STRIP_MEDIA = 'mrf_tag:media-strip' +const FORCE_UNLISTED = 'mrf_tag:force-unlisted' +const SANDBOX = 'mrf_tag:sandbox' + +const ReportCard = { + data () { + return { + hidden: true, + statusesHidden: true, + notesHidden: true, + note: null, + tags: { + FORCE_NSFW, + STRIP_MEDIA, + FORCE_UNLISTED, + SANDBOX + } + } + }, + props: [ + 'account', + 'actor', + 'content', + 'id', + 'notes', + 'state', + 'statuses' + ], + components: { + ReportNote, + Popover, + Status, + UserAvatar + }, + created () { + this.$store.dispatch('fetchUser', this.account.id) + }, + computed: { + isOpen () { + return this.state === 'open' + }, + tagPolicyEnabled () { + return this.$store.state.instance.federationPolicy.mrf_policies.includes('TagPolicy') + }, + user () { + return this.$store.getters.findUser(this.account.id) + } + }, + methods: { + toggleHidden () { + this.hidden = !this.hidden + }, + decode (content) { + content = content.replaceAll('
', '\n') + const textarea = document.createElement('textarea') + textarea.innerHTML = content + return textarea.value + }, + updateReportState (state) { + this.$store.dispatch('updateReportStates', { reports: [{ id: this.id, state }] }) + }, + toggleNotes () { + this.notesHidden = !this.notesHidden + }, + addNoteToReport () { + if (this.note.length > 0) { + this.$store.dispatch('addNoteToReport', { id: this.id, note: this.note }) + this.note = null + } + }, + toggleStatuses () { + this.statusesHidden = !this.statusesHidden + }, + hasTag (tag) { + return this.user.tags.includes(tag) + }, + toggleTag (tag) { + if (this.hasTag(tag)) { + this.$store.state.api.backendInteractor.untagUser({ user: this.user, tag }).then(response => { + if (!response.ok) { return } + this.$store.commit('untagUser', { user: this.user, tag }) + }) + } else { + this.$store.state.api.backendInteractor.tagUser({ user: this.user, tag }).then(response => { + if (!response.ok) { return } + this.$store.commit('tagUser', { user: this.user, tag }) + }) + } + }, + toggleActivationStatus () { + this.$store.dispatch('toggleActivationStatus', { user: this.user }) + }, + deleteUser () { + this.$store.state.backendInteractor.deleteUser({ user: this.user }) + .then(e => { + this.$store.dispatch('markStatusesAsDeleted', status => this.user.id === status.user.id) + const isProfile = this.$route.name === 'external-user-profile' || this.$route.name === 'user-profile' + const isTargetUser = this.$route.params.name === this.user.name || this.$route.params.id === this.user.id + if (isProfile && isTargetUser) { + window.history.back() + } + }) + } + } +} + +export default ReportCard diff --git a/src/components/mod_modal/tabs/reports_tab/report_card.vue b/src/components/mod_modal/tabs/reports_tab/report_card.vue new file mode 100644 index 00000000..6cc034b1 --- /dev/null +++ b/src/components/mod_modal/tabs/reports_tab/report_card.vue @@ -0,0 +1,202 @@ +