diff options
author | David Yip <yipdw@member.fsf.org> | 2017-09-09 14:28:08 -0500 |
---|---|---|
committer | David Yip <yipdw@member.fsf.org> | 2017-09-09 14:28:08 -0500 |
commit | 514fc908a373306b32b2b6b9fc0d849161d88271 (patch) | |
tree | 0f0028e424b43dcf4a59b21ccc7170dfe883746b /app | |
parent | b9f7bc149b2a6abfbdaee83e6992b617b8bdb18e (diff) | |
parent | 11bddd31ce33b654ef72b00221715e6026486e7c (diff) |
Merge tag 'v1.6.0rc3' into sync/upstream
Diffstat (limited to 'app')
28 files changed, 292 insertions, 174 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 8dad12f11..26ab6636b 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -14,7 +14,7 @@ class AccountsController < ApplicationController return end - @pinned_statuses = cache_collection(@account.pinned_statuses, Status) unless media_requested? + @pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses? @statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id]) @statuses = cache_collection(@statuses, Status) @next_url = next_url unless @statuses.empty? @@ -22,7 +22,7 @@ class AccountsController < ApplicationController format.atom do @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id]) - render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.to_a)) + render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? })) end format.json do @@ -33,6 +33,10 @@ class AccountsController < ApplicationController private + def show_pinned_statuses? + [replies_requested?, media_requested?, params[:max_id].present?, params[:since_id].present?].none? + end + def filtered_statuses default_statuses.tap do |statuses| statuses.merge!(only_media_scope) if media_requested? diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index 5fce505fd..b37910b36 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -26,8 +26,12 @@ class ActivityPub::InboxesController < Api::BaseController end def upgrade_account - return unless signed_request_account.subscribed? - Pubsubhubbub::UnsubscribeWorker.perform_async(signed_request_account.id) + if signed_request_account.ostatus? + signed_request_account.update(last_webfingered_at: nil) + ResolveRemoteAccountWorker.perform_async(signed_request_account.acct) + end + + Pubsubhubbub::UnsubscribeWorker.perform_async(signed_request_account.id) if signed_request_account.subscribed? end def process_payload diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index f621aa245..656cacd8a 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -14,6 +14,16 @@ class Api::V1::AccountsController < Api::BaseController def follow FollowService.new.call(current_user.account, @account.acct) + + unless @account.locked? + relationships = AccountRelationshipsPresenter.new( + [@account.id], + current_user.account_id, + following_map: { @account.id => true }, + requested_map: { @account.id => false } + ) + end + render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships end diff --git a/app/helpers/routing_helper.rb b/app/helpers/routing_helper.rb index 1fbf77ec3..f4693358c 100644 --- a/app/helpers/routing_helper.rb +++ b/app/helpers/routing_helper.rb @@ -12,8 +12,14 @@ module RoutingHelper end def full_asset_url(source, options = {}) - source = ActionController::Base.helpers.asset_url(source, options) unless Rails.configuration.x.use_s3 + source = ActionController::Base.helpers.asset_url(source, options) unless use_storage? URI.join(root_url, source).to_s end + + private + + def use_storage? + Rails.configuration.x.use_s3 || Rails.configuration.x.use_swift + end end diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 1a122dbe5..e47b1e9aa 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -5,6 +5,7 @@ import IntersectionObserverArticle from './intersection_observer_article'; import LoadMore from './load_more'; import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'; import { throttle } from 'lodash'; +import { List as ImmutableList } from 'immutable'; export default class ScrollableList extends PureComponent { @@ -95,7 +96,12 @@ export default class ScrollableList extends PureComponent { getFirstChildKey (props) { const { children } = props; - const firstChild = Array.isArray(children) ? children[0] : children; + let firstChild = children; + if (children instanceof ImmutableList) { + firstChild = children.get(0); + } else if (Array.isArray(children)) { + firstChild = children[0]; + } return firstChild && firstChild.key; } diff --git a/app/javascript/mastodon/components/video_player.js b/app/javascript/mastodon/components/video_player.js index 5f2447c6d..f499e3e01 100644 --- a/app/javascript/mastodon/components/video_player.js +++ b/app/javascript/mastodon/components/video_player.js @@ -149,7 +149,7 @@ export default class VideoPlayer extends React.PureComponent { if (!this.state.visible) { if (sensitive) { return ( - <div role='button' tabIndex='0' style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler' onClick={this.handleVisibility}> + <div role='button' tabIndex='0' style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler__video' onClick={this.handleVisibility}> {spoilerButton} <span className='media-spoiler__warning'><FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /></span> <span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span> @@ -157,7 +157,7 @@ export default class VideoPlayer extends React.PureComponent { ); } else { return ( - <div role='button' tabIndex='0' style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler' onClick={this.handleVisibility}> + <div role='button' tabIndex='0' style={{ width: `${width}px`, height: `${height}px`, marginTop: '8px' }} className='media-spoiler__video' onClick={this.handleVisibility}> {spoilerButton} <span className='media-spoiler__warning'><FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' /></span> <span className='media-spoiler__trigger'><FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' /></span> diff --git a/app/javascript/mastodon/features/favourited_statuses/index.js b/app/javascript/mastodon/features/favourited_statuses/index.js index 82b16b369..1e1f5873c 100644 --- a/app/javascript/mastodon/features/favourited_statuses/index.js +++ b/app/javascript/mastodon/features/favourited_statuses/index.js @@ -77,6 +77,7 @@ export default class Favourites extends ImmutablePureComponent { onClick={this.handleHeaderClick} pinned={pinned} multiColumn={multiColumn} + showBackButton /> <StatusList diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js index b644718e3..54e58dfd0 100644 --- a/app/javascript/mastodon/features/notifications/index.js +++ b/app/javascript/mastodon/features/notifications/index.js @@ -124,6 +124,7 @@ export default class Notifications extends React.PureComponent { const scrollContainer = ( <ScrollableList scrollKey={`notifications-${columnId}`} + trackScroll={!pinned} isLoading={isLoading} hasMore={hasMore} emptyMessage={emptyMessage} diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 38324e156..3133238cd 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -26,12 +26,12 @@ "bundle_modal_error.close": "Schließen", "bundle_modal_error.message": "Etwas ist beim Laden schiefgelaufen.", "bundle_modal_error.retry": "Erneut versuchen", - "column.blocks": "Blockierte Benutzer", + "column.blocks": "Blockierte Profile", "column.community": "Lokale Zeitleiste", "column.favourites": "Favoriten", "column.follow_requests": "Folgeanfragen", "column.home": "Startseite", - "column.mutes": "Stummgeschaltete Benutzer", + "column.mutes": "Stummgeschaltete Profile", "column.notifications": "Mitteilungen", "column.public": "Gesamtes bekanntes Netz", "column_back_button.label": "Zurück", @@ -46,7 +46,7 @@ "compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Jeder kann dir jederzeit folgen, um deine privaten Beiträge einzusehen.", "compose_form.lock_disclaimer.lock": "gesperrt", "compose_form.placeholder": "Worüber möchtest du schreiben?", - "compose_form.privacy_disclaimer": "Dein privater Status wird an die genannten Benutzer auf den Domains {domains} zugestellt. Vertraust du {domainsCount, plural, one {diesem Server} other {diesen Servern}}? Private Beiträge funktionieren nur auf Mastodon-Instanzen. Wenn {domains} {domainsCount, plural, one {keine Mastodon-Instanz ist} other {keine Mastodon-Instanzen sind}}, wird es dort kein Anzeichen geben, dass dein Beitrag privat ist und er könnte geteilt oder anderweitig für unerwünschte Empfänger sichtbar gemacht werden.", + "compose_form.privacy_disclaimer": "Dein privater Status wird an die genannten Profile auf den Domains {domains} zugestellt. Vertraust du {domainsCount, plural, one {diesem Server} other {diesen Servern}}? Private Beiträge funktionieren nur auf Mastodon-Instanzen. Wenn {domains} {domainsCount, plural, one {keine Mastodon-Instanz ist} other {keine Mastodon-Instanzen sind}}, wird es dort kein Anzeichen geben, dass dein Beitrag privat ist und er könnte geteilt oder anderweitig für unerwünschte Empfänger sichtbar gemacht werden.", "compose_form.publish": "Tröt", "compose_form.publish_loud": "{publish}!", "compose_form.sensitive": "Medien als heikel markieren", @@ -77,18 +77,18 @@ "emoji_button.travel": "Reise und Orte", "empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe etwas öffentlich, um den Ball ins Rollen zu bringen!", "empty_column.hashtag": "Es gibt noch nichts unter diesem Hashtag.", - "empty_column.home": "Du folgst noch niemandem. Besuche {public} oder benutze die Suche, um zu starten oder andere Benutzer anzutreffen.", + "empty_column.home": "Du folgst noch niemandem. Besuche {public} oder benutze die Suche, um zu starten oder andere Profile zu finden.", "empty_column.home.inactivity": "Deine Zeitleiste ist leer. Falls du eine längere Zeit inaktiv gewesen bist, wird sie für dich so schnell wie möglich wiedererstellt.", "empty_column.home.public_timeline": "die öffentliche Zeitleiste", "empty_column.notifications": "Du hast noch keine Mitteilungen. Interagiere mit anderen, um die Konversation zu starten.", - "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Benutzern von anderen Instanzen, um es aufzufüllen.", + "empty_column.public": "Hier ist nichts zu sehen! Schreibe etwas öffentlich oder folge Profilen von anderen Instanzen, um es aufzufüllen.", "follow_request.authorize": "Erlauben", "follow_request.reject": "Ablehnen", "getting_started.appsshort": "Anwendungen", "getting_started.faq": "Häufig gestellte Fragen", "getting_started.heading": "Erste Schritte", "getting_started.open_source_notice": "Mastodon ist quelloffene Software. Du kannst auf {github} dazu beitragen oder Probleme melden.", - "getting_started.userguide": "Nutzeranleitung", + "getting_started.userguide": "Bedienungsanleitung", "home.column_settings.advanced": "Fortgeschritten", "home.column_settings.basic": "Einfach", "home.column_settings.filter_regex": "Filter durch reguläre Ausdrücke", @@ -101,14 +101,14 @@ "loading_indicator.label": "Lade…", "media_gallery.toggle_visible": "Sichtbarkeit einstellen", "missing_indicator.label": "Nicht gefunden", - "navigation_bar.blocks": "Blockierte Benutzer", + "navigation_bar.blocks": "Blockierte Profile", "navigation_bar.community_timeline": "Lokale Zeitleiste", "navigation_bar.edit_profile": "Profil bearbeiten", "navigation_bar.favourites": "Favoriten", "navigation_bar.follow_requests": "Folgeanfragen", "navigation_bar.info": "Erweiterte Informationen", "navigation_bar.logout": "Abmelden", - "navigation_bar.mutes": "Stummgeschaltete Benutzer", + "navigation_bar.mutes": "Stummgeschaltete Profile", "navigation_bar.preferences": "Einstellungen", "navigation_bar.public_timeline": "Föderierte Zeitleiste", "notification.favourite": "{name} favorisierte deinen Status", @@ -132,7 +132,7 @@ "onboarding.page_four.home": "Die Startseite zeigt dir Beiträge von Leuten, denen du folgst.", "onboarding.page_four.notifications": "Wenn jemand mir dir interagiert, bekommst du eine Mitteilung.", "onboarding.page_one.federation": "Mastodon ist ein soziales Netzwerk, das aus unabhängigen Servern besteht. Diese Server nennen wir auch Instanzen.", - "onboarding.page_one.handle": "Du bist auf der Instanz {domain}, also ist dein vollständiger Nutzername im Netzwerk {handle}", + "onboarding.page_one.handle": "Du bist auf der Instanz {domain}, also ist dein vollständiger Profilname im Netzwerk {handle}", "onboarding.page_one.welcome": "Willkommen bei Mastodon!", "onboarding.page_six.admin": "Für deine Instanz ist {admin} zuständig.", "onboarding.page_six.almost_done": "Fast fertig…", @@ -143,11 +143,11 @@ "onboarding.page_six.read_guidelines": "Bitte mach dich mit den {guidelines} von {domain} vertraut!", "onboarding.page_six.various_app": "mobile Anwendungen", "onboarding.page_three.profile": "Bearbeite dein Profil, um dein Bild, deinen Namen oder deine Beschreibung anzupassen. Dort findest du auch andere Einstellungen.", - "onboarding.page_three.search": "Benutze die Suchfunktion, um Leute oder Themen zu finden. Zum Beispiel, die Hashtags {illustration} oder {introductions}. Um eine Person zu finden, die auf einer anderen Instanz ist, benutze den vollständigen Nutzernamen.", + "onboarding.page_three.search": "Benutze die Suchfunktion, um Leute oder Themen zu finden. Zum Beispiel, die Hashtags {illustration} oder {introductions}. Um eine Person zu finden, die auf einer anderen Instanz ist, benutze den vollständigen Profilnamen.", "onboarding.page_two.compose": "Schreibe Beiträge aus der Schreiben-Spalte. Du kannst Bilder und kurze Videos hochladen, Sichtbarkeitseinstellungen ändern und Inhaltswarnungen hinzufügen.", "onboarding.skip": "Überspringen", "privacy.change": "Privatsphäre des Status anpassen", - "privacy.direct.long": "Beitrag nur an erwähnte Benutzer", + "privacy.direct.long": "Beitrag nur an erwähnte Profile", "privacy.direct.short": "Direkt", "privacy.private.long": "Beitrag nur an Folgende", "privacy.private.short": "Privat", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index b51340fa7..d05b26eb9 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -63,8 +63,8 @@ "confirmations.mute.message": "آیا واقعاً میخواهید {name} را بیصدا کنید؟", "confirmations.unfollow.confirm": "لغو پیگیری", "confirmations.unfollow.message": "آیا واقعاً میخواهید به پیگیری از {name} پایان دهید؟", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", + "embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.", + "embed.preview": "نوشتهٔ جاگذاریشده این گونه به نظر خواهد رسید:", "emoji_button.activity": "فعالیت", "emoji_button.flags": "پرچمها", "emoji_button.food": "غذا و نوشیدنی", @@ -164,14 +164,14 @@ "standalone.public_title": "نگاهی به کاربران این سرور...", "status.cannot_reblog": "این نوشته را نمیشود بازبوقید", "status.delete": "پاککردن", - "status.embed": "Embed", + "status.embed": "جاگذاری", "status.favourite": "پسندیدن", "status.load_more": "بیشتر نشان بده", "status.media_hidden": "تصویر پنهان شده", "status.mention": "نامبردن از @{name}", "status.mute_conversation": "بیصداکردن گفتگو", "status.open": "این نوشته را باز کن", - "status.pin": "Pin on profile", + "status.pin": "نوشتهٔ ثابت نمایه", "status.reblog": "بازبوقیدن", "status.reblogged_by": "{name} بازبوقید", "status.reply": "پاسخ", @@ -183,7 +183,7 @@ "status.show_less": "نهفتن", "status.show_more": "نمایش", "status.unmute_conversation": "باصداکردن گفتگو", - "status.unpin": "Unpin from profile", + "status.unpin": "برداشتن نوشتهٔ ثابت نمایه", "tabs_bar.compose": "بنویسید", "tabs_bar.federated_timeline": "همگانی", "tabs_bar.home": "خانه", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index 27e943bdd..f301723cf 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -1,7 +1,7 @@ { "account.block": "Blokiraj @{name}", "account.block_domain": "Sakrij sve sa {domain}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", + "account.disclaimer_full": "Ovaj korisnik je sa druge instance. Ovaj broj bi mogao biti veći.", "account.edit_profile": "Uredi profil", "account.follow": "Slijedi", "account.followers": "Sljedbenici", @@ -15,7 +15,7 @@ "account.requested": "Čeka pristanak", "account.share": "Share @{name}'s profile", "account.unblock": "Deblokiraj @{name}", - "account.unblock_domain": "Otkrij {domain}", + "account.unblock_domain": "Poništi sakrivanje {domain}", "account.unfollow": "Prestani slijediti", "account.unmute": "Poništi utišavanje @{name}", "account.view_full_profile": "View full profile", @@ -43,7 +43,7 @@ "column_header.unpin": "Unpin", "column_subheading.navigation": "Navigacija", "column_subheading.settings": "Postavke", - "compose_form.lock_disclaimer": "Tvoj račun nije {locked}. Svatko te može slijediti i vidjeti tvoje postove namijenjene samo sljedbenicima.", + "compose_form.lock_disclaimer": "Tvoj račun nije {locked}. Svatko te može slijediti kako bi vidio postove namijenjene samo tvojim sljedbenicima.", "compose_form.lock_disclaimer.lock": "zaključan", "compose_form.placeholder": "Što ti je na umu?", "compose_form.privacy_disclaimer": "Tvoj privatni status će biti dostavljen spomenutim korisnicima na {domains}. Vjeruješ li {domainsCount, plural, one {that server} drugim {those servers}}? Privatnost postova radi samo na Mastodon instancama. Ako {domains} {domainsCount, plural, one {is not a Mastodon instance} other {are not Mastodon instances}}, neće biti indikacije da je tvoj post privatan, i mogao bi biti podignut ili biti učinjen vidljivim na drugi način neželjenim primateljima.", @@ -54,13 +54,14 @@ "compose_form.spoiler_placeholder": "Upozorenje o sadržaju", "confirmation_modal.cancel": "Otkaži", "confirmations.block.confirm": "Blokiraj", - "confirmations.block.message": "Jesi li siguran da želiš blokirati {name}?", + "confirmations.block.message": "Želiš li sigurno blokirati {name}?", "confirmations.delete.confirm": "Obriši", - "confirmations.delete.message": "Jesi li siguran da želiš obrisati ovaj status?", + "confirmations.delete.message": "Želiš li stvarno obrisati ovaj status?", "confirmations.domain_block.confirm": "Sakrij cijelu domenu", - "confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš blokirati sve sa {domain}? U većini slučajeva nekoliko ciljanih blokiranja ili utišavanja je dostatno i poželjnije.", + "confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", "confirmations.mute.confirm": "Utišaj", "confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?", + "confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?", "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "embed.instructions": "Embed this status on your website by copying the code below.", @@ -69,16 +70,16 @@ "emoji_button.flags": "Zastave", "emoji_button.food": "Hrana & Piće", "emoji_button.label": "Umetni smajlije", - "emoji_button.nature": "Nature", + "emoji_button.nature": "Priroda", "emoji_button.objects": "Objekti", "emoji_button.people": "Ljudi", "emoji_button.search": "Traži...", "emoji_button.symbols": "Simboli", - "emoji_button.travel": "Putovanja i Mjesta", + "emoji_button.travel": "Putovanja & Mjesta", "empty_column.community": "Lokalni timeline je prazan. Napiši nešto javno kako bi pokrenuo stvari!", "empty_column.hashtag": "Još ne postoji ništa s ovim hashtagom.", "empty_column.home": "Još ne slijediš nikoga. Posjeti {public} ili koristi tražilicu kako bi počeo i upoznao druge korisnike.", - "empty_column.home.inactivity": "Tvoj home feed je prazan. Ako si neko vrijeme bio neaktivan, regenerirat će se uskoro.", + "empty_column.home.inactivity": "Tvoj home feed je prazan. Ako si neko vrijeme bio neaktivan, uskoro ćese regenerirati.", "empty_column.home.public_timeline": "javni timeline", "empty_column.notifications": "Još nemaš notifikacija. Komuniciraj sa drugima kako bi započeo razgovor.", "empty_column.public": "Ovdje nema ništa! Napiši nešto javno, ili ručno slijedi korisnike sa drugih instanci kako bi popunio", @@ -88,11 +89,11 @@ "getting_started.faq": "FAQ", "getting_started.heading": "Počnimo", "getting_started.open_source_notice": "Mastodon je softver otvorenog koda. Možeš pridonijeti ili prijaviti probleme na GitHubu {github}.", - "getting_started.userguide": "Vodič za korisnike", + "getting_started.userguide": "Upute za korištenje", "home.column_settings.advanced": "Napredno", "home.column_settings.basic": "Osnovno", "home.column_settings.filter_regex": "Filtriraj s regularnim izrazima", - "home.column_settings.show_reblogs": "Pokaži boosts", + "home.column_settings.show_reblogs": "Pokaži boostove", "home.column_settings.show_replies": "Pokaži odgovore", "home.settings": "Postavke Stupca", "lightbox.close": "Zatvori", @@ -113,7 +114,7 @@ "navigation_bar.public_timeline": "Federalni timeline", "notification.favourite": "{name} je lajkao tvoj status", "notification.follow": "{name} te sada slijedi", - "notification.mention": "{name} mentioned you", + "notification.mention": "{name} te je spomenuo", "notification.reblog": "{name} je podigao tvoj status", "notifications.clear": "Očisti notifikacije", "notifications.clear_confirmation": "Želiš li zaista obrisati sve svoje notifikacije?", @@ -123,28 +124,28 @@ "notifications.column_settings.mention": "Spominjanja:", "notifications.column_settings.push": "Push notifications", "notifications.column_settings.push_meta": "This device", - "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.reblog": "Boostovi:", "notifications.column_settings.show": "Prikaži u stupcu", "notifications.column_settings.sound": "Sviraj zvuk", "onboarding.done": "Učinjeno", - "onboarding.next": "Sljedeća", - "onboarding.page_five.public_timelines": "The local timeline prikazuje javne postove svih na {domain}. Federalni timeline pokazuje javne postove svih sa {domain} domena koje slijediš. To je sjajan način da otkriješ nove ljude.", - "onboarding.page_four.home": "The home timeline prikazuje samo postove ljudi koje slijediš.", - "onboarding.page_four.notifications": "Stupac notifikacija pokazuje kada je netko u interakciji s tobom.", - "onboarding.page_one.federation": "Mastodon je mreža nezavisnih servera udruženih kako bi stvorili veću socijalnu mrežu. Te servere zovemo instance.", - "onboarding.page_one.handle": "Ti si na {domain}, tako da je tvoj potpuni opis {handle}", - "onboarding.page_one.welcome": "Dobro došli u Mastodon!", + "onboarding.next": "Sljedeće", + "onboarding.page_five.public_timelines": "Lokalni timeline prikazuje javne postove sviju od svakog na {domain}. Federalni timeline prikazuje javne postove svakog koga ljudi na {domain} slijede. To su Javni Timelineovi, sjajan način za otkriti nove ljude.", + "onboarding.page_four.home": "The home timeline prikazuje postove ljudi koje slijediš.", + "onboarding.page_four.notifications": "Stupac za notifikacije pokazuje poruke drugih upućene tebi.", + "onboarding.page_one.federation": "Mastodon čini mreža neovisnih servera udruženih u jednu veću socialnu mrežu. Te servere nazivamo instancama.", + "onboarding.page_one.handle": "Ti si na {domain}, i tvoja puna handle je {handle}", + "onboarding.page_one.welcome": "Dobro došli na Mastodon!", "onboarding.page_six.admin": "Administrator tvoje instance je {admin}.", "onboarding.page_six.almost_done": "Još malo pa gotovo...", "onboarding.page_six.appetoot": "Živjeli!", "onboarding.page_six.apps_available": "Postoje {apps} dostupne za iOS, Android i druge platforme.", - "onboarding.page_six.github": "Mastodon je besplatan softver otvorenog koda. Možeš prijaviti greške, zahtijevati mogućnosti, ili pridonijeti kodu na {github}.", + "onboarding.page_six.github": "Mastodon je besplatan softver otvorenog koda. You can report bugs, request features, or contribute to the code on {github}.", "onboarding.page_six.guidelines": "smjernice zajednice", - "onboarding.page_six.read_guidelines": "Molimo, pročitaj {domain}'s {guidelines}!", + "onboarding.page_six.read_guidelines": "Molimo pročitaj {domain}'s {guidelines}!", "onboarding.page_six.various_app": "mobilne aplikacije", - "onboarding.page_three.profile": "Uredi svoj profil mijenjanjem avatara, biografije i imena koje će biti prikazano. Naći ćeš i druge korisne postavke.", - "onboarding.page_three.search": "Koristi tražilicu kako bi pronašao ljude i sadržaj sa određenim hashtagovima, kao što su {illustration} i {introductions}. Da bi našao osobu koja nije na ovoj instanci, upotrijebi njihov puni opis.", - "onboarding.page_two.compose": "Piši postove u stupcu za njihovo sastavljanje. Možeš uploadati slike, promijeniti postavke privatnosti, i dodati upozorenja o sadržaju s ikonama ispod.", + "onboarding.page_three.profile": "Uredi svoj profil promjenom svog avatara, biografije, i imena. Ovdje ćeš isto tako pronaći i druge postavke.", + "onboarding.page_three.search": "Koristi tražilicu kako bi pronašao ljude i tražio hashtags, kao što su {illustration} i {introductions}. Kako bi pronašao osobu koja nije na ovoj instanci, upotrijebi njen pun handle.", + "onboarding.page_two.compose": "Piši postove u stupcu za sastavljanje. Možeš uploadati slike, promijeniti postavke privatnosti, i dodati upozorenja o sadržaju s ikonama ispod.", "onboarding.skip": "Preskoči", "privacy.change": "Podesi status privatnosti", "privacy.direct.long": "Prikaži samo spomenutim korisnicima", @@ -162,7 +163,7 @@ "search.placeholder": "Traži", "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "A look inside...", - "status.cannot_reblog": "Ovaj post ne može biti podignut", + "status.cannot_reblog": "Ovaj post ne može biti boostan", "status.delete": "Obriši", "status.embed": "Embed", "status.favourite": "Označi omiljenim", @@ -196,5 +197,5 @@ "video_player.expand": "Proširi video", "video_player.toggle_sound": "Toggle zvuk", "video_player.toggle_visible": "Preklopi vidljivost", - "video_player.video_error": "Video nije mogao biti prikazan" + "video_player.video_error": "Video ne može biti reproduciran" } diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index 141bff042..a86033e6f 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -12,7 +12,7 @@ "account.mute": "Rescondre @{name}", "account.posts": "Estatuts", "account.report": "Senhalar @{name}", - "account.requested": "Invitacion mandada", + "account.requested": "Invitacion mandada. Clicatz per anullar.", "account.share": "Partejar lo perfil a @{name}", "account.unblock": "Desblocar @{name}", "account.unblock_domain": "Desblocar {domain}", @@ -63,8 +63,8 @@ "confirmations.mute.message": "Sètz segur de voler metre en silenci {name} ?", "confirmations.unfollow.confirm": "Quitar de sègre", "confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", + "embed.instructions": "Embarcar aqueste estatut per o far veire sus un site Internet en copiar lo còdi çai-jos.", + "embed.preview": "Semblarà aquò : ", "emoji_button.activity": "Activitats", "emoji_button.flags": "Drapèus", "emoji_button.food": "Beure e manjar", @@ -164,7 +164,7 @@ "standalone.public_title": "Una ulhada dedins…", "status.cannot_reblog": "Aqueste estatut pòt pas èsser partejat", "status.delete": "Escafar", - "status.embed": "Embed", + "status.embed": "Embarcar", "status.favourite": "Apondre als favorits", "status.load_more": "Cargar mai", "status.media_hidden": "Mèdia rescondut", diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss index 2f2d6e1f0..557355260 100644 --- a/app/javascript/styles/components.scss +++ b/app/javascript/styles/components.scss @@ -1885,6 +1885,10 @@ &:hover { text-decoration: underline; } + + &:last-child { + padding: 0 15px 0 0; + } } .column-back-button__icon { @@ -2712,6 +2716,22 @@ button.icon-button.active i.fa-retweet { } } +.media-spoiler__video { + align-items: center; + background: $base-overlay-background; + color: $primary-text-color; + cursor: pointer; + display: flex; + flex-direction: column; + border: 0; + width: 100%; + height: 100%; + justify-content: center; + position: relative; + text-align: center; + z-index: 100; +} + .media-spoiler__warning { display: block; font-size: 14px; @@ -4483,41 +4503,10 @@ noscript { } } -.embed-modal__html { - color: $ui-secondary-color; - outline: 0; - box-sizing: border-box; - display: block; - width: 100%; - border: none; - padding: 10px; - font-family: 'mastodon-font-monospace', monospace; - background: $ui-base-color; - color: $ui-primary-color; - font-size: 14px; - margin: 0; - margin-bottom: 15px; - - &::-moz-focus-inner { - border: 0; - } - - &::-moz-focus-inner, - &:focus, - &:active { - outline: 0 !important; - } - - &:focus { - background: lighten($ui-base-color, 4%); - } - - @media screen and (max-width: 600px) { - font-size: 16px; - } -} - .embed-modal { + max-width: 80vw; + max-height: 80vh; + h4 { padding: 30px; font-weight: 500; @@ -4525,18 +4514,52 @@ noscript { text-align: center; } - .hint { - margin-bottom: 15px; - } -} + .embed-modal__container { + padding: 10px; -.embed-modal__container { - padding: 10px; -} + .hint { + margin-bottom: 15px; + } -.embed-modal__iframe { - width: 100%; - min-width: 400px; - overflow: hidden; - border: 0; + .embed-modal__html { + color: $ui-secondary-color; + outline: 0; + box-sizing: border-box; + display: block; + width: 100%; + border: none; + padding: 10px; + font-family: 'mastodon-font-monospace', monospace; + background: $ui-base-color; + color: $ui-primary-color; + font-size: 14px; + margin: 0; + margin-bottom: 15px; + + &::-moz-focus-inner { + border: 0; + } + + &::-moz-focus-inner, + &:focus, + &:active { + outline: 0 !important; + } + + &:focus { + background: lighten($ui-base-color, 4%); + } + + @media screen and (max-width: 600px) { + font-size: 16px; + } + } + + .embed-modal__iframe { + width: 400px; + max-width: 100%; + overflow: hidden; + border: 0; + } + } } diff --git a/app/javascript/styles/stream_entries.scss b/app/javascript/styles/stream_entries.scss index 00e430184..35225c045 100644 --- a/app/javascript/styles/stream_entries.scss +++ b/app/javascript/styles/stream_entries.scss @@ -399,51 +399,54 @@ .embed { .activity-stream { - border-radius: 4px; box-shadow: none; .entry { - &:last-child { - border-radius: 0 0 4px 4px; - } - &:first-child { - border-radius: 4px 4px 0 0; + .detailed-status.light { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: flex-start; - &:last-child { - border-radius: 4px; + .detailed-status__display-name { + flex: 1; + margin: 0 5px 15px 0; } - } - } - } -} -.button.button-secondary.logo-button { - position: absolute; - right: 14px; - top: 14px; - font-size: 14px; + .button.button-secondary.logo-button { + flex: 0 auto; + font-size: 14px; - svg { - width: 20px; - height: auto; - vertical-align: middle; - margin-right: 5px; + svg { + width: 20px; + height: auto; + vertical-align: middle; + margin-right: 5px; - path:first-child { - fill: $ui-primary-color; - } + path:first-child { + fill: $ui-primary-color; + } - path:last-child { - fill: $simple-background-color; - } - } + path:last-child { + fill: $simple-background-color; + } + } - &:active, - &:focus, - &:hover { - svg path:first-child { - fill: lighten($ui-primary-color, 4%); + &:active, + &:focus, + &:hover { + svg path:first-child { + fill: lighten($ui-primary-color, 4%); + } + } + } + + .status__content, + .detailed-status__meta { + flex: 100%; + } + } } } } diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 081e80570..9a34484f5 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -33,7 +33,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity def status_params { uri: @object['id'], - url: @object['url'] || @object['id'], + url: object_url || @object['id'], account: @account, text: text_from_content || '', language: language_from_content, @@ -147,6 +147,16 @@ class ActivityPub::Activity::Create < ActivityPub::Activity @object['contentMap'].keys.first end + def object_url + return if @object['url'].blank? + + value = first_of_value(@object['url']) + + return value if value.is_a?(String) + + value['href'] + end + def language_map? @object['contentMap'].is_a?(Hash) && !@object['contentMap'].empty? end diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb index 81fae4140..b8e22a381 100644 --- a/app/lib/ostatus/atom_serializer.rb +++ b/app/lib/ostatus/atom_serializer.rb @@ -65,7 +65,7 @@ class OStatus::AtomSerializer add_namespaces(entry) if root - append_element(entry, 'id', TagManager.instance.unique_tag(stream_entry.created_at, stream_entry.activity_id, stream_entry.activity_type)) + append_element(entry, 'id', TagManager.instance.uri_for(stream_entry.status)) append_element(entry, 'published', stream_entry.created_at.iso8601) append_element(entry, 'updated', stream_entry.updated_at.iso8601) append_element(entry, 'title', stream_entry&.status&.title || "#{stream_entry.account.acct} deleted status") @@ -86,7 +86,7 @@ class OStatus::AtomSerializer serialize_status_attributes(entry, stream_entry.status) end - append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: account_stream_entry_url(stream_entry.account, stream_entry)) + append_element(entry, 'link', nil, rel: :alternate, type: 'text/html', href: TagManager.instance.url_for(stream_entry.status)) append_element(entry, 'link', nil, rel: :self, type: 'application/atom+xml', href: account_stream_entry_url(stream_entry.account, stream_entry, format: 'atom')) append_element(entry, 'thr:in-reply-to', nil, ref: TagManager.instance.uri_for(stream_entry.thread), href: TagManager.instance.url_for(stream_entry.thread)) if stream_entry.threaded? append_element(entry, 'ostatus:conversation', nil, ref: conversation_uri(stream_entry.status.conversation)) unless stream_entry&.status&.conversation_id.nil? diff --git a/app/lib/tag_manager.rb b/app/lib/tag_manager.rb index 5f87a2a48..f33a20c6f 100644 --- a/app/lib/tag_manager.rb +++ b/app/lib/tag_manager.rb @@ -49,12 +49,17 @@ class TagManager def unique_tag_to_local_id(tag, expected_type) return nil unless local_id?(tag) - matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag) - return matches[1] unless matches.nil? + + if ActivityPub::TagManager.instance.local_uri?(tag) + ActivityPub::TagManager.instance.uri_to_local_id(tag) + else + matches = Regexp.new("objectId=([\\d]+):objectType=#{expected_type}").match(tag) + return matches[1] unless matches.nil? + end end def local_id?(id) - id.start_with?("tag:#{Rails.configuration.x.local_domain}") + id.start_with?("tag:#{Rails.configuration.x.local_domain}") || ActivityPub::TagManager.instance.local_uri?(id) end def web_domain?(domain) @@ -92,7 +97,7 @@ class TagManager when :person account_url(target) when :note, :comment, :activity - unique_tag(target.created_at, target.id, 'Status') + target.uri || unique_tag(target.created_at, target.id, 'Status') end end diff --git a/app/models/status.rb b/app/models/status.rb index f44f79aaf..fdc230d8f 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -22,6 +22,7 @@ # reblogs_count :integer default(0), not null # language :string # conversation_id :integer +# local :boolean # class Status < ApplicationRecord @@ -84,7 +85,7 @@ class Status < ApplicationRecord end def local? - uri.nil? + attributes['local'] || uri.nil? end def reblog? @@ -131,11 +132,14 @@ class Status < ApplicationRecord !sensitive? && media_attachments.any? end + after_create :store_uri, if: :local? + before_validation :prepare_contents, if: :local? before_validation :set_reblog before_validation :set_visibility before_validation :set_conversation before_validation :set_sensitivity + before_validation :set_local class << self def not_in_filtered_languages(account) @@ -253,6 +257,10 @@ class Status < ApplicationRecord private + def store_uri + update_attribute(:uri, ActivityPub::TagManager.instance.uri_for(self)) if uri.nil? + end + def prepare_contents text&.strip! spoiler_text&.strip! @@ -292,4 +300,8 @@ class Status < ApplicationRecord thread.account_id end end + + def set_local + self.local = account.local? + end end diff --git a/app/presenters/account_relationships_presenter.rb b/app/presenters/account_relationships_presenter.rb index 657807863..a30558bac 100644 --- a/app/presenters/account_relationships_presenter.rb +++ b/app/presenters/account_relationships_presenter.rb @@ -4,12 +4,12 @@ class AccountRelationshipsPresenter attr_reader :following, :followed_by, :blocking, :muting, :requested, :domain_blocking - def initialize(account_ids, current_account_id) - @following = Account.following_map(account_ids, current_account_id) - @followed_by = Account.followed_by_map(account_ids, current_account_id) - @blocking = Account.blocking_map(account_ids, current_account_id) - @muting = Account.muting_map(account_ids, current_account_id) - @requested = Account.requested_map(account_ids, current_account_id) - @domain_blocking = Account.domain_blocking_map(account_ids, current_account_id) + def initialize(account_ids, current_account_id, options = {}) + @following = Account.following_map(account_ids, current_account_id).merge(options[:following_map] || {}) + @followed_by = Account.followed_by_map(account_ids, current_account_id).merge(options[:followed_by_map] || {}) + @blocking = Account.blocking_map(account_ids, current_account_id).merge(options[:blocking_map] || {}) + @muting = Account.muting_map(account_ids, current_account_id).merge(options[:muting_map] || {}) + @requested = Account.requested_map(account_ids, current_account_id).merge(options[:requested_map] || {}) + @domain_blocking = Account.domain_blocking_map(account_ids, current_account_id).merge(options[:domain_blocking_map] || {}) end end diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb index 25521eca9..a11178f5b 100644 --- a/app/serializers/activitypub/actor_serializer.rb +++ b/app/serializers/activitypub/actor_serializer.rb @@ -4,7 +4,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer include RoutingHelper attributes :id, :type, :following, :followers, - :inbox, :outbox, :shared_inbox, + :inbox, :outbox, :preferred_username, :name, :summary, :url, :manually_approves_followers @@ -24,6 +24,18 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer end end + class EndpointsSerializer < ActiveModel::Serializer + include RoutingHelper + + attributes :shared_inbox + + def shared_inbox + inbox_url + end + end + + has_one :endpoints, serializer: EndpointsSerializer + has_one :icon, serializer: ImageSerializer, if: :avatar_exists? has_one :image, serializer: ImageSerializer, if: :header_exists? @@ -51,8 +63,8 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer account_outbox_url(object) end - def shared_inbox - inbox_url + def endpoints + object end def preferred_username diff --git a/app/serializers/oembed_serializer.rb b/app/serializers/oembed_serializer.rb index 4f9293043..bd05da585 100644 --- a/app/serializers/oembed_serializer.rb +++ b/app/serializers/oembed_serializer.rb @@ -40,8 +40,7 @@ class OEmbedSerializer < ActiveModel::Serializer attributes = { src: embed_short_account_status_url(object.account, object), class: 'mastodon-embed', - frameborder: '0', - scrolling: 'no', + style: 'max-width: 100%; border: none;', width: width, height: height, } diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb index a26b39cb5..29eb1c2e1 100644 --- a/app/services/activitypub/process_account_service.rb +++ b/app/services/activitypub/process_account_service.rb @@ -6,7 +6,7 @@ class ActivityPub::ProcessAccountService < BaseService # Should be called with confirmed valid JSON # and WebFinger-resolved username and domain def call(username, domain, json) - return unless json['inbox'].present? + return if json['inbox'].blank? @json = json @uri = @json['id'] @@ -42,9 +42,9 @@ class ActivityPub::ProcessAccountService < BaseService @account.protocol = :activitypub @account.inbox_url = @json['inbox'] || '' @account.outbox_url = @json['outbox'] || '' - @account.shared_inbox_url = @json['sharedInbox'] || '' + @account.shared_inbox_url = (@json['endpoints'].is_a?(Hash) ? @json['endpoints']['sharedInbox'] : @json['sharedInbox']) || '' @account.followers_url = @json['followers'] || '' - @account.url = @json['url'] || @uri + @account.url = url || @uri @account.display_name = @json['name'] || '' @account.note = @json['summary'] || '' @account.avatar_remote_url = image_url('icon') @@ -62,7 +62,7 @@ class ActivityPub::ProcessAccountService < BaseService value = first_of_value(@json[key]) return if value.nil? - return @json[key]['url'] if @json[key].is_a?(Hash) + return value['url'] if value.is_a?(Hash) image = fetch_resource(value) image['url'] if image @@ -78,6 +78,16 @@ class ActivityPub::ProcessAccountService < BaseService key['publicKeyPem'] if key end + def url + return if @json['url'].blank? + + value = first_of_value(@json['url']) + + return value if value.is_a?(String) + + value['href'] + end + def auto_suspend? domain_block && domain_block.suspend? end diff --git a/app/services/process_mentions_service.rb b/app/services/process_mentions_service.rb index dc386c9e7..f123bf869 100644 --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@ -41,7 +41,7 @@ class ProcessMentionsService < BaseService NotifyService.new.call(mentioned_account, mention) elsif mentioned_account.ostatus? && (Rails.configuration.x.use_ostatus_privacy || !status.stream_entry.hidden?) NotificationWorker.perform_async(stream_entry_to_xml(status.stream_entry), status.account_id, mentioned_account.id) - elsif mentioned_account.activitypub? && !mentioned_account.following?(status.account) + elsif mentioned_account.activitypub? ActivityPub::DeliveryWorker.perform_async(build_json(mention.status), mention.status.account_id, mentioned_account.inbox_url) end end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index a157090e0..6fd39c88e 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -21,13 +21,13 @@ = stylesheet_pack_tag 'common', media: 'all' = javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous' - = javascript_pack_tag 'features/getting_started', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' - = javascript_pack_tag 'features/compose', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' - = javascript_pack_tag 'features/home_timeline', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' - = javascript_pack_tag 'features/notifications', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' - = javascript_pack_tag 'features/community_timeline', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' - = javascript_pack_tag 'features/public_timeline', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' - = javascript_pack_tag 'emojione_picker', integrity: true, crossorigin: 'anonymous', rel: 'preload', as: 'script' + %link{ href: asset_pack_path('features/getting_started.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ + %link{ href: asset_pack_path('features/compose.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ + %link{ href: asset_pack_path('features/home_timeline.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ + %link{ href: asset_pack_path('features/notifications.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ + %link{ href: asset_pack_path('features/community_timeline.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ + %link{ href: asset_pack_path('features/public_timeline.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ + %link{ href: asset_pack_path('emojione_picker.js'), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/ = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous' = csrf_meta_tags diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index ab803eebd..1d943a2ca 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -1,9 +1,4 @@ .detailed-status.light - - if embedded_view? - = link_to "web+mastodon://follow?uri=#{status.account.local_username_and_domain}", class: 'button button-secondary logo-button', target: '_new' do - = render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg') - = t('accounts.follow') - = link_to TagManager.instance.url_for(status.account), class: 'detailed-status__display-name p-author h-card', target: stream_link_target, rel: 'noopener' do %div .avatar @@ -12,6 +7,11 @@ %strong.p-name.emojify= display_name(status.account) %span= acct(status.account) + - if embedded_view? + = link_to "web+mastodon://follow?uri=#{status.account.local_username_and_domain}", class: 'button button-secondary logo-button', target: '_new' do + = render file: Rails.root.join('app', 'javascript', 'images', 'logo.svg') + = t('accounts.follow') + .status__content.p-name.emojify< - if status.spoiler_text? %p{ style: 'margin-bottom: 0' }< diff --git a/app/workers/pubsubhubbub/distribution_worker.rb b/app/workers/pubsubhubbub/distribution_worker.rb index 2a5e60fa0..524f6849f 100644 --- a/app/workers/pubsubhubbub/distribution_worker.rb +++ b/app/workers/pubsubhubbub/distribution_worker.rb @@ -6,7 +6,7 @@ class Pubsubhubbub::DistributionWorker sidekiq_options queue: 'push' def perform(stream_entry_ids) - stream_entries = StreamEntry.where(id: stream_entry_ids).includes(:status).reject { |e| e.status&.direct_visibility? } + stream_entries = StreamEntry.where(id: stream_entry_ids).includes(:status).reject { |e| e.status.nil? || e.status.direct_visibility? } return if stream_entries.empty? diff --git a/app/workers/pubsubhubbub/subscribe_worker.rb b/app/workers/pubsubhubbub/subscribe_worker.rb index 7560c2671..130c967e0 100644 --- a/app/workers/pubsubhubbub/subscribe_worker.rb +++ b/app/workers/pubsubhubbub/subscribe_worker.rb @@ -3,7 +3,7 @@ class Pubsubhubbub::SubscribeWorker include Sidekiq::Worker - sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false + sidekiq_options queue: 'push', retry: 10, unique: :until_executed, dead: false, unique_retry: true sidekiq_retry_in do |count| case count diff --git a/app/workers/resolve_remote_account_worker.rb b/app/workers/resolve_remote_account_worker.rb new file mode 100644 index 000000000..5dd84ccb6 --- /dev/null +++ b/app/workers/resolve_remote_account_worker.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ResolveRemoteAccountWorker + include Sidekiq::Worker + + sidekiq_options queue: 'pull', unique: :until_executed + + def perform(uri) + ResolveRemoteAccountService.new.call(uri) + end +end |