From dad8a1baf2b042cd05ddb3abbe64093ef07921ab Mon Sep 17 00:00:00 2001 From: ThibG Date: Thu, 2 Aug 2018 15:08:29 +0200 Subject: [PATCH 01/16] Render custom emoji in display name on public profile (#8115) --- app/views/accounts/_header.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index e343be82088..d3b9893c419 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -7,7 +7,7 @@ .public-account-header__tabs .public-account-header__tabs__name %h1 - = display_name(account) + = display_name(account, custom_emojify: true) %small = acct(account) = fa_icon('lock') if account.locked? From 23b22d0dffdefc519eb85e386e9be74f9066199a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?= Date: Fri, 3 Aug 2018 00:09:24 +0200 Subject: [PATCH 02/16] i18n: Make Polish translation more gender neutral + update (#8119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin Mikołajczak --- app/javascript/mastodon/locales/pl.json | 22 ++--- config/locales/devise.pl.yml | 22 ++--- config/locales/doorkeeper.pl.yml | 2 +- config/locales/pl.yml | 108 +++++++++++++----------- 4 files changed, 83 insertions(+), 71 deletions(-) diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 728a2c88cef..aedc8539a42 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -2,7 +2,7 @@ "account.badges.bot": "Bot", "account.block": "Blokuj @{name}", "account.block_domain": "Blokuj wszystko z {domain}", - "account.blocked": "Zablokowany", + "account.blocked": "Zablokowany(-a)", "account.direct": "Wyślij wiadomość bezpośrednią do @{name}", "account.disclaimer_full": "Poniższe informacje mogą nie odwzorowywać bezbłędnie profilu użytkownika.", "account.domain_blocked": "Ukryto domenę", @@ -14,7 +14,7 @@ "account.hide_reblogs": "Ukryj podbicia od @{name}", "account.media": "Zawartość multimedialna", "account.mention": "Wspomnij o @{name}", - "account.moved_to": "{name} przeniósł się do:", + "account.moved_to": "{name} przeniósł(-osła) się do:", "account.mute": "Wycisz @{name}", "account.mute_notifications": "Wycisz powiadomienia o @{name}", "account.muted": "Wyciszony", @@ -106,7 +106,7 @@ "emoji_button.travel": "Podróże i miejsca", "empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!", "empty_column.direct": "Nie masz żadnych wiadomości bezpośrednich. Kiedy dostaniesz lub wyślesz jakąś, pojawi się ona tutaj.", - "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy!", + "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy(-a)!", "empty_column.home": "Nie śledzisz nikogo. Odwiedź globalną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.", "empty_column.home.public_timeline": "globalna oś czasu", "empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.", @@ -135,7 +135,7 @@ "keyboard_shortcuts.favourite": "aby dodać do ulubionych", "keyboard_shortcuts.heading": "Skróty klawiszowe", "keyboard_shortcuts.hotkey": "Klawisz", - "keyboard_shortcuts.legend": "aby wyświetlić tą legendę", + "keyboard_shortcuts.legend": "aby wyświetlić tę legendę", "keyboard_shortcuts.mention": "aby wspomnieć o autorze", "keyboard_shortcuts.profile": "aby przejść do profilu autora wpisu", "keyboard_shortcuts.reply": "aby odpowiedzieć", @@ -179,10 +179,10 @@ "navigation_bar.preferences": "Preferencje", "navigation_bar.public_timeline": "Globalna oś czasu", "navigation_bar.security": "Bezpieczeństwo", - "notification.favourite": "{name} dodał Twój wpis do ulubionych", - "notification.follow": "{name} zaczął Cię śledzić", - "notification.mention": "{name} wspomniał o tobie", - "notification.reblog": "{name} podbił Twój wpis", + "notification.favourite": "{name} dodał(a) Twój wpis do ulubionych", + "notification.follow": "{name} zaczął(-ęła) Cię śledzić", + "notification.mention": "{name} wspomniał(a) o tobie", + "notification.reblog": "{name} podbił(a) Twój wpis", "notifications.clear": "Wyczyść powiadomienia", "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", "notifications.column_settings.alert": "Powiadomienia na pulpicie", @@ -241,7 +241,7 @@ "report.target": "Zgłaszanie {target}", "search.placeholder": "Szukaj", "search_popout.search_format": "Zaawansowane wyszukiwanie", - "search_popout.tips.full_text": "Pozwala na wyszukiwanie wpisów które napisałeś, dodałeś do ulubionych, podbiłeś w których o Tobie wspomniano, oraz pasujące nazwy użytkowników, pełne nazwy i hashtagi.", + "search_popout.tips.full_text": "Pozwala na wyszukiwanie wpisów które napisałeś(-aś), dodałeś(-aś) do ulubionych lub podbiłeś(-aś), w których o Tobie wspomniano, oraz pasujące nazwy użytkowników, pełne nazwy i hashtagi.", "search_popout.tips.hashtag": "hashtag", "search_popout.tips.status": "wpis", "search_popout.tips.text": "Proste wyszukiwanie pasujących pseudonimów, nazw użytkowników i hashtagów", @@ -258,7 +258,7 @@ "status.direct": "Wyślij wiadomość bezpośrednią do @{name}", "status.embed": "Osadź", "status.favourite": "Dodaj do ulubionych", - "status.filtered": "Filtrowany", + "status.filtered": "Filtrowany(-a)", "status.load_more": "Załaduj więcej", "status.media_hidden": "Zawartość multimedialna ukryta", "status.mention": "Wspomnij o @{name}", @@ -270,7 +270,7 @@ "status.pinned": "Przypięty wpis", "status.reblog": "Podbij", "status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu", - "status.reblogged_by": "{name} podbił", + "status.reblogged_by": "{name} podbił(a)", "status.redraft": "Usuń i przeredaguj", "status.reply": "Odpowiedz", "status.replyAll": "Odpowiedz na wątek", diff --git a/config/locales/devise.pl.yml b/config/locales/devise.pl.yml index 53a4f4552ed..49fcca0243b 100644 --- a/config/locales/devise.pl.yml +++ b/config/locales/devise.pl.yml @@ -6,7 +6,7 @@ pl: send_instructions: W ciągu kilku minut otrzymasz wiadomosć e-mail z instrukcją jak potwierdzić Twój adres e-mail. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. send_paranoid_instructions: Jeśli Twój adres e-mail już istnieje w naszej bazie danych, w ciągu kilku minut otrzymasz wiadomość e-mail z instrukcją jak potwierdzić Twój adres e-mail. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. failure: - already_authenticated: Jesteś już zalogowany/zalogowana. + already_authenticated: Jesteś już zalogowany(-a). inactive: Twoje konto nie zostało jeszcze aktywowane. invalid: Nieprawidłowy %{authentication_keys} lub hasło. last_attempt: Masz jeszcze jedną próbę; Twoje konto zostanie zablokowane jeśli się nie powiedzie. @@ -18,28 +18,28 @@ pl: mailer: confirmation_instructions: action: Zweryfikuj adres e-mail - explanation: Utworzyłeś konto na %{host} podając ten adres e-mail. Jedno kliknięcie dzieli Cię od aktywacji tego konta. Jeżeli to nie Ty, zignoruj ten e-mail. + explanation: Utworzyłeś(-aś) konto na %{host} podając ten adres e-mail. Jedno kliknięcie dzieli Cię od aktywacji tego konta. Jeżeli to nie Ty, zignoruj ten e-mail. extra_html: Przeczytaj też regulamin instancji i nasze zasady użytkowania. subject: 'Mastodon: Instrukcje weryfikacji adresu e-mail' title: Zweryfikuj adres e-mail email_changed: explanation: 'Adres e-mail dla Twojego konta zostanie zmieniony na:' - extra: Jeżeli nie próbowałeś zmienić adresu e-mail, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień natychmiastowo hasło lub skontaktuj się z administratorem isntancji, jeżeli nie masz dostępu do konta. + extra: Jeżeli nie próbowałeś(-aś) zmienić adresu e-mail, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień natychmiastowo hasło lub skontaktuj się z administratorem isntancji, jeżeli nie masz dostępu do konta. subject: 'Mastodon: Zmieniono adres e-mail' title: Nowy adres e-mail password_change: explanation: Hasło do Twojego konta zostało zmienione. - extra: Jeżeli nie zmieniałeś hasła, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień hasło natychmiastowo lub skontaktuj się z administratorem instancji, jeżeli nie masz dostępu do konta. + extra: Jeżeli nie zmieniałeś(-aś) hasła, prawdopodobnie ktoś uzyskał dostęp do Twojego konta. Zmień hasło natychmiastowo lub skontaktuj się z administratorem instancji, jeżeli nie masz dostępu do konta. subject: 'Mastodon: Zmieniono hasło' title: Zmieniono hasło reconfirmation_instructions: explanation: Potwierdź nowy adres aby zmienić e-mail. - extra: Jeżeli nie próbowałeś zmienić e-maila, zignoruj tą wiadomość. Adres e-mail przypisany do konta Mastodona nie ulegnie zmianie, jeżeli nie użyjesz powyższego odnośniku. + extra: Jeżeli nie próbowałeś(-aś) zmienić e-maila, zignoruj tą wiadomość. Adres e-mail przypisany do konta Mastodona nie ulegnie zmianie, jeżeli nie użyjesz powyższego odnośniku. subject: 'Mastodon: Potwierdź adres e-mail na &{instance}' title: Zweryfikuj adres e-mail reset_password_instructions: action: Zmień hasło - explanation: Próbowałeś uzyskać nowe hasło do swojego konta. + explanation: Próbowałeś(-aś) uzyskać nowe hasło do swojego konta. extra: Jeżeli to nie Ty, zignoruj tą wiadomość. Twoje hasło nie ulegnie zmianie, jeżeli nie wykorzystasz powyższego odnośnika i nie utworzysz nowego hasła. subject: 'Mastodon: Instrukcje ustawienia nowego hasła' title: Przywracanie hasła @@ -49,10 +49,10 @@ pl: failure: 'Uwierzytelnienie przez %{kind} nie powiodło się, ponieważ: "%{reason}".' success: Uwierzytelnienie przez %{kind} powiodło się. passwords: - no_token: Dostęp do tej strony możliwy jest wyłącznie za pomocą odnośnika z e-maila z instrukcjami ustawienia nowego hasła. Jeśli skorzystałeś/aś z takiego odnośnika, upewnij się, że został wykorzystany/skopiowany cały odnośnik. + no_token: Dostęp do tej strony możliwy jest wyłącznie za pomocą odnośnika z e-maila z instrukcjami ustawienia nowego hasła. Jeśli skorzystałeś(-aś) z takiego odnośnika, upewnij się, że został wykorzystany/skopiowany cały odnośnik. send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcją ustawienia nowego hasła. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. send_paranoid_instructions: Jeśli Twój adres e-mail już istnieje w naszej bazie danych, w ciągu kilku minut otrzymasz wiadomość e-mail zawierającą odnośnik pozwalający na ustawienie nowego hasła. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. - updated: Twoje hasło zostało zmienione. Jesteś zalogowany/a. + updated: Twoje hasło zostało zmienione. Jesteś zalogowany(-a). updated_not_active: Twoje hasło zostało zmienione. registrations: destroyed: Twoje konto zostało zawieszone. Mamy jednak nadzieję, że do nas wrócisz. Do zobaczenia! @@ -63,9 +63,9 @@ pl: update_needs_confirmation: Konto zostało zaktualizowane, musimy jednak zweryfikować Twój nowy adres e-mail. Została na niego wysłana wiadomość z odnośnikiem potwierdzającym. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. updated: Konto zostało zaktualizowane. sessions: - already_signed_out: Zostałeś/aś wylogowany/a. - signed_in: Zostałeś/aś zalogowany/a. - signed_out: Zostałeś/aś wylogowany/a. + already_signed_out: Zostałeś(-aś) wylogowany(-a). + signed_in: Zostałeś(-aś) zalogowany(-a). + signed_out: Zostałeś(-aś) wylogowany(-a). unlocks: send_instructions: W ciągu kilku minut otrzymasz wiadomość e-mail z instrukcjami odblokowania konta. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. send_paranoid_instructions: Jeśli Twoje konto istnieje, instrukcje odblokowania go otrzymasz w wiadomości e-mail w ciągu kilku minut. Jeżeli nie otrzymano wiadomości, sprawdź folder ze spamem. diff --git a/config/locales/doorkeeper.pl.yml b/config/locales/doorkeeper.pl.yml index 2e0254864c4..de724f6c97b 100644 --- a/config/locales/doorkeeper.pl.yml +++ b/config/locales/doorkeeper.pl.yml @@ -90,7 +90,7 @@ pl: revoked: Token dostępowy został unieważniony unknown: Token dostępowy jest błędny resource_owner_authenticator_not_configured: Wyszukiwanie właściciela zasobu nie powiodło się, ponieważ Doorkeeper.configure.resource_owner_authenticator nie został skonfigurowany. - server_error: Serwer uwierzytelniający napotkał nieoczekiwand warunki, które uniemożliwiły obsłużenie żądania. + server_error: Serwer uwierzytelniający napotkał nieoczekiwane warunki, które uniemożliwiły obsłużenie żądania. temporarily_unavailable: Serwer uwierzytelniający nie jest obecnie w stanie obsłużyć żądania z powodu tymczasowego przeciążenia lub prac konserwacyjnych. unauthorized_client: Klient nie jest uprawniony do wykonania tego żądania przy pomocy tej metody. unsupported_grant_type: Ten typ grantu uwierzytelniającego nie jest wspierany przez serwer uwierzytelniający. diff --git a/config/locales/pl.yml b/config/locales/pl.yml index c33078496fc..4407fd5480c 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -5,11 +5,13 @@ pl: about_mastodon_html: Mastodon jest wolną i otwartą siecią społecznościową, zdecentralizowaną alternatywą dla zamkniętych, komercyjnych platform. about_this: O tej instancji administered_by: 'Administrowana przez:' + api: API closed_registrations: Rejestracja na tej instancji jest obecnie zamknięta. Możesz jednak zarejestrować się na innej instancji, uzyskując dostęp do tej samej sieci. contact: Kontakt contact_missing: Nie ustawiono contact_unavailable: Nie dotyczy description_headline: Czym jest %{domain}? + documentation: Dokumentacja domain_count_after: instancjami domain_count_before: Serwer połączony z extended_description_html: | @@ -28,9 +30,11 @@ pl: hosted_on: Mastodon uruchomiony na %{domain} learn_more: Dowiedz się więcej other_instances: Lista instancji + privacy_policy: Polityka prywatności source_code: Kod źródłowy status_count_after: wpisów status_count_before: Są autorami + terms: Zasady użytkowania user_count_after: użytkowników user_count_before: Z serwera korzysta what_is_mastodon: Czym jest Mastodon? @@ -38,6 +42,7 @@ pl: follow: Śledź followers: Śledzący following: Śledzeni + joined: Dołączył(a) %{date} media: Zawartość multimedialna moved_html: "%{name} korzysta teraz z konta %{new_profile_link}:" network_hidden: Ta informacja nie jest dostępna @@ -151,34 +156,34 @@ pl: web: Sieć action_logs: actions: - assigned_to_self_report: "%{name} przypisał sobie zgłoszenie %{target}" - change_email_user: "%{name} zmienił adres-email użytkownika %{target}" - confirm_user: "%{name} potwierdził adres e-mail użytkownika %{target}" - create_custom_emoji: "%{name} dodał nowe emoji %{target}" - create_domain_block: "%{name} zablokował domenę %{target}" - create_email_domain_block: "%{name} dodał domenę e-mail %{target} na czarną listę" - demote_user: "%{name} zdegradował użytkownika %{target}" - destroy_domain_block: "%{name} odblokował domenę %{target}" - destroy_email_domain_block: "%{name} usunął domenę e-mail %{target} z czarnej listy" - destroy_status: "%{name} usunął wpis użytkownika %{target}" - disable_2fa_user: "%{name} wyłączył uwierzytelnianie dwustopniowe użytkownikowi %{target}" - disable_custom_emoji: "%{name} wyłączył emoji %{target}" - disable_user: "%{name} zablokował możliwość logowania użytkownikowi %{target}" - enable_custom_emoji: "%{name} włączył emoji %{target}" - enable_user: "%{name} przywrócił możliwość logowania użytkownikowi %{target}" - memorialize_account: "%{name} nadał kontu %{target} status in memoriam" - promote_user: "%{name} podniósł uprawnienia użytkownikowi %{target}" - remove_avatar_user: "%{name} usunął awatar użytkownikowi %{target}" - reopen_report: "%{name} otworzył ponownie zgłoszenie %{target}" - reset_password_user: "%{name} przywrócił hasło użytkownikowi %{target}" - resolve_report: "%{name} rozwiązał zgłoszenie %{target}" - silence_account: "%{name} wyciszył konto %{target}" - suspend_account: "%{name} zawiesił konto %{target}" - unassigned_report: "%{name} cofnął przypisanie zgłoszenia %{target}" - unsilence_account: "%{name} cofnął wyciszenie konta %{target}" - unsuspend_account: "%{name} cofnął zawieszenie konta %{target}" - update_custom_emoji: "%{name} zaktualizował emoji %{target}" - update_status: "%{name} zaktualizował wpis użytkownika %{target}" + assigned_to_self_report: "%{name} przypisał(a) sobie zgłoszenie %{target}" + change_email_user: "%{name} zmienił(a) adres e-mail użytkownika %{target}" + confirm_user: "%{name} potwierdził(a) adres e-mail użytkownika %{target}" + create_custom_emoji: "%{name} dodał(a) nowe emoji %{target}" + create_domain_block: "%{name} zablokował(a) domenę %{target}" + create_email_domain_block: "%{name} dodał(a) domenę e-mail %{target} na czarną listę" + demote_user: "%{name} zdegradował(a) użytkownika %{target}" + destroy_domain_block: "%{name} odblokował(a) domenę %{target}" + destroy_email_domain_block: "%{name} usunął(-ęła) domenę e-mail %{target} z czarnej listy" + destroy_status: "%{name} usunął(-ęła) wpis użytkownika %{target}" + disable_2fa_user: "%{name} wyłączył(a) uwierzytelnianie dwustopniowe użytkownikowi %{target}" + disable_custom_emoji: "%{name} wyłączył(a) emoji %{target}" + disable_user: "%{name} zablokował(a) możliwość logowania użytkownikowi %{target}" + enable_custom_emoji: "%{name} włączył(a) emoji %{target}" + enable_user: "%{name} przywrócił(a) możliwość logowania użytkownikowi %{target}" + memorialize_account: "%{name} nadał(a) kontu %{target} status in memoriam" + promote_user: "%{name} podniósł(a) uprawnienia użytkownikowi %{target}" + remove_avatar_user: "%{name} usunął(-ęła) awatar użytkownikowi %{target}" + reopen_report: "%{name} otworzył(a) ponownie zgłoszenie %{target}" + reset_password_user: "%{name} przywrócił(a) hasło użytkownikowi %{target}" + resolve_report: "%{name} rozwiązał(a) zgłoszenie %{target}" + silence_account: "%{name} wyciszył(a) konto %{target}" + suspend_account: "%{name} zawiesił(a) konto %{target}" + unassigned_report: "%{name} cofnął(-ęła) przypisanie zgłoszenia %{target}" + unsilence_account: "%{name} cofnął(-ęła) wyciszenie konta %{target}" + unsuspend_account: "%{name} cofnął(-ęła) zawieszenie konta %{target}" + update_custom_emoji: "%{name} zaktualizował(a) emoji %{target}" + update_status: "%{name} zaktualizował(a) wpis użytkownika %{target}" title: Dziennik działań administracyjnych custom_emojis: by_domain: Domeny @@ -368,13 +373,16 @@ pl: desc_html: Pokazuj odznakę uprawnień na stronie profilu użytkownika title: Pokazuj odznakę administracji site_description: - desc_html: Akapit wprowadzający, widoczny na stronie głównej i znacznikach meta. Możesz korzystać z tagów HTML, w szczególności <a> i <em>. + desc_html: Akapit wprowadzający, widoczny na stronie głównej. Opisz, co czyni tę instancję wyjątkową. Możesz korzystać ze znaczników HTML, w szczególności <a> i <em>. title: Opis instancji site_description_extended: - desc_html: Dobre miejsce na zasady użytkowania, wprowadzenie i inne rzeczy, które wyróżniają tę instancję. Możesz korzystać z tagów HTML + desc_html: Dobre miejsce na zasady użytkowania, wprowadzenie i inne rzeczy, które wyróżniają tę instancję. Możesz korzystać ze znaczników HTML title: Niestandardowy opis strony + site_short_description: + desc_html: Wyświetlany na pasku bocznym i w znacznikach meta. Opisz, czym jest Mastodon i czym wyróżnia się ta instancja w jednym akapicie. Jeżeli pusty, zostanie użyty opis instancji. + title: Krótki opis instancji site_terms: - desc_html: Miejsce na własną politykę prywatności, zasady użytkowania i inne unormowania prawne. Możesz korzystać z tagów HTML + desc_html: Miejsce na własną politykę prywatności, zasady użytkowania i inne unormowania prawne. Możesz korzystać ze znaczników HTML title: Niestandardowe zasady użytkowania site_title: Nazwa instancji thumbnail: @@ -406,8 +414,8 @@ pl: title: Administracja admin_mailer: new_report: - body: Użytkownik %{reporter} zgłosił %{target} - body_remote: Użytkownik instancji %{domain} zgłosił %{target} + body: Użytkownik %{reporter} zgłosił(a) %{target} + body_remote: Użytkownik instancji %{domain} zgłosił(a) %{target} subject: Nowe zgłoszenie na %{instance} (#%{id}) application_mailer: notification_preferences: Zmień ustawienia e-maili @@ -425,18 +433,18 @@ pl: warning: Przechowuj te dane ostrożnie. Nie udostępniaj ich nikomu! your_token: Twój token dostępu auth: - agreement_html: Rejestrując się, oświadczasz, że zapoznałeś się z informacjami o instancji i zasadami korzystania z usługi. + agreement_html: Rejestrując się, oświadczasz, że zapoznałeś(-aś) się z informacjami o instancji i zasadami korzystania z usługi. change_password: Hasło confirm_email: Potwierdź adres e-mail delete_account: Usunięcie konta delete_account_html: Jeżeli chcesz usunąć konto, przejdź tutaj. Otrzymasz prośbę o potwierdzenie. - didnt_get_confirmation: Nie otrzymałeś instrukcji weryfikacji? + didnt_get_confirmation: Nie otrzymałeś(-aś) instrukcji weryfikacji? forgot_password: Nie pamiętasz hasła? invalid_reset_password_token: Token do resetowania hasła jest nieprawidłowy lub utracił ważność. Spróbuj uzyskać nowy. login: Zaloguj się logout: Wyloguj się migrate_account: Przenieś konto - migrate_account_html: Jeżeli chcesz skonfigurować przekierowanie z obecnego konta na inne, możesz skonfigurować to tutaj. + migrate_account_html: Jeżeli chcesz skonfigurować przekierowanie z obecnego konta na inne, możesz zrobić to tutaj. or: lub or_log_in_with: Lub zaloguj się z użyciem providers: @@ -534,6 +542,10 @@ pl: true_privacy_html: Pamiętaj, że rzeczywista prywatność może zostać uzyskana wyłącznie dzięki szyfrowaniu end-to-end. unlocked_warning_html: Każdy może Cię śledzić, dzięki czemu może zobaczyć Twoje niepubliczne wpisy. %{lock_link} aby móc kontrolować, kto Cię śledzi. unlocked_warning_title: Twoje konto nie jest zablokowane + footer: + developers: Dla programistów + more: Więcej… + resources: Zasoby generic: changes_saved_msg: Ustawienia zapisane! save_changes: Zapisz zmiany @@ -563,7 +575,7 @@ pl: '86400': dobie expires_in_prompt: Nigdy generate: Wygeneruj - invited_by: 'Zostałeś zaproszony przez:' + invited_by: 'Zostałeś(-aś) zaproszony(-a) przez:' max_uses: few: "%{count} użycia" many: "%{count} użyć" @@ -615,13 +627,13 @@ pl: title: Nowy śledzący follow_request: action: Zarządzaj prośbami o możliwość śledzenia - body: "%{name} poprosił o możliwość śledzenia Cię" + body: "%{name} poprosił(a) o możliwość śledzenia Cię" subject: 'Prośba o możliwość śledzenia: %{name}' title: Nowa prośba o możliwość śledzenia mention: action: Odpowiedz - body: "%{name} wspomniał o Tobie w:" - subject: "%{name} wspomniał o Tobie" + body: "%{name} wspomniał(a) o Tobie w:" + subject: "%{name} wspomniał(a) o Tobie" title: Nowe wspomnienie o Tobie reblog: body: 'Twój wpis został podbity przez %{name}:' @@ -760,9 +772,9 @@ pl:

Jakie informacje zbieramy?

    -
  • Podstawowe informacje o koncie: Podczas rejestracji na tym serwerze, możesz zostać poproszony o wprowadzenie nazwy użytkownika, adresu e-mail i hasła. Możesz także wprowadzić dodatkowe informacje o profilu, takie jak nazwa wyświetlana i biografia oraz wysłać awatar i obraz nagłówka. Nazwa użytkownika, nazwa wyświetlana, biografia, awatar i obraz nagłówka są zawsze widoczne dla wszystkich.
  • +
  • Podstawowe informacje o koncie: Podczas rejestracji na tym serwerze, możesz zostać poproszony(-a) o wprowadzenie nazwy użytkownika, adresu e-mail i hasła. Możesz także wprowadzić dodatkowe informacje o profilu, takie jak nazwa wyświetlana i biografia oraz wysłać awatar i obraz nagłówka. Nazwa użytkownika, nazwa wyświetlana, biografia, awatar i obraz nagłówka są zawsze widoczne dla wszystkich.
  • Wpisy, śledzenie i inne publiczne informacje: Lista osób które śledzisz jest widoczna publicznie, tak jak lista osób, które Cię śledzą. Jeżeli dodasz wpis, data i czas jego utworzenia i aplikacja, z której go wysłano są przechowywane. Wiadomości mogą zawierać załączniki multimedialne, takie jak zdjęcia i filmy. Publiczne i niewidoczne wpisy są dostępne publicznie. Udostępniony wpis również jest widoczny publicznie. Twoje wpisy są dostarczane obserwującym, co oznacza że jego kopie mogą zostać dostarczone i być przechowywane na innych serwerach. Kiedy usuniesz wpis, przestaje być widoczny również dla osób śledzących Cię. „Podbijanie” i dodanie do ulubionych jest zawsze publiczne.
  • -
  • Wpisy bezpośrednie i tylko dla śledzących: Wszystkie wpisy są przechowywane i przetwarzane na serwerze. Wpisy przeznaczone tylko dla śledzących są widoczne tylko dla nich i osób wspomnianych we wpisie, a wpisy bezpośrednie tylko dla wspimnianych. W wielu przypadkach oznacza to, że ich kopie są dostarczane i przechowywane na innych serwerach. Staramy się ograniczać zasięg tych wpisów wyłącznie do właściwych odbiorców, ale inne serwery mogą tego nie robić. Ważne jest, aby sprawdzać jakich serwerów używają osoby, które Cię śledzą. Możesz aktywować opcję pozwalającą na ręczne akceptowanie i odrzucanie nowych śledzących. Pamiętaj, że właściciele serwerów mogą zobaczyć te wiadomości, a odbiorcy mogą wykonać zrzut ekranu, skopiować lub udostępniać ten wpis. Nie udostępniaj wrażliwych danych z użyciem Mastodona.
  • +
  • Wpisy bezpośrednie i tylko dla śledzących: Wszystkie wpisy są przechowywane i przetwarzane na serwerze. Wpisy przeznaczone tylko dla śledzących są widoczne tylko dla nich i osób wspomnianych we wpisie, a wpisy bezpośrednie tylko dla wspomnianych. W wielu przypadkach oznacza to, że ich kopie są dostarczane i przechowywane na innych serwerach. Staramy się ograniczać zasięg tych wpisów wyłącznie do właściwych odbiorców, ale inne serwery mogą tego nie robić. Ważne jest, aby sprawdzać jakich serwerów używają osoby, które Cię śledzą. Możesz aktywować opcję pozwalającą na ręczne akceptowanie i odrzucanie nowych śledzących. Pamiętaj, że właściciele serwerów mogą zobaczyć te wiadomości, a odbiorcy mogą wykonać zrzut ekranu, skopiować lub udostępniać ten wpis. Nie udostępniaj wrażliwych danych z użyciem Mastodona.
  • Adresy IP i inne metadane: Kiedy zalogujesz się, przechowujemy adres IP użyty w trakcie logowania wraz z nazwą używanej przeglądarki. Wszystkie aktywne sesje możesz zobaczyć (i wygasić) w ustawieniach. Ostatnio używany adres IP jest przechowywany przez nas do 12 miesięcy. Możemy również przechowywać adresy IP wykorzystywane przy każdym działaniu na serwerze.
@@ -803,15 +815,15 @@ pl:

Czy używany plików cookies?

-

Tak. Pliki cookies są małymi plikami, które strona lub dostawca jej usługi dostarcza na dysk twardy komputera z użyciem przeglądarki internetowej (jeżeli na to pozwoli). Pliki cookies pozwalają na rozpoznanie przeglądarki i – jeśli jesteś zarejestrowany – przypisanie jej do konta.

+

Tak. Pliki cookies są małymi plikami, które strona lub dostawca jej usługi dostarcza na dysk twardy komputera z użyciem przeglądarki internetowej (jeżeli na to pozwoli). Pliki cookies pozwalają na rozpoznanie przeglądarki i – jeśli jesteś zarejestrowany(-a) – przypisanie jej do konta.

-

Wykorzystujemy pliki cookies, aby przechowywać preferencję użytkowników na przyszłe wizyty.

+

Wykorzystujemy pliki cookies, aby przechowywać preferencje użytkowników na przyszłe wizyty.


Czy przekazujemy informacje osobom trzecim?

-

Nie sprzedajemy, nie wymieniamy i nie przekazujemy osobom trzecim informacji pozwalających na identyfikację Ciebie. Nie dotyczy to zaufanym dostawcom pomagającym w prowadzeniu lub obsługiwaniu użytkowników, jeżeli zgadzają się, aby nie przekazywać dalej tych informacji. Możemy również udostępnić informacje, jeżeli uważany to za wymagane przez prawo, konieczne do wypełnienia polityki strony, przestrzegania naszych lub cudzych praw, własności i bezpieczeństwa.

+

Nie sprzedajemy, nie wymieniamy i nie przekazujemy osobom trzecim informacji pozwalających na identyfikację Ciebie. Nie dotyczy to zaufanych dostawców pomagających w prowadzeniu strony lub obsługiwaniu użytkowników, jeżeli zgadzają się, aby nie przekazywać dalej tych informacji. Możemy również udostępnić informacje, jeżeli uważany to za wymagane przez prawo, konieczne do wypełnienia polityki strony, przestrzegania naszych lub cudzych praw, własności i bezpieczeństwa.

Twoja publiczna zawartość może zostać pobrana przez inne serwery w sieci. Wpisy publiczne i tylko dla śledzących są dostarczane na serwery, na których znajdują się śledzący Cię, a wiadomości bezpośrednie trafiają na serwery adresatów, jeżeli są oni użytkownikami innego serwera.

@@ -821,9 +833,9 @@ pl:

Korzystanie ze strony przez dzieci

-

Jeżeli serwer znajduje się w UE lub w EOG: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 16 lat. Jeżeli nie ukończyłeś 16 roku życia, zgodnie z wymogami COPPA (Prawo o Ochronie Prywatności Dzieci w Internecie), nie używaj tej strony.

+

Jeżeli serwer znajduje się w UE lub w EOG: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 16 lat. Jeżeli nie ukończyłeś(-aś) 16 roku życia, zgodnie z wymogami COPPA (Prawo o Ochronie Prywatności Dzieci w Internecie), nie używaj tej strony.

-

Jeżeli serwer znajduje się w USA: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli nie ukończyłeś 13 roku życia, zgodnie z wymogami RODO (Ogólne rozporządzenie o ochronie danych), nie używaj tej strony.

+

Jeżeli serwer znajduje się w USA: Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli nie ukończyłeś(-aś) 13 roku życia, zgodnie z wymogami RODO (Ogólne rozporządzenie o ochronie danych), nie używaj tej strony.

Wymogi mogą być inne, jeżeli serwer znajduje się w innym kraju.

@@ -874,7 +886,7 @@ pl: full_handle: Twój pełny adres full_handle_hint: Ten adres możesz podać znajomym, aby mogli skontaktować się z Tobą lub zacząć śledzić z innej instancji. review_preferences_action: Zmień ustawienia - review_preferences_step: Upewnij się, że zmieniłeś ustawienia, takie jak maile, które chciałbyś otrzymywać lub domyślne opcje prywatności. Jeżeli nie masz choroby lokomocyjnej, możesz włączyć automatyczne odtwarzanie animacji GIF. + review_preferences_step: Upewnij się, że zmieniłeś(-aś) ustawienia, takie jak maile, które chciałbyś otrzymywać lub domyślne opcje prywatności. Jeżeli nie masz choroby lokomocyjnej, możesz włączyć automatyczne odtwarzanie animacji GIF. subject: Witaj w Mastodonie tip_bridge_html: Jeżeli przybywasz z Twittera, możesz znaleźć znajomych na Mastodonie używając aplikacji mostku. Działa to tylko, jeżeli oni również z niej korzystali! tip_federated_timeline: Oś czasu federacji przedstawia całą sieć Mastodona. Wyświetla tylko wpisy osób, które śledzą użytkownicy Twojej instancji, więc nie jest kompletna. From c52bcc0331762a15cc39e1ff090cc4c113769008 Mon Sep 17 00:00:00 2001 From: ThibG Date: Sun, 5 Aug 2018 12:22:23 +0200 Subject: [PATCH 03/16] Serialize text-less statuses as '.' over OStatus (fixes #7856) (#8126) --- app/lib/ostatus/atom_serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 5c6ff4f9b9f..1a0a635b3dc 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -352,7 +352,7 @@ class OStatus::AtomSerializer append_element(entry, 'link', nil, rel: :alternate, type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(status)) if status.account.local? append_element(entry, 'summary', status.spoiler_text, 'xml:lang': status.language) if status.spoiler_text? - append_element(entry, 'content', Formatter.instance.format(status).to_str, type: 'html', 'xml:lang': status.language) + append_element(entry, 'content', Formatter.instance.format(status).to_str || '.', type: 'html', 'xml:lang': status.language) status.mentions.sort_by(&:id).each do |mentioned| append_element(entry, 'link', nil, rel: :mentioned, 'ostatus:object-type': OStatus::TagManager::TYPES[:person], href: OStatus::TagManager.instance.uri_for(mentioned.account)) From 1ab8b4b8ea59e8f87be2a2b701f82b1751099737 Mon Sep 17 00:00:00 2001 From: ThibG Date: Mon, 6 Aug 2018 15:16:02 +0200 Subject: [PATCH 04/16] Scroll to linked status in public status view (fixes #7884) (#8130) When there is a single detailed status on a public page, scroll to it and replace the history state to not scroll back on refresh (simulates # anchors). --- app/javascript/packs/public.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index 855e56ee61a..6b47eecf9b4 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -31,6 +31,7 @@ function main() { const React = require('react'); const ReactDOM = require('react-dom'); const Rellax = require('rellax'); + const createHistory = require('history').createBrowserHistory; ready(() => { const locale = document.documentElement.lang; @@ -86,6 +87,14 @@ function main() { } new Rellax('.parallax', { speed: -1 }); + + const history = createHistory(); + const detailedStatuses = document.querySelectorAll('.public-layout .detailed-status'); + const location = history.location; + if (detailedStatuses.length === 1 && (!location.state || !location.state.scrolledToDetailedStatus)) { + detailedStatuses[0].scrollIntoView(); + history.replace(location.pathname, { ...location.state, scrolledToDetailedStatus: true }); + } }); delegate(document, '.webapp-btn', 'click', ({ target, button }) => { From 58cc6738822d27340f1ce7e99108e3cb4e656d7f Mon Sep 17 00:00:00 2001 From: Mozinet Date: Tue, 7 Aug 2018 18:02:34 +0200 Subject: [PATCH 05/16] Update fr.yml for 3 spelling mistakes and a typo (#8135) --- config/locales/fr.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index bc2c7b387a3..a4f2758e015 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -18,9 +18,9 @@ fr: features: humane_approach_body: Ayant appris des échecs d’autres réseaux, Mastodon à l’ambition de combattre l’abus des médias sociaux en effectuant des choix de conception éthiques. humane_approach_title: Une approche plus humaine - not_a_product_body: Mastodon n’est pas un réseau commercial. Ici, pas de publicités, pas de prospection de données et pas d’environnement fermés. Il n’y existe aucune autorité centrale. + not_a_product_body: Mastodon n’est pas un réseau commercial. Ici, pas de publicités, pas de prospection de données et pas d’environnements fermés. Il n’y existe aucune autorité centrale. not_a_product_title: Vous êtes une personne, pas un produit - real_conversation_body: Avec 500 caractères à votre dispostion, une grande granularité en terme de diffusion et la possibilité de masquer vos messages derrières des avertissements, vous êtes libre de vous exprimer de la manière qui vous plaît. + real_conversation_body: Avec 500 caractères à votre disposition, une grande granularité en termes de diffusion et la possibilité de masquer vos messages derrières des avertissements, vous êtes libre de vous exprimer de la manière qui vous plaît. real_conversation_title: Construit pour de vraies conversations within_reach_body: Grâce à l’existence d’un environnement API accueillant pour les développeur·se·s, de multiples applications pour iOS, Android et d’autres plateformes vous permettent de rester en contact avec vos ami·e·s où que vous soyez. within_reach_title: Toujours à portée de main @@ -40,7 +40,7 @@ fr: following: Abonnements media: Médias moved_html: "%{name} a changé de compte pour %{new_profile_link} :" - network_hidden: Cette information n'est pas disponible + network_hidden: Cette information n’est pas disponible nothing_here: Rien à voir ici ! people_followed_by: Personnes suivies par %{name} people_who_follow: Personnes qui suivent %{name} From d974c94478c32da80026e9db0229f5e73ad04634 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 8 Aug 2018 21:12:45 +0200 Subject: [PATCH 06/16] Remove protocol handler registration (#8127) Browser UI too confusing / scares people, protocol URIs not used much --- app/javascript/mastodon/containers/mastodon.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js index b29898d3b27..b2b0265aac3 100644 --- a/app/javascript/mastodon/containers/mastodon.js +++ b/app/javascript/mastodon/containers/mastodon.js @@ -38,13 +38,6 @@ export default class Mastodon extends React.PureComponent { window.setTimeout(() => Notification.requestPermission(), 60 * 1000); } - // Protocol handler - // Ask after 5 minutes - if (typeof navigator.registerProtocolHandler !== 'undefined') { - const handlerUrl = window.location.protocol + '//' + window.location.host + '/intent?uri=%s'; - window.setTimeout(() => navigator.registerProtocolHandler('web+mastodon', handlerUrl, 'Mastodon'), 5 * 60 * 1000); - } - store.dispatch(showOnboardingOnce()); } From 80176a3814abad7f5c9023f97b5d4d82b73c089d Mon Sep 17 00:00:00 2001 From: Evgeny Petrov Date: Thu, 9 Aug 2018 09:50:42 +0300 Subject: [PATCH 07/16] [RU] Translation update: (#8147) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [RU] Translation update: • Added translation to Welcome timeline • Doorkeeper: changed date format to more common in Russia • Doorkeeper: added translation to scopes • Added translation to Dashboard settings (I didn't have a chance to test it on Live server, so some strings may be a bit incorrect) • Added translation to Relays settings • Added translation to Filters settings • Some other small fixes and improvements * Quoted string for "joined" key to avoid mapping error * [RU] Changed "повторить" (repeat) to "исправить" (change, fix) for a more correct translation. * i18n-tasks normalize --- app/javascript/mastodon/locales/ru.json | 44 +++++++-------- config/locales/doorkeeper.ru.yml | 26 ++++++++- config/locales/ru.yml | 72 ++++++++++++++++++++++--- config/locales/simple_form.ru.yml | 19 ++++++- 4 files changed, 130 insertions(+), 31 deletions(-) diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index ad2dcda1247..2706d5b71d1 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -12,7 +12,7 @@ "account.follows": "Подписки", "account.follows_you": "Подписан(а) на Вас", "account.hide_reblogs": "Скрыть продвижения от @{name}", - "account.media": "Медиаконтент", + "account.media": "Медиа", "account.mention": "Упомянуть", "account.moved_to": "Ищите {name} здесь:", "account.mute": "Заглушить", @@ -59,9 +59,9 @@ "column_header.show_settings": "Показать настройки", "column_header.unpin": "Открепить", "column_subheading.settings": "Настройки", - "community.column_settings.media_only": "Media Only", + "community.column_settings.media_only": "Только медиа", "compose_form.direct_message_warning": "Этот статус будет виден только упомянутым пользователям.", - "compose_form.direct_message_warning_learn_more": "Learn more", + "compose_form.direct_message_warning_learn_more": "Узнать больше", "compose_form.hashtag_warning": "Этот пост не будет показывается в поиске по хэштегу, т.к. он непубличный. Только публичные посты можно найти в поиске по хэштегу.", "compose_form.lock_disclaimer": "Ваш аккаунт не {locked}. Любой человек может подписаться на Вас и просматривать посты для подписчиков.", "compose_form.lock_disclaimer.lock": "закрыт", @@ -84,8 +84,8 @@ "confirmations.domain_block.message": "Вы на самом деле уверены, что хотите блокировать весь {domain}? В большинстве случаев нескольких отдельных блокировок или глушений достаточно.", "confirmations.mute.confirm": "Заглушить", "confirmations.mute.message": "Вы уверены, что хотите заглушить {name}?", - "confirmations.redraft.confirm": "Delete & redraft", - "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", + "confirmations.redraft.confirm": "Удалить и исправить", + "confirmations.redraft.message": "Вы уверены, что хотите удалить этот статус и превратить в черновик? Вы потеряете все ответы, продвижения и отметки 'нравится' к нему.", "confirmations.unfollow.confirm": "Отписаться", "confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?", "embed.instructions": "Встройте этот статус на Вашем сайте, скопировав код внизу.", @@ -114,14 +114,14 @@ "empty_column.public": "Здесь ничего нет! Опубликуйте что-нибудь или подпишитесь на пользователей с других узлов, чтобы заполнить ленту.", "follow_request.authorize": "Авторизовать", "follow_request.reject": "Отказать", - "getting_started.developers": "Developers", - "getting_started.documentation": "Documentation", - "getting_started.find_friends": "Find friends from Twitter", + "getting_started.developers": "Для разработчиков", + "getting_started.documentation": "Документация", + "getting_started.find_friends": "Найти друзей из Twitter", "getting_started.heading": "Добро пожаловать", - "getting_started.invite": "Invite people", - "getting_started.open_source_notice": "Mastodon - программа с открытым исходным кодом. Вы можете помочь проекту или сообщить о проблемах на GitHub по адресу {github}.", - "getting_started.security": "Security", - "getting_started.terms": "Terms of service", + "getting_started.invite": "Пригласить людей", + "getting_started.open_source_notice": "Mastodon - сервис с открытым исходным кодом. Вы можете помочь проекту или сообщить о проблемах на GitHub по адресу {github}.", + "getting_started.security": "Безопасность", + "getting_started.terms": "Условия использования", "home.column_settings.basic": "Основные", "home.column_settings.show_reblogs": "Показывать продвижения", "home.column_settings.show_replies": "Показывать ответы", @@ -137,7 +137,7 @@ "keyboard_shortcuts.hotkey": "Гор. клавиша", "keyboard_shortcuts.legend": "показать это окно", "keyboard_shortcuts.mention": "упомянуть автора поста", - "keyboard_shortcuts.profile": "to open author's profile", + "keyboard_shortcuts.profile": "перейти к профилю автора", "keyboard_shortcuts.reply": "ответить", "keyboard_shortcuts.search": "перейти к поиску", "keyboard_shortcuts.toggle_hidden": "показать/скрыть текст за предупреждением", @@ -163,22 +163,22 @@ "navigation_bar.blocks": "Список блокировки", "navigation_bar.community_timeline": "Локальная лента", "navigation_bar.direct": "Личные сообщения", - "navigation_bar.discover": "Discover", + "navigation_bar.discover": "Изучайте", "navigation_bar.domain_blocks": "Скрытые домены", "navigation_bar.edit_profile": "Изменить профиль", "navigation_bar.favourites": "Понравившееся", - "navigation_bar.filters": "Muted words", + "navigation_bar.filters": "Заглушенные слова", "navigation_bar.follow_requests": "Запросы на подписку", "navigation_bar.info": "Об узле", "navigation_bar.keyboard_shortcuts": "Сочетания клавиш", "navigation_bar.lists": "Списки", "navigation_bar.logout": "Выйти", "navigation_bar.mutes": "Список глушения", - "navigation_bar.personal": "Personal", + "navigation_bar.personal": "Личное", "navigation_bar.pins": "Закреплённые посты", "navigation_bar.preferences": "Опции", "navigation_bar.public_timeline": "Глобальная лента", - "navigation_bar.security": "Security", + "navigation_bar.security": "Безопасность", "notification.favourite": "{name} понравился Ваш статус", "notification.follow": "{name} подписался(-лась) на Вас", "notification.mention": "{name} упомянул(а) Вас", @@ -194,7 +194,7 @@ "notifications.column_settings.reblog": "Продвижения:", "notifications.column_settings.show": "Показывать в колонке", "notifications.column_settings.sound": "Проигрывать звук", - "notifications.group": "{count} notifications", + "notifications.group": "{count} уведомл.", "onboarding.done": "Готово", "onboarding.next": "Далее", "onboarding.page_five.public_timelines": "Локальная лента показывает публичные посты всех пользователей {domain}. Глобальная лента показывает публичные посты всех людей, на которых подписаны пользователи {domain}. Это - публичные ленты, отличный способ найти новые знакомства.", @@ -258,9 +258,9 @@ "status.direct": "Написать @{name}", "status.embed": "Встроить", "status.favourite": "Нравится", - "status.filtered": "Filtered", + "status.filtered": "Отфильтровано", "status.load_more": "Показать еще", - "status.media_hidden": "Медиаконтент скрыт", + "status.media_hidden": "Медиа скрыто", "status.mention": "Упомянуть @{name}", "status.more": "Больше", "status.mute": "Заглушить @{name}", @@ -271,7 +271,7 @@ "status.reblog": "Продвинуть", "status.reblog_private": "Продвинуть для своей аудитории", "status.reblogged_by": "{name} продвинул(а)", - "status.redraft": "Delete & re-draft", + "status.redraft": "Удалить и повторить", "status.reply": "Ответить", "status.replyAll": "Ответить на тред", "status.report": "Пожаловаться", @@ -289,7 +289,7 @@ "tabs_bar.local_timeline": "Локальная", "tabs_bar.notifications": "Уведомления", "tabs_bar.search": "Поиск", - "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", + "trends.count_by_accounts": "Популярно у {count} {rawCount, plural, one {человека} few {человек} many {человек} other {человек}}", "ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.", "upload_area.title": "Перетащите сюда, чтобы загрузить", "upload_button.label": "Добавить медиаконтент", diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml index 0a88d628e54..f3731755959 100644 --- a/config/locales/doorkeeper.ru.yml +++ b/config/locales/doorkeeper.ru.yml @@ -72,7 +72,7 @@ ru: index: application: Приложение created_at: Авторизовано - date_format: "%Y-%m-%d %H:%M:%S" + date_format: "%d.%m.%Y %H:%M:%S" scopes: Разрешения title: Ваши авторизованные приложения errors: @@ -117,4 +117,26 @@ ru: follow: подписываться, отписываться, блокировать и разблокировать аккаунты push: принимать push-уведомления для Вашего аккаунта read: читать данные Вашего аккаунта - write: отправлять за Вас посты + read:accounts: видеть информацию об аккаунтах + read:blocks: видеть ваших заблокированных + read:favourites: видеть ваше избранное + read:filters: видеть ваши фильтры + read:follows: видеть, на кого вы подписаны + read:lists: видеть ваши списки + read:mutes: видеть список заглушенных + read:notifications: видеть ваши уведомления + read:reports: видеть ваши жалобы + read:search: использовать поиск + read:statuses: видеть все статусы + write: изменять все данные вашего аккаунта + write:accounts: редактировать ваш профиль + write:blocks: блокировать аккаунты и домены + write:favourites: отмечать статусы как избранные + write:filters: создавать фильтры + write:follows: подписываться на людей + write:lists: создавать списки + write:media: выкладывать медиаконтент + write:mutes: заглушать людей и обсуждения + write:notifications: очищать список уведомлений + write:reports: отправлять жалобы на других + write:statuses: публиковать статусы diff --git a/config/locales/ru.yml b/config/locales/ru.yml index 5fc511d2e21..f3184e238c1 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -5,7 +5,7 @@ ru: about_mastodon_html: Mastodon - это свободная социальная сеть с открытым исходным кодом. Как децентрализованная альтернатива коммерческим платформам, Mastodon предотвращает риск монополизации Вашего общения одной компанией. Выберите сервер, которому Вы доверяете — что бы Вы ни выбрали, Вы сможете общаться со всеми остальными. Любой может запустить свой собственный узел Mastodon и участвовать в социальной сети совершенно бесшовно. about_this: Об этом узле administered_by: 'Администратор узла:' - closed_registrations: В данный момент регистрация на этом узле закрыта. + closed_registrations: В данный момент регистрация на этом узле закрыта. Но вы можете найти другой узел, создать на нём учётную запись и получить доступ к той же сети оттуда. contact: Связаться contact_missing: Не установлено contact_unavailable: Недоступен @@ -28,9 +28,11 @@ ru: hosted_on: Mastodon размещен на %{domain} learn_more: Узнать больше other_instances: Другие узлы + privacy_policy: Политика конфиденциальности source_code: Исходный код status_count_after: статусов status_count_before: Опубликовано + terms: Условия использования user_count_after: пользователей user_count_before: Здесь живет what_is_mastodon: Что такое Mastodon? @@ -38,7 +40,8 @@ ru: follow: Подписаться followers: Подписчики following: Подписан(а) - media: Медиаконтент + joined: 'Дата регистрации: %{date}' + media: Медиа moved_html: "%{name} переехал(а) на %{new_profile_link}:" network_hidden: Эта информация недоступна nothing_here: Здесь ничего нет! @@ -205,6 +208,27 @@ ru: update_failed_msg: Невозможно обновить этот эмодзи updated_msg: Эмодзи обновлён! upload: Загрузить + dashboard: + backlog: задачи + config: Конфигурация + feature_deletions: Аккаунтов удалено + feature_invites: Пригласительные ссылки + feature_registrations: Регистрации + feature_relay: Ретрансляторов сети + features: Нововведения + hidden_service: Федерация со скрытыми сервисами + open_reports: открытых жалоб + recent_users: Недавние пользователи + search: Полнотекстовый поиск + single_user_mode: Однопользовательский режим + software: Программное обеспечение + space: Использовано места + title: Панель управления + total_users: всего пользователей + trends: Тренды + week_interactions: взаимодействий на этой неделе + week_users_active: активно на этой неделе + week_users_new: пользователей на этой неделе domain_blocks: add_new: Добавить новую created_msg: Блокировка домена обрабатывается @@ -262,6 +286,14 @@ ru: expired: Истёкшие title: Фильтр title: Приглашения + relays: + add_new: Добавить ретранслятор + description_html: "Федеративный ретранслятор – это промежуточный сервер, который передаёт большие объёмы публичных статусов между серверами, которые подписываются и публикуют туда. Это может помочь небольшим и средним серверам находить записи со всей федерации, ведь в противном случае пользователям нужно будет вручную подписываться на людей с удалённых узлов." + enable_hint: Если включено, ваш сервер будет подписан на все публичные статусы с этого ретранслятора и начнёт туда отправлять публичные статусы со своего узла. + inbox_url: URL ретранслятора + setup: Настроте соединение с ретранслятором + status: Состояние + title: Ретрансляторы report_notes: created_msg: Примечание жалобы создано! destroyed_msg: Примечание жалобы удалено! @@ -281,8 +313,8 @@ ru: mark_as_unresolved: Отметить как неразрешённую notes: create: Добавить заметку - create_and_resolve: Разрешить с заметкой - create_and_unresolve: Переоткрыть с заметкой + create_and_resolve: Разрешить с примечанием + create_and_unresolve: Переоткрыть с примечанием delete: Удалить placeholder: Опишите, какие действия были приняты, или любые другие подробности… reopen: Переоткрыть жалобу @@ -317,6 +349,9 @@ ru: peers_api_enabled: desc_html: Домены, которые были замечены этим узлом среди всей федерации title: Публикация списка обнаруженных узлов + preview_sensitive_media: + desc_html: Предпросмотр ссылок с остальных веб-сайтов будет показан даже если медиаконтент отмечен как чувствительный + title: Показывать чувствительный медиаконтент в предпросмотре OpenGraph registrations: closed_message: desc_html: Отображается на титульной странице, когда закрыта регистрация
Можно использовать HTML-теги @@ -341,7 +376,10 @@ ru: title: Описание сайта site_description_extended: desc_html: Отображается на странице дополнительной информации
Можно использовать HTML-теги - title: Расширенное описание сайта + title: Расширенное описание узла + site_short_description: + desc_html: Отображается в боковой панели и в тегах. Опишите, что такое Mastodon и что делает именно этот узел особенным. Если пусто, используется описание узла по умолчанию. + title: Короткое описание узла site_terms: desc_html: Вы можете добавить сюда собственную политику конфиденциальности, пользовательское соглашение и другие документы. Можно использовать теги HTML. title: Условия использования @@ -475,6 +513,22 @@ ru: follows: Подписки mutes: Список глушения storage: Ваш медиаконтент + filters: + contexts: + home: Домашняя лента + notifications: Уведомления + public: Публичные ленты + thread: Диалоги + edit: + title: Изменить фильтр + errors: + invalid_context: Некорректный контекст или ничего + invalid_irreversible: Необратимая фильтрация работает только с лентой уведомлений и домашней лентой + index: + delete: Удалить + title: Фильтры + new: + title: Добавить фильтр followers: domain: Домен explanation_html: Если Вы хотите быть уверены в приватности Ваших статусов, Вы должны иметь четкое представление о том, кто на Вас подписан. Ваши приватные статусы отправляются всем узлам, на которых у Вас есть подписчики. Рекомендуем удалить из подписчиков пользователей узлов, администрации или программному обеспечению которых Вы не доверяете. @@ -489,6 +543,10 @@ ru: true_privacy_html: Пожалуйста, заметьте, что настоящая конфиденциальность может быть достигнута только при помощи end-to-end шифрования. unlocked_warning_html: Кто угодно может подписаться на Вас и получить доступ к просмотру Ваших приватных статусов. %{lock_link}, чтобы получить возможность рассматривать и вручную подтверждать запросы о подписке. unlocked_warning_title: Ваш аккаунт не закрыт для подписки + footer: + developers: Разработчики + more: Ещё… + resources: Ссылки generic: changes_saved_msg: Изменения успешно сохранены! save_changes: Сохранить изменения @@ -606,6 +664,7 @@ ru: remote_follow: acct: Введите username@domain, откуда Вы хотите подписаться missing_resource: Поиск требуемого перенаправления URL для Вашего аккаунта завершился неудачей + no_account_html: Нет учётной записи? Вы можете зарегистрироваться здесь proceed: Продолжить подписку prompt: 'Вы хотите подписаться на:' remote_unfollow: @@ -688,6 +747,7 @@ ru: many: 'содержались запрещённые хэштеги: %{tags}' one: 'содержался запрещённый хэштег: %{tags}' other: 'содержались запрещённые хэштеги: %{tags}' + language_detection: Определять язык автоматически open_in_web: Открыть в WWW over_character_limit: превышен лимит символов (%{max}) pin_errors: @@ -705,7 +765,7 @@ ru: unlisted: Скрывать из лент unlisted_long: Показывать всем, но не отображать в публичных лентах stream_entries: - pinned: Закреплённое сообщение + pinned: Закреплённый статус reblogged: продвинул(а) sensitive_content: Чувствительный контент terms: diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml index 9174237bc95..4db6fd45c4e 100644 --- a/config/locales/simple_form.ru.yml +++ b/config/locales/simple_form.ru.yml @@ -3,8 +3,10 @@ ru: simple_form: hints: defaults: + autofollow: Люди, пришедшие по этому приглашению автоматически будут подписаны на Вас avatar: PNG, GIF или JPG. Максимально %{size}. Будет уменьшено до %{dimensions}px bot: Этот аккаунт обычно выполяет автоматизированные действия и может не просматриваться владельцем + context: Один или несколько контекстов, к которым должны быть применены фильтры digest: Отсылается лишь после длительной неактивности, если Вы в это время получали личные сообщения display_name: few: Осталось %{count} символа @@ -13,15 +15,22 @@ ru: other: Осталось %{count} символов fields: В профиле можно отобразить до 4 пунктов как таблицу header: PNG, GIF или JPG. Максимально %{size}. Будет уменьшено до %{dimensions}px + inbox_url: Копировать URL с главной страницы ретранслятора, который Вы хотите использовать + irreversible: Отфильтрованные статусы будут утеряны навсегда, даже если в будущем фильтр будет убран + locale: Язык интерфейса, e-mail писем и push-уведомлений locked: Потребует от Вас ручного подтверждения подписчиков, изменит приватность постов по умолчанию на "только для подписчиков" note: few: Осталось %{count} символа many: Осталось %{count} символов one: Остался 1 символ other: Осталось %{count} символов + phrase: Будет сопоставлено независимо от присутствия в тексте или предупреждения о содержании статуса + scopes: Какие API приложению будет позволено использовать. Если Вы выберите самый верхний, нижестоящие будут выбраны автоматически. + setting_default_language: Язык Ваших статусов может быть определён автоматически, но не всегда правильно setting_hide_network: Те, на кого Вы подписаны и кто подписан на Вас, не будут отображены в Вашем профиле setting_noindex: Относится к Вашему публичному профилю и страницам статусов setting_theme: Влияет на внешний вид Mastodon при выполненном входе в аккаунт. + whole_word: Если слово или фраза состоит только из букв и цифр, сопоставление произойдёт только по полному совпадению imports: data: Файл CSV, экспортированный с другого узла Mastodon sessions: @@ -32,10 +41,13 @@ ru: name: Пункт value: Значение defaults: + autofollow: Пригласите подписаться на Ваш аккаунт avatar: Аватар bot: Это аккаунт бота + chosen_languages: Фильтр языков confirm_new_password: Повторите новый пароль confirm_password: Повторите пароль + context: Контекст фильтра current_password: Текущий пароль data: Данные display_name: Показываемое имя @@ -43,15 +55,19 @@ ru: expires_in: Срок действия fields: Метаданные профиля header: Заголовок - locale: Язык + inbox_url: URL для входящих от ретрансляторов + irreversible: Удалять, а не скрывать + locale: Язык интерфейса locked: Сделать аккаунт закрытым max_uses: Макс. число использований new_password: Новый пароль note: О Вас otp_attempt: Двухфакторный код password: Пароль + phrase: Слово или фраза setting_auto_play_gif: Автоматически проигрывать анимированные GIF setting_boost_modal: Показывать диалог подтверждения перед продвижением + setting_default_language: Язык отправляемых статусов setting_default_privacy: Видимость постов setting_default_sensitive: Всегда отмечать медиаконтент как чувствительный setting_delete_modal: Показывать диалог подтверждения перед удалением @@ -66,6 +82,7 @@ ru: type: Тип импорта username: Имя пользователя username_or_email: Имя пользователя или e-mail + whole_word: Слово целиком interactions: must_be_follower: Заблокировать уведомления не от подписчиков must_be_following: Заблокировать уведомления от людей, на которых Вы не подписаны From f2404de871f0bdfda5c9aeeeb4c6c4d10a8da8ab Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 9 Aug 2018 09:56:53 +0200 Subject: [PATCH 08/16] Public profile endorsements (accounts picked by profile owner) (#8146) --- app/controllers/accounts_controller.rb | 5 +- .../api/v1/accounts/pins_controller.rb | 32 ++++++++ app/helpers/home_helper.rb | 32 ++++++++ app/javascript/mastodon/actions/accounts.js | 74 +++++++++++++++++++ .../features/account/components/action_bar.js | 6 ++ .../account_timeline/components/header.js | 6 ++ .../containers/header_container.js | 10 +++ .../mastodon/reducers/relationships.js | 4 + app/javascript/styles/mastodon/widgets.scss | 32 ++++++++ app/models/account.rb | 4 + app/models/account_pin.rb | 26 +++++++ app/models/concerns/account_interactions.rb | 8 ++ .../account_relationships_presenter.rb | 7 +- .../rest/relationship_serializer.rb | 7 +- app/views/accounts/show.html.haml | 8 ++ config/locales/en.yml | 3 + config/routes.rb | 3 + .../20180808175627_create_account_pins.rb | 12 +++ db/schema.rb | 16 +++- spec/fabricators/account_pin_fabricator.rb | 4 + spec/models/account_pin_spec.rb | 5 ++ 21 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 app/controllers/api/v1/accounts/pins_controller.rb create mode 100644 app/models/account_pin.rb create mode 100644 db/migrate/20180808175627_create_account_pins.rb create mode 100644 spec/fabricators/account_pin_fabricator.rb create mode 100644 spec/models/account_pin_spec.rb diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 86e3b6e47ee..e5a7301eeb5 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -10,8 +10,9 @@ class AccountsController < ApplicationController def show respond_to do |format| format.html do - @body_classes = 'with-modals' - @pinned_statuses = [] + @body_classes = 'with-modals' + @pinned_statuses = [] + @endorsed_accounts = @account.endorsed_accounts.to_a.sample(4) if current_account && @account.blocking?(current_account) @statuses = [] diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb new file mode 100644 index 00000000000..0a0239c424e --- /dev/null +++ b/app/controllers/api/v1/accounts/pins_controller.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class Api::V1::Accounts::PinsController < Api::BaseController + include Authorization + + before_action -> { doorkeeper_authorize! :write, :'write:accounts' } + before_action :require_user! + before_action :set_account + + respond_to :json + + def create + AccountPin.create!(account: current_account, target_account: @account) + render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter + end + + def destroy + pin = AccountPin.find_by(account: current_account, target_account: @account) + pin&.destroy! + render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter + end + + private + + def set_account + @account = Account.find(params[:account_id]) + end + + def relationships_presenter + AccountRelationshipsPresenter.new([@account.id], current_user.account_id) + end +end diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb index d3c6b13a65e..8449f6c8a47 100644 --- a/app/helpers/home_helper.rb +++ b/app/helpers/home_helper.rb @@ -6,4 +6,36 @@ module HomeHelper locale: I18n.locale, } end + + def account_link_to(account, button = '') + content_tag(:div, class: 'account') do + content_tag(:div, class: 'account__wrapper') do + section = if account.nil? + content_tag(:div, class: 'account__display-name') do + content_tag(:div, class: 'account__avatar-wrapper') do + content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})") + end + + content_tag(:span, class: 'display-name') do + content_tag(:strong, t('about.contact_missing')) + + content_tag(:span, t('about.contact_unavailable'), class: 'display-name__account') + end + end + else + link_to(TagManager.instance.url_for(account), class: 'account__display-name') do + content_tag(:div, class: 'account__avatar-wrapper') do + content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{account.avatar.url})") + end + + content_tag(:span, class: 'display-name') do + content_tag(:bdi) do + content_tag(:strong, display_name(account, custom_emojify: true), class: 'display-name__html emojify') + end + + content_tag(:span, "@#{account.acct}", class: 'display-name__account') + end + end + end + + section + button + end + end + end end diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index c9e4afcfc3d..cbae62a0f4c 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -30,6 +30,14 @@ export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST'; export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS'; export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL'; +export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST'; +export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS'; +export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL'; + +export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST'; +export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS'; +export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL'; + export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST'; export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS'; export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL'; @@ -694,3 +702,69 @@ export function rejectFollowRequestFail(id, error) { error, }; }; + +export function pinAccount(id) { + return (dispatch, getState) => { + dispatch(pinAccountRequest(id)); + + api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => { + dispatch(pinAccountSuccess(response.data)); + }).catch(error => { + dispatch(pinAccountFail(error)); + }); + }; +}; + +export function unpinAccount(id) { + return (dispatch, getState) => { + dispatch(unpinAccountRequest(id)); + + api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => { + dispatch(unpinAccountSuccess(response.data)); + }).catch(error => { + dispatch(unpinAccountFail(error)); + }); + }; +}; + +export function pinAccountRequest(id) { + return { + type: ACCOUNT_PIN_REQUEST, + id, + }; +}; + +export function pinAccountSuccess(relationship) { + return { + type: ACCOUNT_PIN_SUCCESS, + relationship, + }; +}; + +export function pinAccountFail(error) { + return { + type: ACCOUNT_PIN_FAIL, + error, + }; +}; + +export function unpinAccountRequest(id) { + return { + type: ACCOUNT_UNPIN_REQUEST, + id, + }; +}; + +export function unpinAccountSuccess(relationship) { + return { + type: ACCOUNT_UNPIN_SUCCESS, + relationship, + }; +}; + +export function unpinAccountFail(error) { + return { + type: ACCOUNT_UNPIN_FAIL, + error, + }; +}; diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js index e3f2d0f55c3..43b4811e103 100644 --- a/app/javascript/mastodon/features/account/components/action_bar.js +++ b/app/javascript/mastodon/features/account/components/action_bar.js @@ -32,6 +32,8 @@ const messages = defineMessages({ blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden 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' }, }); @injectIntl @@ -48,6 +50,7 @@ export default class ActionBar extends React.PureComponent { onMute: PropTypes.func.isRequired, onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, + onEndorseToggle: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; @@ -93,6 +96,9 @@ export default class ActionBar extends React.PureComponent { } else { menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); } + + menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); + menu.push(null); } if (account.getIn(['relationship', 'muting'])) { diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js index 1ae5126e60f..ab29e4bdf76 100644 --- a/app/javascript/mastodon/features/account_timeline/components/header.js +++ b/app/javascript/mastodon/features/account_timeline/components/header.js @@ -22,6 +22,7 @@ export default class Header extends ImmutablePureComponent { onMute: PropTypes.func.isRequired, onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, + onEndorseToggle: PropTypes.func.isRequired, hideTabs: PropTypes.bool, }; @@ -73,6 +74,10 @@ export default class Header extends ImmutablePureComponent { this.props.onUnblockDomain(domain); } + handleEndorseToggle = () => { + this.props.onEndorseToggle(this.props.account); + } + render () { const { account, hideTabs } = this.props; @@ -100,6 +105,7 @@ export default class Header extends ImmutablePureComponent { onMute={this.handleMute} onBlockDomain={this.handleBlockDomain} onUnblockDomain={this.handleUnblockDomain} + onEndorseToggle={this.handleEndorseToggle} /> {!hideTabs && ( diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js index 7681430b789..02803893d89 100644 --- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js +++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js @@ -8,6 +8,8 @@ import { blockAccount, unblockAccount, unmuteAccount, + pinAccount, + unpinAccount, } from '../../../actions/accounts'; import { mentionCompose, @@ -82,6 +84,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onEndorseToggle (account) { + if (account.getIn(['relationship', 'endorsed'])) { + dispatch(unpinAccount(account.get('id'))); + } else { + dispatch(pinAccount(account.get('id'))); + } + }, + onReport (account) { dispatch(initReport(account)); }, diff --git a/app/javascript/mastodon/reducers/relationships.js b/app/javascript/mastodon/reducers/relationships.js index d1caabc1c70..f4604929723 100644 --- a/app/javascript/mastodon/reducers/relationships.js +++ b/app/javascript/mastodon/reducers/relationships.js @@ -5,6 +5,8 @@ import { ACCOUNT_UNBLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS, ACCOUNT_UNMUTE_SUCCESS, + ACCOUNT_PIN_SUCCESS, + ACCOUNT_UNPIN_SUCCESS, RELATIONSHIPS_FETCH_SUCCESS, } from '../actions/accounts'; import { @@ -41,6 +43,8 @@ export default function relationships(state = initialState, action) { case ACCOUNT_UNBLOCK_SUCCESS: case ACCOUNT_MUTE_SUCCESS: case ACCOUNT_UNMUTE_SUCCESS: + case ACCOUNT_PIN_SUCCESS: + case ACCOUNT_UNPIN_SUCCESS: return normalizeRelationship(state, action.relationship); case RELATIONSHIPS_FETCH_SUCCESS: return normalizeRelationships(state, action.relationships); diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index d37a6f4587a..b05bbbda7c8 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -71,6 +71,38 @@ } } +.endorsements-widget { + margin-bottom: 10px; + padding-bottom: 10px; + + h4 { + padding: 10px; + text-transform: uppercase; + font-weight: 700; + font-size: 13px; + color: $darker-text-color; + } + + .account { + padding: 10px 0; + + &:last-child { + border-bottom: 0; + } + + .account__display-name { + display: flex; + align-items: center; + } + + .account__avatar { + width: 44px; + height: 44px; + background-size: 44px 44px; + } + } +} + .moved-account-widget { padding: 15px; padding-bottom: 20px; diff --git a/app/models/account.rb b/app/models/account.rb index 0272b4615a4..c33ec4bd52c 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -89,6 +89,10 @@ class Account < ApplicationRecord has_many :status_pins, inverse_of: :account, dependent: :destroy has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status + # Endorsements + has_many :account_pins, inverse_of: :account, dependent: :destroy + has_many :endorsed_accounts, through: :account_pins, class_name: 'Account', source: :target_account + # Media has_many :media_attachments, dependent: :destroy diff --git a/app/models/account_pin.rb b/app/models/account_pin.rb new file mode 100644 index 00000000000..9a21c340544 --- /dev/null +++ b/app/models/account_pin.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: account_pins +# +# id :bigint(8) not null, primary key +# account_id :bigint(8) +# target_account_id :bigint(8) +# created_at :datetime not null +# updated_at :datetime not null +# + +class AccountPin < ApplicationRecord + include RelationshipCacheable + + belongs_to :account + belongs_to :target_account, class_name: 'Account' + + validate :validate_follow_relationship + + private + + def validate_follow_relationship + errors.add(:base, I18n.t('accounts.pin_errors.following')) unless account.following?(target_account) + end +end diff --git a/app/models/concerns/account_interactions.rb b/app/models/concerns/account_interactions.rb index e14e041f614..f5f833446ab 100644 --- a/app/models/concerns/account_interactions.rb +++ b/app/models/concerns/account_interactions.rb @@ -40,6 +40,10 @@ module AccountInteractions end end + def endorsed_map(target_account_ids, account_id) + follow_mapping(AccountPin.where(account_id: account_id, target_account_id: target_account_ids), :target_account_id) + end + def domain_blocking_map(target_account_ids, account_id) accounts_map = Account.where(id: target_account_ids).select('id, domain').map { |a| [a.id, a.domain] }.to_h blocked_domains = domain_blocking_map_by_domain(accounts_map.values.compact, account_id) @@ -190,6 +194,10 @@ module AccountInteractions status_pins.where(status: status).exists? end + def endorsed?(account) + account_pins.where(target_account: account).exists? + end + def followers_for_local_distribution followers.local .joins(:user) diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index b1e99b31b7c..e4aaa65f6ff 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -2,7 +2,8 @@ class AccountRelationshipsPresenter attr_reader :following, :followed_by, :blocking, - :muting, :requested, :domain_blocking + :muting, :requested, :domain_blocking, + :endorsed def initialize(account_ids, current_account_id, **options) @account_ids = account_ids.map { |a| a.is_a?(Account) ? a.id : a } @@ -14,6 +15,7 @@ class AccountRelationshipsPresenter @muting = cached[:muting].merge(Account.muting_map(@uncached_account_ids, @current_account_id)) @requested = cached[:requested].merge(Account.requested_map(@uncached_account_ids, @current_account_id)) @domain_blocking = cached[:domain_blocking].merge(Account.domain_blocking_map(@uncached_account_ids, @current_account_id)) + @endorsed = cached[:endorsed].merge(Account.endorsed_map(@uncached_account_ids, @current_account_id)) cache_uncached! @@ -23,6 +25,7 @@ class AccountRelationshipsPresenter @muting.merge!(options[:muting_map] || {}) @requested.merge!(options[:requested_map] || {}) @domain_blocking.merge!(options[:domain_blocking_map] || {}) + @endorsed.merge!(options[:endorsed_map] || {}) end private @@ -37,6 +40,7 @@ class AccountRelationshipsPresenter muting: {}, requested: {}, domain_blocking: {}, + endorsed: {}, } @uncached_account_ids = [] @@ -63,6 +67,7 @@ class AccountRelationshipsPresenter muting: { account_id => muting[account_id] }, requested: { account_id => requested[account_id] }, domain_blocking: { account_id => domain_blocking[account_id] }, + endorsed: { account_id => endorsed[account_id] }, } Rails.cache.write("relationship:#{@current_account_id}:#{account_id}", maps_for_account, expires_in: 1.day) diff --git a/app/serializers/rest/relationship_serializer.rb b/app/serializers/rest/relationship_serializer.rb index 45bfd4d6e76..c6c722a54ea 100644 --- a/app/serializers/rest/relationship_serializer.rb +++ b/app/serializers/rest/relationship_serializer.rb @@ -2,7 +2,8 @@ class REST::RelationshipSerializer < ActiveModel::Serializer attributes :id, :following, :showing_reblogs, :followed_by, :blocking, - :muting, :muting_notifications, :requested, :domain_blocking + :muting, :muting_notifications, :requested, :domain_blocking, + :endorsed def id object.id.to_s @@ -41,4 +42,8 @@ class REST::RelationshipSerializer < ActiveModel::Serializer def domain_blocking instance_options[:relationships].domain_blocking[object.id] || false end + + def endorsed + instance_options[:relationships].endorsed[object.id] || false + end end diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index b30755d94d0..e398fc29bb9 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -55,4 +55,12 @@ = render 'moved', account: @account = render 'bio', account: @account + + - unless @endorsed_accounts.empty? + .endorsements-widget + %h4= t 'accounts.choices_html', name: content_tag(:bdi, display_name(@account, custom_emojify: true)) + + - @endorsed_accounts.each do |account| + = account_link_to account + = render 'application/sidebar' diff --git a/config/locales/en.yml b/config/locales/en.yml index 4693fe1ba30..ef5b2c93bd7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -39,6 +39,7 @@ en: user_count_before: Home to what_is_mastodon: What is Mastodon? accounts: + choices_html: "%{name}'s choices:" follow: Follow followers: Followers following: Following @@ -49,6 +50,8 @@ en: nothing_here: There is nothing here! people_followed_by: People whom %{name} follows people_who_follow: People who follow %{name} + pin_errors: + following: You must be already following the person you want to endorse posts: Toots posts_with_replies: Toots and replies reserved_username: The username is reserved diff --git a/config/routes.rb b/config/routes.rb index 1c97f5a82c1..2983011d262 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -309,6 +309,9 @@ Rails.application.routes.draw do post :mute post :unmute end + + resource :pin, only: :create, controller: 'accounts/pins' + post :unpin, to: 'accounts/pins#destroy' end resources :lists, only: [:index, :create, :show, :update, :destroy] do diff --git a/db/migrate/20180808175627_create_account_pins.rb b/db/migrate/20180808175627_create_account_pins.rb new file mode 100644 index 00000000000..43d8185be9d --- /dev/null +++ b/db/migrate/20180808175627_create_account_pins.rb @@ -0,0 +1,12 @@ +class CreateAccountPins < ActiveRecord::Migration[5.2] + def change + create_table :account_pins do |t| + t.belongs_to :account, foreign_key: { on_delete: :cascade } + t.belongs_to :target_account, foreign_key: { on_delete: :cascade, to_table: :accounts } + + t.timestamps + end + + add_index :account_pins, [:account_id, :target_account_id], unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index e0da669c46c..46ee42714c3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_07_11_152640) do +ActiveRecord::Schema.define(version: 2018_08_08_175627) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -33,6 +33,16 @@ ActiveRecord::Schema.define(version: 2018_07_11_152640) do t.index ["target_account_id"], name: "index_account_moderation_notes_on_target_account_id" end + create_table "account_pins", force: :cascade do |t| + t.bigint "account_id" + t.bigint "target_account_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["account_id", "target_account_id"], name: "index_account_pins_on_account_id_and_target_account_id", unique: true + t.index ["account_id"], name: "index_account_pins_on_account_id" + t.index ["target_account_id"], name: "index_account_pins_on_target_account_id" + end + create_table "accounts", force: :cascade do |t| t.string "username", default: "", null: false t.string "domain" @@ -149,9 +159,9 @@ ActiveRecord::Schema.define(version: 2018_07_11_152640) do t.text "phrase", default: "", null: false t.string "context", default: [], null: false, array: true t.boolean "irreversible", default: false, null: false - t.boolean "whole_word", default: true, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "whole_word", default: true, null: false t.index ["account_id"], name: "index_custom_filters_on_account_id" end @@ -575,6 +585,8 @@ ActiveRecord::Schema.define(version: 2018_07_11_152640) do add_foreign_key "account_domain_blocks", "accounts", name: "fk_206c6029bd", on_delete: :cascade add_foreign_key "account_moderation_notes", "accounts" add_foreign_key "account_moderation_notes", "accounts", column: "target_account_id" + add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade + add_foreign_key "account_pins", "accounts", on_delete: :cascade add_foreign_key "accounts", "accounts", column: "moved_to_account_id", on_delete: :nullify add_foreign_key "admin_action_logs", "accounts", on_delete: :cascade add_foreign_key "backups", "users", on_delete: :nullify diff --git a/spec/fabricators/account_pin_fabricator.rb b/spec/fabricators/account_pin_fabricator.rb new file mode 100644 index 00000000000..c0f8b8afbb6 --- /dev/null +++ b/spec/fabricators/account_pin_fabricator.rb @@ -0,0 +1,4 @@ +Fabricator(:account_pin) do + account nil + target_account nil +end diff --git a/spec/models/account_pin_spec.rb b/spec/models/account_pin_spec.rb new file mode 100644 index 00000000000..4f226b12770 --- /dev/null +++ b/spec/models/account_pin_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe AccountPin, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 0dcc1950d14cc4a7725ea1572d253c538a1f74e8 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 9 Aug 2018 12:58:20 +0200 Subject: [PATCH 09/16] Update /terms and /about/more to use public layout (#8142) --- app/controllers/about_controller.rb | 8 +- app/javascript/styles/mastodon/about.scss | 407 ++++++++++++------ .../styles/mastodon/containers.scss | 37 ++ app/javascript/styles/mastodon/widgets.scss | 42 ++ app/views/about/_administration.html.haml | 19 - app/views/about/_contact.html.haml | 22 - app/views/about/more.html.haml | 66 +-- app/views/about/show.html.haml | 4 +- app/views/about/terms.html.haml | 14 +- config/locales/ar.yml | 3 - config/locales/ast.yml | 2 - config/locales/bg.yml | 3 - config/locales/ca.yml | 3 - config/locales/co.yml | 3 - config/locales/cs.yml | 3 - config/locales/da.yml | 3 - config/locales/de.yml | 3 - config/locales/el.yml | 3 - config/locales/en.yml | 3 - config/locales/eo.yml | 3 - config/locales/es.yml | 3 - config/locales/eu.yml | 3 - config/locales/fa.yml | 3 - config/locales/fi.yml | 3 - config/locales/fr.yml | 3 - config/locales/gl.yml | 3 - config/locales/he.yml | 3 - config/locales/hr.yml | 3 - config/locales/hu.yml | 3 - config/locales/id.yml | 3 - config/locales/io.yml | 3 - config/locales/it.yml | 3 - config/locales/ja.yml | 3 - config/locales/ko.yml | 3 - config/locales/nl.yml | 3 - config/locales/no.yml | 3 - config/locales/oc.yml | 3 - config/locales/pl.yml | 3 - config/locales/pt-BR.yml | 3 - config/locales/pt.yml | 3 - config/locales/ru.yml | 3 - config/locales/sk.yml | 3 - config/locales/sl.yml | 3 - config/locales/sr-Latn.yml | 3 - config/locales/sr.yml | 3 - config/locales/sv.yml | 3 - config/locales/th.yml | 3 - config/locales/tr.yml | 3 - config/locales/uk.yml | 3 - config/locales/zh-CN.yml | 3 - config/locales/zh-HK.yml | 3 - config/locales/zh-TW.yml | 3 - spec/views/about/_contact.html.haml_spec.rb | 35 -- 53 files changed, 397 insertions(+), 385 deletions(-) delete mode 100644 app/views/about/_administration.html.haml delete mode 100644 app/views/about/_contact.html.haml delete mode 100644 spec/views/about/_contact.html.haml_spec.rb diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb index 810f212fd2a..0dbf0283d20 100644 --- a/app/controllers/about_controller.rb +++ b/app/controllers/about_controller.rb @@ -9,9 +9,13 @@ class AboutController < ApplicationController @initial_state_json = serializable_resource.to_json end - def more; end + def more + render layout: 'public' + end - def terms; end + def terms + render layout: 'public' + end private diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index b9544bb33b3..bba7044cf3b 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -15,6 +15,276 @@ $small-breakpoint: 960px; } } +.rich-formatting { + font-family: 'mastodon-font-sans-serif', sans-serif; + font-size: 16px; + font-weight: 400; + font-size: 16px; + line-height: 30px; + color: $darker-text-color; + padding-right: 10px; + + a { + color: $highlight-text-color; + text-decoration: underline; + } + + p, + li { + font-family: 'mastodon-font-sans-serif', sans-serif; + font-size: 16px; + font-weight: 400; + font-size: 16px; + line-height: 30px; + margin-bottom: 12px; + color: $darker-text-color; + + a { + color: $highlight-text-color; + text-decoration: underline; + } + + &:last-child { + margin-bottom: 0; + } + } + + em { + display: inline; + margin: 0; + padding: 0; + font-weight: 700; + background: transparent; + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: lighten($darker-text-color, 10%); + } + + h1 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 26px; + line-height: 30px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + + small { + font-family: 'mastodon-font-sans-serif', sans-serif; + display: block; + font-size: 18px; + font-weight: 400; + color: lighten($darker-text-color, 10%); + } + } + + h2 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 22px; + line-height: 26px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h3 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 18px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h4 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h5 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 14px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h6 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 12px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + ul, + ol { + margin-left: 20px; + + &[type='a'] { + list-style-type: lower-alpha; + } + + &[type='i'] { + list-style-type: lower-roman; + } + } + + ul { + list-style: disc; + } + + ol { + list-style: decimal; + } + + li > ol, + li > ul { + margin-top: 6px; + } + + hr { + width: 100%; + height: 0; + border: 0; + border-bottom: 1px solid rgba($ui-base-lighter-color, .6); + margin: 20px 0; + + &.spacer { + height: 1px; + border: 0; + } + } +} + +.information-board { + background: darken($ui-base-color, 4%); + padding: 20px 0; + + .container-alt { + position: relative; + padding-right: 280px + 15px; + } + + &__sections { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + } + + &__section { + flex: 1 0 0; + font-family: 'mastodon-font-sans-serif', sans-serif; + font-size: 16px; + line-height: 28px; + color: $primary-text-color; + text-align: right; + padding: 10px 15px; + + span, + strong { + display: block; + } + + span { + &:last-child { + color: $secondary-text-color; + } + } + + strong { + font-weight: 500; + font-size: 32px; + line-height: 48px; + } + + @media screen and (max-width: $column-breakpoint) { + text-align: center; + } + } + + .panel { + position: absolute; + width: 280px; + box-sizing: border-box; + background: darken($ui-base-color, 8%); + padding: 20px; + padding-top: 10px; + border-radius: 4px 4px 0 0; + right: 0; + bottom: -40px; + + .panel-header { + font-family: 'mastodon-font-display', sans-serif; + font-size: 14px; + line-height: 24px; + font-weight: 500; + color: $darker-text-color; + padding-bottom: 5px; + margin-bottom: 15px; + border-bottom: 1px solid lighten($ui-base-color, 4%); + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + + a, + span { + font-weight: 400; + color: darken($darker-text-color, 10%); + } + + a { + text-decoration: none; + } + } + } + + .owner { + text-align: center; + + .avatar { + width: 80px; + height: 80px; + margin: 0 auto; + margin-bottom: 15px; + + img { + display: block; + width: 80px; + height: 80px; + border-radius: 48px; + } + } + + .name { + font-size: 14px; + + a { + display: block; + color: $primary-text-color; + text-decoration: none; + + &:hover { + .display_name { + text-decoration: underline; + } + } + } + + .username { + display: block; + color: $darker-text-color; + } + } + } +} + .landing-page { .grid { display: grid; @@ -486,128 +756,6 @@ $small-breakpoint: 960px; } } - .information-board { - background: darken($ui-base-color, 4%); - padding: 20px 0; - - .container-alt { - position: relative; - padding-right: 280px + 15px; - } - - &__sections { - display: flex; - justify-content: space-between; - flex-wrap: wrap; - } - - &__section { - flex: 1 0 0; - font-family: 'mastodon-font-sans-serif', sans-serif; - font-size: 16px; - line-height: 28px; - color: $primary-text-color; - text-align: right; - padding: 10px 15px; - - span, - strong { - display: block; - } - - span { - &:last-child { - color: $secondary-text-color; - } - } - - strong { - font-weight: 500; - font-size: 32px; - line-height: 48px; - } - - @media screen and (max-width: $column-breakpoint) { - text-align: center; - } - } - - .panel { - position: absolute; - width: 280px; - box-sizing: border-box; - background: darken($ui-base-color, 8%); - padding: 20px; - padding-top: 10px; - border-radius: 4px 4px 0 0; - right: 0; - bottom: -40px; - - .panel-header { - font-family: 'mastodon-font-display', sans-serif; - font-size: 14px; - line-height: 24px; - font-weight: 500; - color: $darker-text-color; - padding-bottom: 5px; - margin-bottom: 15px; - border-bottom: 1px solid lighten($ui-base-color, 4%); - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - - a, - span { - font-weight: 400; - color: darken($darker-text-color, 10%); - } - - a { - text-decoration: none; - } - } - } - - .owner { - text-align: center; - - .avatar { - width: 80px; - height: 80px; - margin: 0 auto; - margin-bottom: 15px; - - img { - display: block; - width: 80px; - height: 80px; - border-radius: 48px; - } - } - - .name { - font-size: 14px; - - a { - display: block; - color: $primary-text-color; - text-decoration: none; - - &:hover { - .display_name { - text-decoration: underline; - } - } - } - - .username { - display: block; - color: $darker-text-color; - } - } - } - } - &.alternative { padding: 10px 0; @@ -983,21 +1131,6 @@ $small-breakpoint: 960px; } } - .extended-description { - padding: 50px 0; - font-family: 'mastodon-font-sans-serif', sans-serif; - font-size: 16px; - font-weight: 400; - font-size: 16px; - line-height: 30px; - color: $darker-text-color; - - a { - color: $highlight-text-color; - text-decoration: underline; - } - } - .footer-links { padding-bottom: 50px; text-align: right; diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index 7b339277f55..ba36d62d97e 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -115,6 +115,34 @@ } } +.grid-3 { + display: grid; + grid-gap: 10px; + grid-template-columns: 3fr 1fr; + grid-auto-columns: 25%; + grid-auto-rows: max-content; + + .column-0 { + grid-column: 1/3; + grid-row: 1; + } + + .column-1 { + grid-column: 1; + grid-row: 2; + } + + .column-2 { + grid-column: 2; + grid-row: 2; + } + + .column-3 { + grid-column: 1/3; + grid-row: 3; + } +} + .public-layout { @media screen and (max-width: $no-gap-breakpoint) { padding-top: 48px; @@ -300,6 +328,15 @@ } } + &--no-bar { + margin-bottom: 0; + + .public-account-header__image, + .public-account-header__image img { + border-radius: 4px; + } + } + @media screen and (max-width: $no-gap-breakpoint) { margin-bottom: 0; box-shadow: none; diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index b05bbbda7c8..875a369594f 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -103,6 +103,48 @@ } } +.box-widget { + padding: 20px; + border-radius: 4px; + background: $ui-base-color; + box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); +} + +.contact-widget, +.landing-page__information.contact-widget { + box-sizing: border-box; + padding: 20px; + height: 100%; + border-radius: 4px; + background: $ui-base-color; + box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); +} + +.contact-widget { + font-size: 15px; + color: $darker-text-color; + line-height: 20px; + word-wrap: break-word; + font-weight: 400; + + p { + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + + &__mail { + margin-top: 10px; + + a { + color: $primary-text-color; + text-decoration: none; + } + } +} + .moved-account-widget { padding: 15px; padding-bottom: 20px; diff --git a/app/views/about/_administration.html.haml b/app/views/about/_administration.html.haml deleted file mode 100644 index 02286d68b7b..00000000000 --- a/app/views/about/_administration.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -.account - .account__wrapper - - if @instance_presenter.contact_account - = link_to TagManager.instance.url_for(@instance_presenter.contact_account), class: 'account__display-name' do - .account__avatar-wrapper - .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" } - %span.display-name - %bdi - %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account, custom_emojify: true) - %span.display-name__account @#{@instance_presenter.contact_account.acct} - - else - .account__display-name - .account__avatar-wrapper - .account__avatar{ style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})" } - %span.display-name - %strong= t 'about.contact_missing' - %span.display-name__account= t 'about.contact_unavailable' - - = link_to t('about.learn_more'), about_more_path, class: 'button button-alternative' diff --git a/app/views/about/_contact.html.haml b/app/views/about/_contact.html.haml deleted file mode 100644 index 3215d50b531..00000000000 --- a/app/views/about/_contact.html.haml +++ /dev/null @@ -1,22 +0,0 @@ -.panel - .panel-header - = succeed ':' do - = t 'about.contact' - - if contact.site_contact_email.present? - = mail_to contact.site_contact_email, nil, title: contact.site_contact_email - - else - %span= t 'about.contact_unavailable' - .panel-body - - if contact.contact_account - .owner - .avatar= image_tag contact.contact_account.avatar.url - .name - = link_to TagManager.instance.url_for(contact.contact_account) do - %span.display_name.emojify= display_name(contact.contact_account, custom_emojify: true) - %span.username @#{contact.contact_account.acct} - - else - .owner - .avatar= image_tag full_asset_url('avatars/original/missing.png', skip_pipeline: true) - .name - %span.display_name= t 'about.contact_missing' - %span.username= t 'about.contact_unavailable' diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index df072b8aec4..9e042ca73dc 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -5,39 +5,41 @@ = javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous' = render partial: 'shared/og' -.landing-page - .header-wrapper.compact - .header - = render 'links' +.grid-3 + .column-0 + .public-account-header.public-account-header--no-bar + .public-account-header__image + = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title, class: 'parallax' - .container-alt.hero - .heading - %h3= t('about.description_headline', domain: site_hostname) - %p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname) + .column-1 + .landing-page__call-to-action{ dir: 'ltr' } + .row + .row__information-board + .information-board__section + %span= t 'about.user_count_before' + %strong= number_with_delimiter @instance_presenter.user_count + %span= t 'about.user_count_after' + .information-board__section + %span= t 'about.status_count_before' + %strong= number_with_delimiter @instance_presenter.status_count + %span= t 'about.status_count_after' + .row__mascot + .landing-page__mascot + = image_tag asset_pack_path('elephant_ui_plane.svg') - .information-board - .container-alt - .information-board__sections - .information-board__section - %span= t 'about.user_count_before' - %strong= number_with_delimiter @instance_presenter.user_count - %span= t 'about.user_count_after' - .information-board__section - %span= t 'about.status_count_before' - %strong= number_with_delimiter @instance_presenter.status_count - %span= t 'about.status_count_after' - .information-board__section - %span= t 'about.domain_count_before' - %strong= number_with_delimiter @instance_presenter.domain_count - %span= t 'about.domain_count_after' - = render 'contact', contact: @instance_presenter + .column-2 + .landing-page__information.contact-widget + %p= t 'about.administered_by' - .extended-description - .container-alt - = @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html') + = account_link_to(@instance_presenter.contact_account) - .footer-links - .container-alt - %p - = link_to t('about.source_code'), @instance_presenter.source_url - = " (#{@instance_presenter.version_number})" + - if @instance_presenter.site_contact_email.present? + %p.contact-widget__mail + = succeed ':' do + = t 'about.contact' + %br/ + = mail_to @instance_presenter.site_contact_email, nil, title: @instance_presenter.site_contact_email + + .column-3 + .box-widget + .rich-formatting= @instance_presenter.site_extended_description.html_safe.presence || t('about.extended_description_html') diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index fba46d54b74..8a40b97ccb7 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -110,7 +110,7 @@ %p= t 'about.about_mastodon_html' %div.contact %h3= t 'about.administered_by' - = render 'administration' + = account_link_to(@instance_presenter.contact_account, link_to(t('about.learn_more'), about_more_path, class: 'button button-alternative')) = render 'features' @@ -131,7 +131,7 @@ %p= t 'about.about_mastodon_html' %div.contact %h3= t 'about.administered_by' - = render 'administration' + = account_link_to(@instance_presenter.contact_account, link_to(t('about.learn_more'), about_more_path, class: 'button button-alternative')) = render 'features' diff --git a/app/views/about/terms.html.haml b/app/views/about/terms.html.haml index c7d36ed47a8..9d076a91b41 100644 --- a/app/views/about/terms.html.haml +++ b/app/views/about/terms.html.haml @@ -1,11 +1,9 @@ - content_for :page_title do = t('terms.title', instance: site_hostname) -.landing-page - .header-wrapper.compact - .header - = render 'links' - - .extended-description - .container-alt - = @instance_presenter.site_terms.html_safe.presence || t('terms.body_html') +.grid + .column-0 + .box-widget + .rich-formatting= @instance_presenter.site_terms.html_safe.presence || t('terms.body_html') + .column-1 + = render 'application/sidebar' diff --git a/config/locales/ar.yml b/config/locales/ar.yml index d40ae0f7231..c2d7dc75e20 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -9,9 +9,6 @@ ar: contact: للتواصل معنا contact_missing: غير محدد contact_unavailable: غير متوفر - description_headline: ما هو %{domain}? - domain_count_after: خوادم أخرى - domain_count_before: متصل بـ extended_description_html: |

مكان جيد للقواعد

لا يوجد تفصيل طويل حتى الآن.

diff --git a/config/locales/ast.yml b/config/locales/ast.yml index 3dae9cc1a09..65620a7c47b 100644 --- a/config/locales/ast.yml +++ b/config/locales/ast.yml @@ -3,8 +3,6 @@ ast: about: about_mastodon_html: Mastodon ye una rede social basada en protocolos abiertos y software de códigu llibre. Ye descentralizada, como'l corréu electrónicu. contact_unavailable: N/D - description_headline: "¿Qué ye %{domain}?" - domain_count_after: otres instancies features: not_a_product_title: Yes una persona, non un productu source_code: Códigu fonte diff --git a/config/locales/bg.yml b/config/locales/bg.yml index f101101e236..8c11ac7b76c 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -5,9 +5,6 @@ bg: about_this: За тази инстанция closed_registrations: В момента регистрациите за тази инстанция са затворени. contact: За контакти - description_headline: Какво е %{domain}? - domain_count_after: други инстанции - domain_count_before: Свързани към other_instances: Други инстанции source_code: Програмен код status_count_after: публикации diff --git a/config/locales/ca.yml b/config/locales/ca.yml index ea8a5712b23..41c35e79bf7 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -9,9 +9,6 @@ ca: contact: Contacte contact_missing: No configurat contact_unavailable: N/D - description_headline: Què es %{domain}? - domain_count_after: altres instàncies - domain_count_before: Connectada a extended_description_html: |

Un bon lloc per les regles

Encara no s'ha configurat la descripció ampliada.

diff --git a/config/locales/co.yml b/config/locales/co.yml index 4326dde67ff..09d470c9717 100644 --- a/config/locales/co.yml +++ b/config/locales/co.yml @@ -9,9 +9,6 @@ co: contact: Cuntattu contact_missing: Mancante contact_unavailable: Micca dispunibule - description_headline: Quale hè %{domain} ? - domain_count_after: altre istanze - domain_count_before: Cunnettati à extended_description_html: |

Una bona piazza per e regule

A descrizzione stesa ùn hè micca stata riempiuta.

diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 6529992dcb9..27bc793ed92 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -9,9 +9,6 @@ cs: contact: Kontakt contact_missing: Nenastaveno contact_unavailable: Neuvedeno - description_headline: Co je %{domain}? - domain_count_after: dalším instancím - domain_count_before: Připojeno k extended_description_html: |

Dobré místo pro pravidla

Rozšířený popis ještě nebyl nastaven.

diff --git a/config/locales/da.yml b/config/locales/da.yml index 4c7f0f55043..2b6207de689 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -9,9 +9,6 @@ da: contact: Kontakt contact_missing: Ikke sat contact_unavailable: Ikke tilgængeligt - description_headline: Hvad er %{domain}? - domain_count_after: andre instanser - domain_count_before: Forbundet til extended_description_html: |

Et godt sted for regler

Den udvidede beskrivelse er endnu ikke blevet opsat.

diff --git a/config/locales/de.yml b/config/locales/de.yml index a7e3c6ffe4e..24ee095be1a 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -9,9 +9,6 @@ de: contact: Kontakt contact_missing: Nicht angegeben contact_unavailable: N/A - description_headline: Was ist %{domain}? - domain_count_after: anderen Instanzen - domain_count_before: Vernetzt mit extended_description_html: |

Ein guter Platz für Regeln

Die erweiterte Beschreibung wurde noch nicht aufgesetzt.

diff --git a/config/locales/el.yml b/config/locales/el.yml index 90556431713..674712d9848 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -9,9 +9,6 @@ el: contact: Επικοινωνία contact_missing: Δεν έχει οριστεί contact_unavailable: Μ/Δ - description_headline: Τι είναι το %{domain}; - domain_count_after: άλλους διακομιστές - domain_count_before: Συνδέεται με extended_description_html: |

Ένα καλό σημείο για κανόνες

Η αναλυτική περιγραφή δεν έχει ακόμα οριστεί

diff --git a/config/locales/en.yml b/config/locales/en.yml index ef5b2c93bd7..a5e4ab75d68 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -10,10 +10,7 @@ en: contact: Contact contact_missing: Not set contact_unavailable: N/A - description_headline: What is %{domain}? documentation: Documentation - domain_count_after: other instances - domain_count_before: Connected to extended_description_html: |

A good place for rules

The extended description has not been set up yet.

diff --git a/config/locales/eo.yml b/config/locales/eo.yml index 72010a085ca..788fd5f5247 100644 --- a/config/locales/eo.yml +++ b/config/locales/eo.yml @@ -9,9 +9,6 @@ eo: contact: Kontakti contact_missing: Ne elektita contact_unavailable: Ne disponebla - description_headline: Kio estas %{domain}? - domain_count_after: aliaj nodoj - domain_count_before: Konektita al extended_description_html: |

Bona loko por reguloj

La detala priskribo ne estis elektita.

diff --git a/config/locales/es.yml b/config/locales/es.yml index 3aae7f93474..ca04f0b1c61 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -9,9 +9,6 @@ es: contact: Contacto contact_missing: No especificado contact_unavailable: N/A - description_headline: "¿Qué es %{domain}?" - domain_count_after: otras instancias - domain_count_before: Conectado a extended_description_html: |

Un buen lugar para las reglas

La descripción extendida no se ha colocado aún.

diff --git a/config/locales/eu.yml b/config/locales/eu.yml index c11e0590855..7b70ca77e40 100644 --- a/config/locales/eu.yml +++ b/config/locales/eu.yml @@ -9,9 +9,6 @@ eu: contact: Kontaktua contact_missing: Ezarri gabe contact_unavailable: E/E - description_headline: Zer da %{domain}? - domain_count_after: instantzia desberdinetara - domain_count_before: Konektatuta extended_description_html: |

Arauentzako toki egoki bat

Azalpen luzea ez da ezarri oraindik.

diff --git a/config/locales/fa.yml b/config/locales/fa.yml index b4dc3fd8a91..25d1e81abb7 100644 --- a/config/locales/fa.yml +++ b/config/locales/fa.yml @@ -9,9 +9,6 @@ fa: contact: تماس contact_missing: تعیین نشده contact_unavailable: موجود نیست - description_headline: "%{domain} چیست؟" - domain_count_after: سرور دیگر - domain_count_before: متصل به extended_description_html: |

جای خوبی برای قانون‌ها

توضیحات تکمیلی نوشته نشده است.

diff --git a/config/locales/fi.yml b/config/locales/fi.yml index 2c534f0712f..7fa2bc8de17 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -9,9 +9,6 @@ fi: contact: Ota yhteyttä contact_missing: Ei asetettu contact_unavailable: Ei saatavilla - description_headline: Mikä on %{domain}? - domain_count_after: muuhun instanssiin - domain_count_before: Yhdistyneenä extended_description_html: |

Hyvä paikka säännöille

Pidempää kuvausta ei ole vielä laadittu.

diff --git a/config/locales/fr.yml b/config/locales/fr.yml index a4f2758e015..2eb1ba0ce16 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -9,9 +9,6 @@ fr: contact: Contact contact_missing: Manquant contact_unavailable: Non disponible - description_headline: Qu’est-ce que %{domain} ? - domain_count_after: autres instances - domain_count_before: Connecté⋅e⋅s à extended_description_html: |

Un bon endroit pour les règles

La description étendue n’a pas été remplie.

diff --git a/config/locales/gl.yml b/config/locales/gl.yml index a5732168b29..92b71cce64c 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -9,9 +9,6 @@ gl: contact: Contacto contact_missing: Non establecido contact_unavailable: N/A - description_headline: Qué é %{domain}? - domain_count_after: outras instancias - domain_count_before: Conectada a extended_description_html: |

Un bo lugar para regras

A descrición extendida aínda non se proporcionou.

diff --git a/config/locales/he.yml b/config/locales/he.yml index b03f184caad..e3bb6436434 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -8,9 +8,6 @@ he: contact: צור קשר contact_missing: אין contact_unavailable: לא רלוונטי/חסר - description_headline: מהו %{domain}? - domain_count_after: שרתים אחרים - domain_count_before: מחובר אל extended_description_html: |

מקום טוב לכללים

התיאור המורחב טרם הוגדר.

diff --git a/config/locales/hr.yml b/config/locales/hr.yml index 07373d19dab..a6e7649f20d 100644 --- a/config/locales/hr.yml +++ b/config/locales/hr.yml @@ -5,9 +5,6 @@ hr: about_this: O ovoj instanci closed_registrations: Registracije na ovoj instanci su trenutno zatvorene. contact: Kontakt - description_headline: Što je %{domain}? - domain_count_after: druge instance - domain_count_before: Spojen na other_instances: Druge instance source_code: Izvorni kod status_count_after: statusi diff --git a/config/locales/hu.yml b/config/locales/hu.yml index af10dfd8015..824a460669e 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -8,9 +8,6 @@ hu: contact: Kapcsolat contact_missing: Nincs megadva contact_unavailable: N/A - description_headline: Mi az a %{domain}? - domain_count_after: további instanciával - domain_count_before: Kapcsolatban extended_description_html: |

Ez itt a szabályzat helye

Még nem állítottál be bővebb leírást.

diff --git a/config/locales/id.yml b/config/locales/id.yml index c391a6b4ea9..33a764a2822 100644 --- a/config/locales/id.yml +++ b/config/locales/id.yml @@ -5,9 +5,6 @@ id: about_this: Tentang server ini closed_registrations: Pendaftaran untuk server ini sedang ditutup. contact: Kontak - description_headline: Apa itu %{domain}? - domain_count_after: server lain - domain_count_before: Terhubung dengan other_instances: Server lain source_code: Kode sumber status_count_after: status diff --git a/config/locales/io.yml b/config/locales/io.yml index 71a7f2d94ef..287c1d0e640 100644 --- a/config/locales/io.yml +++ b/config/locales/io.yml @@ -5,9 +5,6 @@ io: about_this: Pri ta instaluro closed_registrations: Membresko ne nun esas posible en ta instaluro. contact: Kontaktar - description_headline: Quo esas %{domain}? - domain_count_after: altra instaluri - domain_count_before: Konektita ad other_instances: Altra instaluri source_code: Fontkodexo status_count_after: mesaji diff --git a/config/locales/it.yml b/config/locales/it.yml index e985d1f109f..0f25dd23143 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -9,9 +9,6 @@ it: contact: Contatti contact_missing: Non impostato contact_unavailable: N/D - description_headline: Cos'è %{domain}? - domain_count_after: altri server - domain_count_before: Connesso a extended_description_html: |

Un buon posto per le regole

La descrizione estesa non è ancora stata preparata.

diff --git a/config/locales/ja.yml b/config/locales/ja.yml index d9503a141f8..69c7d33674c 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -9,9 +9,6 @@ ja: contact: 連絡先 contact_missing: 未設定 contact_unavailable: N/A - description_headline: "%{domain} とは?" - domain_count_after: 個のインスタンス - domain_count_before: 接続中 extended_description_html: |

ルールを書くのに適した場所

詳細説明が設定されていません。

diff --git a/config/locales/ko.yml b/config/locales/ko.yml index 00b3b249d4d..d328ae4e75a 100644 --- a/config/locales/ko.yml +++ b/config/locales/ko.yml @@ -9,9 +9,6 @@ ko: contact: 연락처 contact_missing: 미설정 contact_unavailable: N/A - description_headline: "%{domain} (은)는 무엇인가요?" - domain_count_after: 개의 인스턴스 - domain_count_before: 연결된 extended_description_html: |

룰을 작성하는 장소

아직 설명이 작성되지 않았습니다.

diff --git a/config/locales/nl.yml b/config/locales/nl.yml index 0001891b244..112b5d5feae 100644 --- a/config/locales/nl.yml +++ b/config/locales/nl.yml @@ -9,9 +9,6 @@ nl: contact: Contact contact_missing: Niet ingesteld contact_unavailable: n.v.t - description_headline: Wat is %{domain}? - domain_count_after: andere servers - domain_count_before: Verbonden met extended_description_html: |

Een goede plek voor richtlijnen

De uitgebreide omschrijving is nog niet ingevuld.

diff --git a/config/locales/no.yml b/config/locales/no.yml index c17ea3e862c..bcf3966d489 100644 --- a/config/locales/no.yml +++ b/config/locales/no.yml @@ -8,9 +8,6 @@ contact: Kontakt contact_missing: Ikke innstilt contact_unavailable: Ikke tilgjengelig - description_headline: Hva er %{domain}? - domain_count_after: andre instanser - domain_count_before: Koblet til extended_description_html: |

En god plassering for regler

En utvidet beskrivelse er ikke satt opp ennå.

diff --git a/config/locales/oc.yml b/config/locales/oc.yml index 828ecfbf5bb..3ff2dae66b2 100644 --- a/config/locales/oc.yml +++ b/config/locales/oc.yml @@ -9,9 +9,6 @@ oc: contact: Contacte contact_missing: Pas parametrat contact_unavailable: Pas disponible - description_headline: Qué es %{domain} ? - domain_count_after: autras instàncias - domain_count_before: Connectat a extended_description_html: |

Una bona plaça per las règlas

La descripcion longa es pas estada causida pel moment.

diff --git a/config/locales/pl.yml b/config/locales/pl.yml index 4407fd5480c..fb5c51c5e40 100644 --- a/config/locales/pl.yml +++ b/config/locales/pl.yml @@ -10,10 +10,7 @@ pl: contact: Kontakt contact_missing: Nie ustawiono contact_unavailable: Nie dotyczy - description_headline: Czym jest %{domain}? documentation: Dokumentacja - domain_count_after: instancjami - domain_count_before: Serwer połączony z extended_description_html: |

Dobre miejsce na zasady użytkowania

Nie ustawiono jeszcze szczegółowego opisu

diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 0c1cc6a6dd2..9aedd375ce7 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -9,9 +9,6 @@ pt-BR: contact: Contato contact_missing: Não definido contact_unavailable: N/A - description_headline: O que é %{domain}? - domain_count_after: outras instâncias - domain_count_before: Conectado a extended_description_html: |

Um bom lugar para regras

A descrição da instância ainda não foi feita.

diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 33b6b0acb78..eebeb498e9a 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -8,9 +8,6 @@ pt: contact: Contacto contact_missing: Não configurado contact_unavailable: n.d. - description_headline: O que é o %{domain}? - domain_count_after: outras instâncias - domain_count_before: Ligado a extended_description_html: |

Um bom lugar para regras

A descrição estendida ainda não foi configurada.

diff --git a/config/locales/ru.yml b/config/locales/ru.yml index f3184e238c1..9d41e20ff35 100644 --- a/config/locales/ru.yml +++ b/config/locales/ru.yml @@ -9,9 +9,6 @@ ru: contact: Связаться contact_missing: Не установлено contact_unavailable: Недоступен - description_headline: Что такое %{domain}? - domain_count_after: другими узлами - domain_count_before: Связан с extended_description_html: |

Хорошее место для правил

Расширенное описание еще не настроено.

diff --git a/config/locales/sk.yml b/config/locales/sk.yml index 0c86f5aa02c..1be11baa499 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -9,9 +9,6 @@ sk: contact: Kontakt contact_missing: Nezadané contact_unavailable: Neuvedené - description_headline: Čo je %{domain}? - domain_count_after: ďalším instanciám - domain_count_before: Pripojený k extended_description_html: |

Pravidlá

Žiadne zatiaľ nie sú

diff --git a/config/locales/sl.yml b/config/locales/sl.yml index 16ace08d37e..f7ef654232b 100644 --- a/config/locales/sl.yml +++ b/config/locales/sl.yml @@ -9,9 +9,6 @@ sl: contact: Kontakt contact_missing: Ni nastavljeno contact_unavailable: Ni na voljo - description_headline: Kaj je %{domain}? - domain_count_after: ostala vozlišča - domain_count_before: Povezan z extended_description_html: |

Dober prostor za pravila

Razširjen opis še ni bil nastavljen.

diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml index d7dd574c724..d9813db4743 100644 --- a/config/locales/sr-Latn.yml +++ b/config/locales/sr-Latn.yml @@ -8,9 +8,6 @@ sr-Latn: contact: Kontakt contact_missing: Nije postavljeno contact_unavailable: N/A - description_headline: Šta je %{domain}? - domain_count_after: ostale instance - domain_count_before: Povezan na extended_description_html: |

Dobro mesto za pravila

Prošireni opis koji još nije postavljen.

diff --git a/config/locales/sr.yml b/config/locales/sr.yml index 63c42f62fc5..61c0b123cbf 100644 --- a/config/locales/sr.yml +++ b/config/locales/sr.yml @@ -9,9 +9,6 @@ sr: contact: Контакт contact_missing: Није постављено contact_unavailable: N/A - description_headline: Шта је %{domain}? - domain_count_after: остале инстанце - domain_count_before: Повезан на extended_description_html: |

Добро место за правила

Проширени опис који још није постављен.

diff --git a/config/locales/sv.yml b/config/locales/sv.yml index cf1ab582f5c..605d9db12f6 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -9,9 +9,6 @@ sv: contact: Kontakt contact_missing: Inte inställd contact_unavailable: N/A - description_headline: Vad är %{domain}? - domain_count_after: andra instanser - domain_count_before: Uppkopplad mot extended_description_html: |

En bra plats för regler

Den utökade beskrivningen har inte konfigurerats ännu.

diff --git a/config/locales/th.yml b/config/locales/th.yml index 182bde38832..88e1eb44c30 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -5,9 +5,6 @@ th: about_this: เกี่ยวกับอินซะแตนซ์นี้ closed_registrations: อินซะแตนซ์นี้ปิดรับลงทะเบียนแล้ว. contact: ติดต่อ - description_headline: โดเมนคือ %{domain} ? - domain_count_after: อินซะแตนซ์อื่นๆ - domain_count_before: เชื่อมต่อกับ other_instances: อินซะแตนซ์อื่นๆ source_code: ซอร์สโค๊ด status_count_after: สถานะ diff --git a/config/locales/tr.yml b/config/locales/tr.yml index 3609261ed68..26dd4c1e304 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -5,9 +5,6 @@ tr: about_this: Bu sunucu hakkında closed_registrations: Bu sunucu şu anda yeni kayıt almamaktadır. contact: İletişim - description_headline: Peki %{domain} nedir? - domain_count_after: sunucu var. - domain_count_before: Bağlı olduğu other_instances: Diğer sunucular source_code: Kaynak kodu status_count_after: adet gönderi yazıldı. diff --git a/config/locales/uk.yml b/config/locales/uk.yml index 266c878f1b8..1380635eb12 100644 --- a/config/locales/uk.yml +++ b/config/locales/uk.yml @@ -7,9 +7,6 @@ uk: closed_registrations: На даний момент реєстрація на цій інстанції закрита. contact: Зв'язатися contact_missing: Не зазначено - description_headline: Що таке %{domain}? - domain_count_after: іншими інстанціями - domain_count_before: Зв'язаний з features: humane_approach_title: Більш людський підхід real_conversation_title: Побудований для справжньої розмови diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index 6e64aff5aa2..b2f9fd01e7e 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -9,9 +9,6 @@ zh-CN: contact: 联系方式 contact_missing: 未设定 contact_unavailable: 未公开 - description_headline: 关于 %{domain} - domain_count_after: 个其它实例 - domain_count_before: 现已接入 extended_description_html: |

这里可以写一些规定

本站尚未设置详细介绍。

diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml index 7ff0d7ae641..ee7ca444339 100644 --- a/config/locales/zh-HK.yml +++ b/config/locales/zh-HK.yml @@ -9,9 +9,6 @@ zh-HK: contact: 聯絡 contact_missing: 未設定 contact_unavailable: 未公開 - description_headline: 甚麼是 %{domain} ? - domain_count_after: 個其他服務站 - domain_count_before: 已連接至 extended_description_html: |

這裡可以寫一些網站規則

本站未有詳細介紹

diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index 483cffe8e00..0a18dc9909e 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -9,9 +9,6 @@ zh-TW: contact: 聯絡我們 contact_missing: 未設定 contact_unavailable: 未公開 - description_headline: 關於 %{domain}? - domain_count_after: 個站點相連 - domain_count_before: 與其他 extended_description_html: |

這裡可以寫一些網站規則

本站點未有詳細介紹

diff --git a/spec/views/about/_contact.html.haml_spec.rb b/spec/views/about/_contact.html.haml_spec.rb deleted file mode 100644 index 25ba1579464..00000000000 --- a/spec/views/about/_contact.html.haml_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -describe 'about/_contact.html.haml' do - describe 'the contact account', without_verify_partial_doubles: true do - before do - allow(view).to receive(:display_name).and_return('Display Name!') - end - - it 'shows info when account is present' do - account = Account.new(username: 'admin') - contact = double(contact_account: account, site_contact_email: '') - render 'about/contact', contact: contact - - expect(rendered).to have_content('@admin') - end - - it 'does not show info when account is missing' do - contact = double(contact_account: nil, site_contact_email: '') - render 'about/contact', contact: contact - - expect(rendered).not_to have_content('@') - end - end - - describe 'the contact email' do - it 'show info when email is present' do - contact = double(site_contact_email: 'admin@example.com', contact_account: nil) - render 'about/contact', contact: contact - - expect(rendered).to have_content('admin@example.com') - end - end -end From aff6a15061de203842653d680047322277dc7af6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 9 Aug 2018 15:24:29 +0200 Subject: [PATCH 10/16] When follow is removed, remove endorsement (#8149) --- app/models/follow.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/follow.rb b/app/models/follow.rb index eaf8445f3bf..3fce14b9ac5 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -33,10 +33,15 @@ class Follow < ApplicationRecord end before_validation :set_uri, only: :create + after_destroy :remove_endorsements private def set_uri self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil? end + + def remove_endorsements + AccountPin.where(target_account_id: target_account_id, account_id: account_id).delete_all + end end From 8c279b1648fc0a07b5c5d4a0e18526bcb51c7700 Mon Sep 17 00:00:00 2001 From: Aaron Brady Date: Thu, 9 Aug 2018 16:37:48 -0400 Subject: [PATCH 11/16] Update docker-compose to cope with build-time assets (#8156) #7780 means that asset compilation happens as a build step. Having the assets and packs volumes defined in `docker-compose.yml` breaks this. For people who run under Docker Compose, I believe this will fix their CSS (which even running the asset recompilation separately did not). --- docker-compose.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index c54c73e44a0..3b50f6d31c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -46,8 +46,6 @@ services: - redis # - es volumes: - - ./public/assets:/mastodon/public/assets - - ./public/packs:/mastodon/public/packs - ./public/system:/mastodon/public/system streaming: @@ -78,7 +76,6 @@ services: - external_network - internal_network volumes: - - ./public/packs:/mastodon/public/packs - ./public/system:/mastodon/public/system ## Uncomment to enable federation with tor instances along with adding the following ENV variables ## http_proxy=http://privoxy:8118 From 5b8603879f06573d51c5c33edda6f410d1af7a02 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 10 Aug 2018 06:43:02 +0200 Subject: [PATCH 12/16] Adjust responsive design for /about/more and /terms (#8158) Follow-up to #8142 --- app/javascript/styles/mastodon/about.scss | 11 ++++ .../styles/mastodon/containers.scss | 53 +++++++++++++++++++ app/javascript/styles/mastodon/widgets.scss | 11 +++- app/views/about/more.html.haml | 8 +-- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index bba7044cf3b..228dd96f0de 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -790,8 +790,10 @@ $small-breakpoint: 960px; border-radius: 4px; padding: 25px 40px; overflow: hidden; + box-sizing: border-box; .row { + width: 100%; display: flex; flex-direction: row-reverse; flex-wrap: wrap; @@ -808,11 +810,20 @@ $small-breakpoint: 960px; flex: 1 0 auto; padding: 0 10px; } + + @media screen and (max-width: $no-gap-breakpoint) { + width: 100%; + justify-content: space-between; + } } .row__mascot { flex: 1; margin: 10px -50px 0 0; + + @media screen and (max-width: $no-gap-breakpoint) { + display: none; + } } } diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index ba36d62d97e..8ecedd2cb7f 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -141,6 +141,55 @@ grid-column: 1/3; grid-row: 3; } + + .landing-page__call-to-action { + min-height: 100%; + } + + @media screen and (max-width: 738px) { + grid-template-columns: minmax(0, 50%) minmax(0, 50%); + + .landing-page__call-to-action { + padding: 20px; + display: flex; + align-items: center; + justify-content: center; + } + + .row__information-board { + width: 100%; + justify-content: center; + align-items: center; + } + + .row__mascot { + display: none; + } + } + + @media screen and (max-width: $no-gap-breakpoint) { + grid-gap: 0; + grid-template-columns: minmax(0, 100%); + + .column-0 { + grid-column: 1; + } + + .column-1 { + grid-column: 1; + grid-row: 3; + } + + .column-2 { + grid-column: 1; + grid-row: 2; + } + + .column-3 { + grid-column: 1; + grid-row: 4; + } + } } .public-layout { @@ -334,6 +383,10 @@ .public-account-header__image, .public-account-header__image img { border-radius: 4px; + + @media screen and (max-width: $no-gap-breakpoint) { + border-radius: 0; + } } } diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index 875a369594f..f843f0b42b5 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -114,7 +114,7 @@ .landing-page__information.contact-widget { box-sizing: border-box; padding: 20px; - height: 100%; + min-height: 100%; border-radius: 4px; background: $ui-base-color; box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); @@ -127,6 +127,10 @@ word-wrap: break-word; font-weight: 400; + strong { + font-weight: 500; + } + p { margin-bottom: 10px; @@ -226,7 +230,10 @@ } .moved-account-widget, -.memoriam-widget { +.memoriam-widget, +.box-widget, +.contact-widget, +.landing-page__information.contact-widget { @media screen and (max-width: $no-gap-breakpoint) { margin-bottom: 0; box-shadow: none; diff --git a/app/views/about/more.html.haml b/app/views/about/more.html.haml index 9e042ca73dc..8411cd276d2 100644 --- a/app/views/about/more.html.haml +++ b/app/views/about/more.html.haml @@ -29,14 +29,16 @@ .column-2 .landing-page__information.contact-widget - %p= t 'about.administered_by' + %p + %strong= t 'about.administered_by' = account_link_to(@instance_presenter.contact_account) - if @instance_presenter.site_contact_email.present? %p.contact-widget__mail - = succeed ':' do - = t 'about.contact' + %strong + = succeed ':' do + = t 'about.contact' %br/ = mail_to @instance_presenter.site_contact_email, nil, title: @instance_presenter.site_contact_email From 90b492143dae5cbaf884b12fbfd823c9f65d392f Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 10 Aug 2018 15:22:04 +0200 Subject: [PATCH 13/16] Introduce OAuth scopes for bookmarks --- app/controllers/api/v1/bookmarks_controller.rb | 2 +- app/controllers/api/v1/statuses/bookmarks_controller.rb | 2 +- config/initializers/doorkeeper.rb | 2 ++ config/locales/doorkeeper.en.yml | 2 ++ spec/controllers/api/v1/bookmarks_controller_spec.rb | 2 +- spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb | 2 +- 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb index 49038807db7..1cab3c372e7 100644 --- a/app/controllers/api/v1/bookmarks_controller.rb +++ b/app/controllers/api/v1/bookmarks_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Api::V1::BookmarksController < Api::BaseController - before_action -> { doorkeeper_authorize! :read } + before_action -> { doorkeeper_authorize! :read, :'read:bookmarks' } before_action :require_user! after_action :insert_pagination_headers diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb index d7def5f1f81..bb9729cf50f 100644 --- a/app/controllers/api/v1/statuses/bookmarks_controller.rb +++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb @@ -3,7 +3,7 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController include Authorization - before_action -> { doorkeeper_authorize! :write } + before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' } before_action :require_user! respond_to :json diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index fe2490b326a..c77387ed467 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -58,6 +58,7 @@ Doorkeeper.configure do optional_scopes :write, :'write:accounts', :'write:blocks', + :'write:bookmarks', :'write:favourites', :'write:filters', :'write:follows', @@ -70,6 +71,7 @@ Doorkeeper.configure do :read, :'read:accounts', :'read:blocks', + :'read:bookmarks', :'read:favourites', :'read:filters', :'read:follows', diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml index f1fe03716a1..211b210d7e6 100644 --- a/config/locales/doorkeeper.en.yml +++ b/config/locales/doorkeeper.en.yml @@ -119,6 +119,7 @@ en: read: read all your account's data read:accounts: see accounts information read:blocks: see your blocks + read:bookmarks: see your bookmarks read:favourites: see your favourites read:filters: see your filters read:follows: see your follows @@ -131,6 +132,7 @@ en: write: modify all your account's data write:accounts: modify your profile write:blocks: block accounts and domains + write:bookmarks: bookmark statuses write:favourites: favourite statuses write:filters: create filters write:follows: follow people diff --git a/spec/controllers/api/v1/bookmarks_controller_spec.rb b/spec/controllers/api/v1/bookmarks_controller_spec.rb index 26130e71bf5..79601b6e623 100644 --- a/spec/controllers/api/v1/bookmarks_controller_spec.rb +++ b/spec/controllers/api/v1/bookmarks_controller_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Api::V1::BookmarksController, type: :controller do render_views let(:user) { Fabricate(:user) } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read') } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:bookmarks') } describe 'GET #index' do context 'without token' do diff --git a/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb b/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb index d881e22ed1f..b79853718d1 100644 --- a/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb +++ b/spec/controllers/api/v1/statuses/bookmarks_controller_spec.rb @@ -7,7 +7,7 @@ describe Api::V1::Statuses::BookmarksController do let(:user) { Fabricate(:user, account: Fabricate(:account, username: 'alice')) } let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') } - let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write', application: app) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:bookmarks', application: app) } context 'with an oauth token' do before do From 16a4a333a2b4942364abe79e80bcc928bc079bf2 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 10 Aug 2018 15:48:54 +0200 Subject: [PATCH 14/16] Merge upstream styling for public profile endorsements Port the SCSS part of f2404de871f0bdfda5c9aeeeb4c6c4d10a8da8ab to glitch-soc --- .../flavours/glitch/styles/widgets.scss | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/javascript/flavours/glitch/styles/widgets.scss b/app/javascript/flavours/glitch/styles/widgets.scss index d37a6f4587a..b05bbbda7c8 100644 --- a/app/javascript/flavours/glitch/styles/widgets.scss +++ b/app/javascript/flavours/glitch/styles/widgets.scss @@ -71,6 +71,38 @@ } } +.endorsements-widget { + margin-bottom: 10px; + padding-bottom: 10px; + + h4 { + padding: 10px; + text-transform: uppercase; + font-weight: 700; + font-size: 13px; + color: $darker-text-color; + } + + .account { + padding: 10px 0; + + &:last-child { + border-bottom: 0; + } + + .account__display-name { + display: flex; + align-items: center; + } + + .account__avatar { + width: 44px; + height: 44px; + background-size: 44px 44px; + } + } +} + .moved-account-widget { padding: 15px; padding-bottom: 20px; From 4e66e0ac045a45a14670bb9492e2babe0c9bafb7 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 10 Aug 2018 15:57:58 +0200 Subject: [PATCH 15/16] Merge upstream SCSS changes for /about, /about/more and /terms Port various commits to glitch-soc, mainly commits 0dcc1950d14cc4a7725ea1572d253c538a1f74e8 and 5b8603879f06573d51c5c33edda6f410d1af7a02. --- .../flavours/glitch/styles/about.scss | 449 ++++++++++++------ .../flavours/glitch/styles/containers.scss | 90 ++++ .../flavours/glitch/styles/widgets.scss | 51 +- 3 files changed, 447 insertions(+), 143 deletions(-) diff --git a/app/javascript/flavours/glitch/styles/about.scss b/app/javascript/flavours/glitch/styles/about.scss index 74807bb6577..ba46c65c57e 100644 --- a/app/javascript/flavours/glitch/styles/about.scss +++ b/app/javascript/flavours/glitch/styles/about.scss @@ -15,6 +15,278 @@ $small-breakpoint: 960px; } } +.rich-formatting { + font-family: 'mastodon-font-sans-serif', sans-serif; + font-size: 16px; + font-weight: 400; + font-size: 16px; + line-height: 30px; + color: $darker-text-color; + padding-right: 10px; + + a { + color: $highlight-text-color; + text-decoration: underline; + } + + p, + li { + font-family: 'mastodon-font-sans-serif', sans-serif; + font-size: 16px; + font-weight: 400; + font-size: 16px; + line-height: 30px; + margin-bottom: 12px; + color: $darker-text-color; + + a { + color: $highlight-text-color; + text-decoration: underline; + } + + &:last-child { + margin-bottom: 0; + } + } + + em { + display: inline; + margin: 0; + padding: 0; + font-weight: 700; + background: transparent; + font-family: inherit; + font-size: inherit; + line-height: inherit; + color: lighten($darker-text-color, 10%); + } + + h1 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 26px; + line-height: 30px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + + small { + font-family: 'mastodon-font-sans-serif', sans-serif; + display: block; + font-size: 18px; + font-weight: 400; + color: lighten($darker-text-color, 10%); + } + } + + h2 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 22px; + line-height: 26px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h3 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 18px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h4 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h5 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 14px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + h6 { + font-family: 'mastodon-font-display', sans-serif; + font-size: 12px; + line-height: 24px; + font-weight: 500; + margin-bottom: 20px; + color: $secondary-text-color; + } + + ul, + ol { + margin-left: 20px; + + &[type='a'] { + list-style-type: lower-alpha; + } + + &[type='i'] { + list-style-type: lower-roman; + } + } + + ul { + list-style: disc; + } + + ol { + list-style: decimal; + } + + li > ol, + li > ul { + margin-top: 6px; + } + + hr { + width: 100%; + height: 0; + border: 0; + border-bottom: 1px solid rgba($ui-base-lighter-color, .6); + margin: 20px 0; + + &.spacer { + height: 1px; + border: 0; + } + } +} + +.information-board { + background: darken($ui-base-color, 4%); + padding: 20px 0; + + .container-alt { + position: relative; + padding-right: 280px + 15px; + } + + &__sections { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + } + + &__section { + flex: 1 0 0; + font-family: 'mastodon-font-sans-serif', sans-serif; + font-size: 16px; + line-height: 28px; + color: $primary-text-color; + text-align: right; + padding: 10px 15px; + + span, + strong { + display: block; + } + + span { + &:last-child { + color: $secondary-text-color; + } + } + + strong { + font-weight: 500; + font-size: 32px; + line-height: 48px; + } + + @media screen and (max-width: $column-breakpoint) { + text-align: center; + } + } + + .panel { + position: absolute; + width: 280px; + box-sizing: border-box; + background: darken($ui-base-color, 8%); + padding: 20px; + padding-top: 10px; + border-radius: 4px 4px 0 0; + right: 0; + bottom: -40px; + + .panel-header { + font-family: 'mastodon-font-display', sans-serif; + font-size: 14px; + line-height: 24px; + font-weight: 500; + color: $darker-text-color; + padding-bottom: 5px; + margin-bottom: 15px; + border-bottom: 1px solid lighten($ui-base-color, 4%); + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + + a, + span { + font-weight: 400; + color: darken($darker-text-color, 10%); + } + + a { + text-decoration: none; + } + } + } + + .owner { + text-align: center; + + .avatar { + width: 80px; + height: 80px; + @include avatar-size(80px); + margin: 0 auto; + margin-bottom: 15px; + + img { + display: block; + width: 80px; + height: 80px; + border-radius: 48px; + @include avatar-radius(); + } + } + + .name { + font-size: 14px; + + a { + display: block; + color: $primary-text-color; + text-decoration: none; + + &:hover { + .display_name { + text-decoration: underline; + } + } + } + + .username { + display: block; + color: $darker-text-color; + } + } + } +} + .landing-page { .grid { display: grid; @@ -396,7 +668,7 @@ $small-breakpoint: 960px; display: flex; justify-content: center; align-items: center; - color: $ui-primary-color; + color: $darker-text-color; text-decoration: none; padding: 12px 16px; line-height: 32px; @@ -486,130 +758,6 @@ $small-breakpoint: 960px; } } - .information-board { - background: darken($ui-base-color, 4%); - padding: 20px 0; - - .container-alt { - position: relative; - padding-right: 280px + 15px; - } - - &__sections { - display: flex; - justify-content: space-between; - flex-wrap: wrap; - } - - &__section { - flex: 1 0 0; - font-family: 'mastodon-font-sans-serif', sans-serif; - font-size: 16px; - line-height: 28px; - color: $primary-text-color; - text-align: right; - padding: 10px 15px; - - span, - strong { - display: block; - } - - span { - &:last-child { - color: $secondary-text-color; - } - } - - strong { - font-weight: 500; - font-size: 32px; - line-height: 48px; - } - - @media screen and (max-width: $column-breakpoint) { - text-align: center; - } - } - - .panel { - position: absolute; - width: 280px; - box-sizing: border-box; - background: darken($ui-base-color, 8%); - padding: 20px; - padding-top: 10px; - border-radius: 4px 4px 0 0; - right: 0; - bottom: -40px; - - .panel-header { - font-family: 'mastodon-font-display', sans-serif; - font-size: 14px; - line-height: 24px; - font-weight: 500; - color: $darker-text-color; - padding-bottom: 5px; - margin-bottom: 15px; - border-bottom: 1px solid lighten($ui-base-color, 4%); - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - - a, - span { - font-weight: 400; - color: darken($darker-text-color, 10%); - } - - a { - text-decoration: none; - } - } - } - - .owner { - text-align: center; - - .avatar { - width: 80px; - height: 80px; - @include avatar-size(80px); - margin: 0 auto; - margin-bottom: 15px; - - img { - display: block; - width: 80px; - height: 80px; - border-radius: 48px; - @include avatar-radius(); - } - } - - .name { - font-size: 14px; - - a { - display: block; - color: $primary-text-color; - text-decoration: none; - - &:hover { - .display_name { - text-decoration: underline; - } - } - } - - .username { - display: block; - color: $darker-text-color; - } - } - } - } - &.alternative { padding: 10px 0; @@ -644,8 +792,10 @@ $small-breakpoint: 960px; border-radius: 4px; padding: 25px 40px; overflow: hidden; + box-sizing: border-box; .row { + width: 100%; display: flex; flex-direction: row-reverse; flex-wrap: wrap; @@ -662,11 +812,20 @@ $small-breakpoint: 960px; flex: 1 0 auto; padding: 0 10px; } + + @media screen and (max-width: $no-gap-breakpoint) { + width: 100%; + justify-content: space-between; + } } .row__mascot { flex: 1; margin: 10px -50px 0 0; + + @media screen and (max-width: $no-gap-breakpoint) { + display: none; + } } } @@ -718,8 +877,8 @@ $small-breakpoint: 960px; &__avatar { width: 44px; height: 44px; - @include avatar-size(48px); background-size: 44px 44px; + @include avatar-size(44px); } .display-name { @@ -904,8 +1063,29 @@ $small-breakpoint: 960px; } } + .attachment-list__list { + margin-left: 0; + list-style: none; + + li { + font-size: inherit; + line-height: inherit; + font-weight: inherit; + margin-bottom: 0; + + a { + color: $dark-text-color; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + } + @media screen and (max-width: $column-breakpoint) { - height: 90vh; + display: none; } } @@ -965,21 +1145,6 @@ $small-breakpoint: 960px; } } - .extended-description { - padding: 50px 0; - font-family: 'mastodon-font-sans-serif', sans-serif; - font-size: 16px; - font-weight: 400; - font-size: 16px; - line-height: 30px; - color: $darker-text-color; - - a { - color: $highlight-text-color; - text-decoration: underline; - } - } - .footer-links { padding-bottom: 50px; text-align: right; diff --git a/app/javascript/flavours/glitch/styles/containers.scss b/app/javascript/flavours/glitch/styles/containers.scss index 01c8ebbaf93..b5d79f4d7d5 100644 --- a/app/javascript/flavours/glitch/styles/containers.scss +++ b/app/javascript/flavours/glitch/styles/containers.scss @@ -117,6 +117,83 @@ } } +.grid-3 { + display: grid; + grid-gap: 10px; + grid-template-columns: 3fr 1fr; + grid-auto-columns: 25%; + grid-auto-rows: max-content; + + .column-0 { + grid-column: 1/3; + grid-row: 1; + } + + .column-1 { + grid-column: 1; + grid-row: 2; + } + + .column-2 { + grid-column: 2; + grid-row: 2; + } + + .column-3 { + grid-column: 1/3; + grid-row: 3; + } + + .landing-page__call-to-action { + min-height: 100%; + } + + @media screen and (max-width: 738px) { + grid-template-columns: minmax(0, 50%) minmax(0, 50%); + + .landing-page__call-to-action { + padding: 20px; + display: flex; + align-items: center; + justify-content: center; + } + + .row__information-board { + width: 100%; + justify-content: center; + align-items: center; + } + + .row__mascot { + display: none; + } + } + + @media screen and (max-width: $no-gap-breakpoint) { + grid-gap: 0; + grid-template-columns: minmax(0, 100%); + + .column-0 { + grid-column: 1; + } + + .column-1 { + grid-column: 1; + grid-row: 3; + } + + .column-2 { + grid-column: 1; + grid-row: 2; + } + + .column-3 { + grid-column: 1; + grid-row: 4; + } + } +} + .public-layout { @media screen and (max-width: $no-gap-breakpoint) { padding-top: 48px; @@ -302,6 +379,19 @@ } } + &--no-bar { + margin-bottom: 0; + + .public-account-header__image, + .public-account-header__image img { + border-radius: 4px; + + @media screen and (max-width: $no-gap-breakpoint) { + border-radius: 0; + } + } + } + @media screen and (max-width: $no-gap-breakpoint) { margin-bottom: 0; box-shadow: none; diff --git a/app/javascript/flavours/glitch/styles/widgets.scss b/app/javascript/flavours/glitch/styles/widgets.scss index b05bbbda7c8..f843f0b42b5 100644 --- a/app/javascript/flavours/glitch/styles/widgets.scss +++ b/app/javascript/flavours/glitch/styles/widgets.scss @@ -103,6 +103,52 @@ } } +.box-widget { + padding: 20px; + border-radius: 4px; + background: $ui-base-color; + box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); +} + +.contact-widget, +.landing-page__information.contact-widget { + box-sizing: border-box; + padding: 20px; + min-height: 100%; + border-radius: 4px; + background: $ui-base-color; + box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); +} + +.contact-widget { + font-size: 15px; + color: $darker-text-color; + line-height: 20px; + word-wrap: break-word; + font-weight: 400; + + strong { + font-weight: 500; + } + + p { + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + + &__mail { + margin-top: 10px; + + a { + color: $primary-text-color; + text-decoration: none; + } + } +} + .moved-account-widget { padding: 15px; padding-bottom: 20px; @@ -184,7 +230,10 @@ } .moved-account-widget, -.memoriam-widget { +.memoriam-widget, +.box-widget, +.contact-widget, +.landing-page__information.contact-widget { @media screen and (max-width: $no-gap-breakpoint) { margin-bottom: 0; box-shadow: none; From 7067b64de33f9cd491e97329df266fde5fb49e42 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Fri, 10 Aug 2018 16:25:46 +0200 Subject: [PATCH 16/16] Implement public profile endorsements in glitch-soc Port WebUI changes from f2404de871f0bdfda5c9aeeeb4c6c4d10a8da8ab to glitch-soc --- .../flavours/glitch/actions/accounts.js | 74 +++++++++++++++++++ .../features/account/components/action_bar.js | 6 ++ .../account_timeline/components/header.js | 6 ++ .../containers/header_container.js | 10 +++ .../flavours/glitch/reducers/relationships.js | 4 + 5 files changed, 100 insertions(+) diff --git a/app/javascript/flavours/glitch/actions/accounts.js b/app/javascript/flavours/glitch/actions/accounts.js index 8ab92f9e7ad..d5c4a02f931 100644 --- a/app/javascript/flavours/glitch/actions/accounts.js +++ b/app/javascript/flavours/glitch/actions/accounts.js @@ -28,6 +28,14 @@ export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST'; export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS'; export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL'; +export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST'; +export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS'; +export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL'; + +export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST'; +export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS'; +export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL'; + export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST'; export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS'; export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL'; @@ -659,3 +667,69 @@ export function rejectFollowRequestFail(id, error) { error, }; }; + +export function pinAccount(id) { + return (dispatch, getState) => { + dispatch(pinAccountRequest(id)); + + api(getState).post(`/api/v1/accounts/${id}/pin`).then(response => { + dispatch(pinAccountSuccess(response.data)); + }).catch(error => { + dispatch(pinAccountFail(error)); + }); + }; +}; + +export function unpinAccount(id) { + return (dispatch, getState) => { + dispatch(unpinAccountRequest(id)); + + api(getState).post(`/api/v1/accounts/${id}/unpin`).then(response => { + dispatch(unpinAccountSuccess(response.data)); + }).catch(error => { + dispatch(unpinAccountFail(error)); + }); + }; +}; + +export function pinAccountRequest(id) { + return { + type: ACCOUNT_PIN_REQUEST, + id, + }; +}; + +export function pinAccountSuccess(relationship) { + return { + type: ACCOUNT_PIN_SUCCESS, + relationship, + }; +}; + +export function pinAccountFail(error) { + return { + type: ACCOUNT_PIN_FAIL, + error, + }; +}; + +export function unpinAccountRequest(id) { + return { + type: ACCOUNT_UNPIN_REQUEST, + id, + }; +}; + +export function unpinAccountSuccess(relationship) { + return { + type: ACCOUNT_UNPIN_SUCCESS, + relationship, + }; +}; + +export function unpinAccountFail(error) { + return { + type: ACCOUNT_UNPIN_FAIL, + error, + }; +}; diff --git a/app/javascript/flavours/glitch/features/account/components/action_bar.js b/app/javascript/flavours/glitch/features/account/components/action_bar.js index 4a4d31f29e6..9c80a470bc6 100644 --- a/app/javascript/flavours/glitch/features/account/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/account/components/action_bar.js @@ -23,6 +23,8 @@ const messages = defineMessages({ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, hideReblogs: { id: 'account.hide_reblogs', defaultMessage: 'Hide boosts from @{name}' }, showReblogs: { id: 'account.show_reblogs', defaultMessage: 'Show boosts from @{name}' }, + endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' }, + unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, }); @injectIntl @@ -39,6 +41,7 @@ export default class ActionBar extends React.PureComponent { onMute: PropTypes.func.isRequired, onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, + onEndorseToggle: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; @@ -72,6 +75,9 @@ export default class ActionBar extends React.PureComponent { } else { menu.push({ text: intl.formatMessage(messages.showReblogs, { name: account.get('username') }), action: this.props.onReblogToggle }); } + + menu.push({ text: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), action: this.props.onEndorseToggle }); + menu.push(null); } if (account.getIn(['relationship', 'muting'])) { diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index a1434b8dd2e..89b9be92b6c 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -22,6 +22,7 @@ export default class Header extends ImmutablePureComponent { onMute: PropTypes.func.isRequired, onBlockDomain: PropTypes.func.isRequired, onUnblockDomain: PropTypes.func.isRequired, + onEndorseToggle: PropTypes.func.isRequired, hideTabs: PropTypes.bool, }; @@ -73,6 +74,10 @@ export default class Header extends ImmutablePureComponent { this.props.onUnblockDomain(domain); } + handleEndorseToggle = () => { + this.props.onEndorseToggle(this.props.account); + } + render () { const { account, hideTabs } = this.props; @@ -100,6 +105,7 @@ export default class Header extends ImmutablePureComponent { onMute={this.handleMute} onBlockDomain={this.handleBlockDomain} onUnblockDomain={this.handleUnblockDomain} + onEndorseToggle={this.handleEndorseToggle} /> {!hideTabs && ( diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js index fb0edfa882f..f5f56d85ccd 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js @@ -8,6 +8,8 @@ import { blockAccount, unblockAccount, unmuteAccount, + pinAccount, + unpinAccount, } from 'flavours/glitch/actions/accounts'; import { mentionCompose, @@ -86,6 +88,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onEndorseToggle (account) { + if (account.getIn(['relationship', 'endorsed'])) { + dispatch(unpinAccount(account.get('id'))); + } else { + dispatch(pinAccount(account.get('id'))); + } + }, + onReport (account) { dispatch(initReport(account)); }, diff --git a/app/javascript/flavours/glitch/reducers/relationships.js b/app/javascript/flavours/glitch/reducers/relationships.js index e5ef1d2e3b2..4652bbc14cc 100644 --- a/app/javascript/flavours/glitch/reducers/relationships.js +++ b/app/javascript/flavours/glitch/reducers/relationships.js @@ -5,6 +5,8 @@ import { ACCOUNT_UNBLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS, ACCOUNT_UNMUTE_SUCCESS, + ACCOUNT_PIN_SUCCESS, + ACCOUNT_UNPIN_SUCCESS, RELATIONSHIPS_FETCH_SUCCESS, } from 'flavours/glitch/actions/accounts'; import { @@ -41,6 +43,8 @@ export default function relationships(state = initialState, action) { case ACCOUNT_UNBLOCK_SUCCESS: case ACCOUNT_MUTE_SUCCESS: case ACCOUNT_UNMUTE_SUCCESS: + case ACCOUNT_PIN_SUCCESS: + case ACCOUNT_UNPIN_SUCCESS: return normalizeRelationship(state, action.relationship); case RELATIONSHIPS_FETCH_SUCCESS: return normalizeRelationships(state, action.relationships);