diff options
Diffstat (limited to 'app/helpers')
-rw-r--r-- | app/helpers/accounts_helper.rb | 114 | ||||
-rw-r--r-- | app/helpers/admin/action_logs_helper.rb | 8 | ||||
-rw-r--r-- | app/helpers/admin/filter_helper.rb | 7 | ||||
-rw-r--r-- | app/helpers/application_helper.rb | 29 | ||||
-rw-r--r-- | app/helpers/domain_control_helper.rb | 25 | ||||
-rw-r--r-- | app/helpers/home_helper.rb | 2 | ||||
-rw-r--r-- | app/helpers/instance_helper.rb | 12 | ||||
-rw-r--r-- | app/helpers/jsonld_helper.rb | 54 | ||||
-rw-r--r-- | app/helpers/settings_helper.rb | 25 | ||||
-rw-r--r-- | app/helpers/statuses_helper.rb (renamed from app/helpers/stream_entries_helper.rb) | 93 |
10 files changed, 238 insertions, 131 deletions
diff --git a/app/helpers/accounts_helper.rb b/app/helpers/accounts_helper.rb new file mode 100644 index 000000000..7fcc4e816 --- /dev/null +++ b/app/helpers/accounts_helper.rb @@ -0,0 +1,114 @@ +# frozen_string_literal: true + +module AccountsHelper + def display_name(account, **options) + if options[:custom_emojify] + Formatter.instance.format_display_name(account, options) + else + account.display_name.presence || account.username + end + end + + def acct(account) + if account.local? + "@#{account.acct}@#{Rails.configuration.x.local_domain}" + else + "@#{account.acct}" + end + end + + def account_action_button(account) + if user_signed_in? + if account.id == current_user.account_id + link_to settings_profile_url, class: 'button logo-button' do + safe_join([svg_logo, t('settings.edit_profile')]) + end + elsif current_account.following?(account) || current_account.requested?(account) + link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do + safe_join([svg_logo, t('accounts.unfollow')]) + end + elsif !(account.memorial? || account.moved?) + link_to account_follow_path(account), class: "button logo-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post } do + safe_join([svg_logo, t('accounts.follow')]) + end + end + elsif !(account.memorial? || account.moved?) + link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do + safe_join([svg_logo, t('accounts.follow')]) + end + end + end + + def minimal_account_action_button(account) + if user_signed_in? + return if account.id == current_user.account_id + + if current_account.following?(account) || current_account.requested?(account) + link_to account_unfollow_path(account), class: 'icon-button active', data: { method: :post }, title: t('accounts.unfollow') do + fa_icon('user-times fw') + end + elsif !(account.memorial? || account.moved?) + link_to account_follow_path(account), class: "icon-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post }, title: t('accounts.follow') do + fa_icon('user-plus fw') + end + end + elsif !(account.memorial? || account.moved?) + link_to account_remote_follow_path(account), class: 'icon-button modal-button', target: '_new', title: t('accounts.follow') do + fa_icon('user-plus fw') + end + end + end + + def account_badge(account, all: false) + if account.bot? + content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles') + elsif account.group? + content_tag(:div, content_tag(:div, t('accounts.roles.group'), class: 'account-role group'), class: 'roles') + elsif (Setting.show_staff_badge && account.user_staff?) || all + content_tag(:div, class: 'roles') do + if all && !account.user_staff? + content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role') + elsif account.user_admin? + content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin') + elsif account.user_moderator? + content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator') + end + end + end + end + + def hide_followers_count?(account) + Setting.hide_followers_count || account.user&.setting_hide_followers_count + end + + def account_description(account) + prepend_stats = [ + [ + number_to_human(account.statuses_count, strip_insignificant_zeros: true), + I18n.t('accounts.posts', count: account.statuses_count), + ].join(' '), + + [ + number_to_human(account.following_count, strip_insignificant_zeros: true), + I18n.t('accounts.following', count: account.following_count), + ].join(' '), + ] + + unless hide_followers_count?(account) + prepend_stats << [ + number_to_human(account.followers_count, strip_insignificant_zeros: true), + I18n.t('accounts.followers', count: account.followers_count), + ].join(' ') + end + + [prepend_stats.join(', '), account.note].join(' · ') + end + + def svg_logo + content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo'), 'viewBox' => '0 0 216.4144 232.00976') + end + + def svg_logo_full + content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo-full'), 'viewBox' => '0 0 713.35878 175.8678') + end +end diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb index e5fbb1500..608a99dd5 100644 --- a/app/helpers/admin/action_logs_helper.rb +++ b/app/helpers/admin/action_logs_helper.rb @@ -44,6 +44,8 @@ module Admin::ActionLogsHelper 'flag' when 'DomainBlock' 'lock' + when 'DomainAllow' + 'plus-circle' when 'EmailDomainBlock' 'envelope' when 'Status' @@ -86,10 +88,10 @@ module Admin::ActionLogsHelper record.shortcode when 'Report' link_to "##{record.id}", admin_report_path(record) - when 'DomainBlock', 'EmailDomainBlock' + when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock' link_to record.domain, "https://#{record.domain}" when 'Status' - link_to record.account.acct, TagManager.instance.url_for(record) + link_to record.account.acct, ActivityPub::TagManager.instance.url_for(record) when 'AccountWarning' link_to record.target_account.acct, admin_account_path(record.target_account_id) end @@ -99,7 +101,7 @@ module Admin::ActionLogsHelper case type when 'CustomEmoji' attributes['shortcode'] - when 'DomainBlock', 'EmailDomainBlock' + when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock' link_to attributes['domain'], "https://#{attributes['domain']}" when 'Status' tmp_status = Status.new(attributes.except('reblogs_count', 'favourites_count')) diff --git a/app/helpers/admin/filter_helper.rb b/app/helpers/admin/filter_helper.rb index 0bda25974..fc4f15985 100644 --- a/app/helpers/admin/filter_helper.rb +++ b/app/helpers/admin/filter_helper.rb @@ -2,18 +2,19 @@ module Admin::FilterHelper ACCOUNT_FILTERS = %i(local remote by_domain active pending silenced suspended username display_name email ip staff).freeze - REPORT_FILTERS = %i(resolved account_id target_account_id).freeze + REPORT_FILTERS = %i(resolved account_id target_account_id by_target_domain).freeze INVITE_FILTER = %i(available expired).freeze CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze - TAGS_FILTERS = %i(hidden).freeze + TAGS_FILTERS = %i(directory reviewed unreviewed pending_review popular active name).freeze INSTANCES_FILTERS = %i(limited by_domain).freeze FOLLOWERS_FILTERS = %i(relationship status by_domain activity order).freeze FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS + TAGS_FILTERS + INSTANCES_FILTERS + FOLLOWERS_FILTERS def filter_link_to(text, link_to_params, link_class_params = link_to_params) - new_url = filtered_url_for(link_to_params) + new_url = filtered_url_for(link_to_params) new_class = filtered_url_for(link_class_params) + link_to text, new_url, class: filter_link_class(new_class) end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7ae1e5d0b..40f914f1e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -77,8 +77,12 @@ module ApplicationHelper content_tag(:i, nil, attributes.merge(class: class_names.join(' '))) end - def custom_emoji_tag(custom_emoji) - image_tag(custom_emoji.image.url, class: 'emojione', alt: ":#{custom_emoji.shortcode}:") + def custom_emoji_tag(custom_emoji, animate = true) + if animate + image_tag(custom_emoji.image.url, class: 'emojione', alt: ":#{custom_emoji.shortcode}:") + else + image_tag(custom_emoji.image.url(:static), class: 'emojione custom-emoji', alt: ":#{custom_emoji.shortcode}", 'data-original' => full_asset_url(custom_emoji.image.url), 'data-static' => full_asset_url(custom_emoji.image.url(:static))) + end end def opengraph(property, content) @@ -123,4 +127,25 @@ module ApplicationHelper text = word_wrap(text, line_width: line_width - 2, break_sequence: break_sequence) text.split("\n").map { |line| '> ' + line }.join("\n") end + + def render_initial_state + state_params = { + settings: { + known_fediverse: Setting.show_known_fediverse_at_about_page, + }, + + text: [params[:title], params[:text], params[:url]].compact.join(' '), + } + + if user_signed_in? + state_params[:settings] = state_params[:settings].merge(Web::Setting.find_by(user: current_user)&.data || {}) + state_params[:push_subscription] = current_account.user.web_push_subscription(current_session) + state_params[:current_account] = current_account + state_params[:token] = current_session.token + state_params[:admin] = Account.find_local(Setting.site_contact_username.strip.gsub(/\A@/, '')) + end + + json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json + content_tag(:script, json_escape(json).html_safe, id: 'initial-state', type: 'application/json') + end end diff --git a/app/helpers/domain_control_helper.rb b/app/helpers/domain_control_helper.rb new file mode 100644 index 000000000..ac60cad29 --- /dev/null +++ b/app/helpers/domain_control_helper.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module DomainControlHelper + def domain_not_allowed?(uri_or_domain) + return if uri_or_domain.blank? + + domain = begin + if uri_or_domain.include?('://') + Addressable::URI.parse(uri_or_domain).host + else + uri_or_domain + end + end + + if whitelist_mode? + !DomainAllow.allowed?(domain) + else + DomainBlock.blocked?(domain) + end + end + + def whitelist_mode? + Rails.configuration.x.whitelist_mode + end +end diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb index df60b7dd7..b66e827fe 100644 --- a/app/helpers/home_helper.rb +++ b/app/helpers/home_helper.rb @@ -21,7 +21,7 @@ module HomeHelper end end else - link_to(path || TagManager.instance.url_for(account), class: 'account__display-name') do + link_to(path || ActivityPub::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: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url)})") end + diff --git a/app/helpers/instance_helper.rb b/app/helpers/instance_helper.rb index dd0b25f3e..daacb535b 100644 --- a/app/helpers/instance_helper.rb +++ b/app/helpers/instance_helper.rb @@ -8,4 +8,16 @@ module InstanceHelper def site_hostname @site_hostname ||= Addressable::URI.parse("//#{Rails.configuration.x.local_domain}").display_uri.host end + + def description_for_sign_up + prefix = begin + if @invite.present? + I18n.t('auth.description.prefix_invited_by_user', name: @invite.user.account.username) + else + I18n.t('auth.description.prefix_sign_up') + end + end + + safe_join([prefix, I18n.t('auth.description.suffix')], ' ') + end end diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb index 5b4011275..1c473efa3 100644 --- a/app/helpers/jsonld_helper.rb +++ b/app/helpers/jsonld_helper.rb @@ -16,13 +16,15 @@ module JsonLdHelper # The url attribute can be a string, an array of strings, or an array of objects. # The objects could include a mimeType. Not-included mimeType means it's text/html. def url_to_href(value, preferred_type = nil) - single_value = if value.is_a?(Array) && !value.first.is_a?(String) - value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } - elsif value.is_a?(Array) - value.first - else - value - end + single_value = begin + if value.is_a?(Array) && !value.first.is_a?(String) + value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) } + elsif value.is_a?(Array) + value.first + else + value + end + end if single_value.nil? || single_value.is_a?(String) single_value @@ -64,7 +66,9 @@ module JsonLdHelper def fetch_resource(uri, id, on_behalf_of = nil) unless id json = fetch_resource_without_id_validation(uri, on_behalf_of) + return unless json + uri = json['id'] end @@ -73,25 +77,20 @@ module JsonLdHelper end def fetch_resource_without_id_validation(uri, on_behalf_of = nil, raise_on_temporary_error = false) + on_behalf_of ||= Account.representative + build_request(uri, on_behalf_of).perform do |response| - unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error - raise Mastodon::UnexpectedResponseError, response - end - return body_to_json(response.body_with_limit) if response.code == 200 - end - # If request failed, retry without doing it on behalf of a user - return if on_behalf_of.nil? - build_request(uri).perform do |response| - unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error - raise Mastodon::UnexpectedResponseError, response - end - response.code == 200 ? body_to_json(response.body_with_limit) : nil + raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error + + body_to_json(response.body_with_limit) if response.code == 200 end end def body_to_json(body, compare_id: nil) json = body.is_a?(String) ? Oj.load(body, mode: :strict) : body + return if compare_id.present? && json['id'] != compare_id + json rescue Oj::ParseError nil @@ -105,35 +104,34 @@ module JsonLdHelper end end - private - def response_successful?(response) (200...300).cover?(response.code) end def response_error_unsalvageable?(response) - (400...500).cover?(response.code) && response.code != 429 + response.code == 501 || ((400...500).cover?(response.code) && ![401, 408, 429].include?(response.code)) end def build_request(uri, on_behalf_of = nil) - request = Request.new(:get, uri) - request.on_behalf_of(on_behalf_of) if on_behalf_of - request.add_headers('Accept' => 'application/activity+json, application/ld+json') - request + Request.new(:get, uri).tap do |request| + request.on_behalf_of(on_behalf_of) if on_behalf_of + request.add_headers('Accept' => 'application/activity+json, application/ld+json') + end end def load_jsonld_context(url, _options = {}, &_block) json = Rails.cache.fetch("jsonld:context:#{url}", expires_in: 30.days, raw: true) do request = Request.new(:get, url) request.add_headers('Accept' => 'application/ld+json') - request.perform do |res| raise JSON::LD::JsonLdError::LoadingDocumentFailed unless res.code == 200 && res.mime_type == 'application/ld+json' + res.body_with_limit end end - doc = JSON::LD::API::RemoteDocument.new(url, json) + doc = JSON::LD::API::RemoteDocument.new(json, documentUrl: url) + block_given? ? yield(doc) : doc end end diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 92bc222ea..39eb4180e 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -2,11 +2,11 @@ module SettingsHelper HUMAN_LOCALES = { - en: 'English', ar: 'العربية', ast: 'Asturianu', bg: 'Български', bn: 'বাংলা', + br: 'Breton', ca: 'Català', co: 'Corsu', cs: 'Čeština', @@ -14,8 +14,11 @@ module SettingsHelper da: 'Dansk', de: 'Deutsch', el: 'Ελληνικά', + en: 'English', eo: 'Esperanto', + 'es-AR': 'Español (Argentina)', es: 'Español', + et: 'Eesti', eu: 'Euskara', fa: 'فارسی', fi: 'Suomi', @@ -33,34 +36,40 @@ module SettingsHelper ja: '日本語', ka: 'ქართული', kk: 'Қазақша', + kn: 'ಕನ್ನಡ', ko: '한국어', lt: 'Lietuvių', lv: 'Latviešu', + mk: 'Македонски', ml: 'മലയാളം', + mr: 'मराठी', ms: 'Bahasa Melayu', nl: 'Nederlands', + nn: 'Nynorsk', no: 'Norsk', oc: 'Occitan', pl: 'Polski', + 'pt-BR': 'Português (Brasil)', + 'pt-PT': 'Português (Portugal)', pt: 'Português', - 'pt-BR': 'Português do Brasil', ro: 'Română', ru: 'Русский', sk: 'Slovenčina', sl: 'Slovenščina', sq: 'Shqip', - sr: 'Српски', 'sr-Latn': 'Srpski (latinica)', + sr: 'Српски', sv: 'Svenska', ta: 'தமிழ்', te: 'తెలుగు', th: 'ไทย', tr: 'Türkçe', uk: 'Українська', - zh: '中文', + ur: 'اُردُو', 'zh-CN': '简体中文', 'zh-HK': '繁體中文(香港)', 'zh-TW': '繁體中文(臺灣)', + zh: '中文', }.freeze def human_locale(locale) @@ -86,4 +95,12 @@ module SettingsHelper 'desktop' end end + + def compact_account_link_to(account) + return if account.nil? + + link_to ActivityPub::TagManager.instance.url_for(account), class: 'name-tag', title: account.acct do + safe_join([image_tag(account.avatar.url, width: 15, height: 15, alt: display_name(account), class: 'avatar'), content_tag(:span, account.acct, class: 'username')], ' ') + end + end end diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/statuses_helper.rb index 6a71f1c02..866a9902c 100644 --- a/app/helpers/stream_entries_helper.rb +++ b/app/helpers/statuses_helper.rb @@ -1,63 +1,9 @@ # frozen_string_literal: true -module StreamEntriesHelper +module StatusesHelper EMBEDDED_CONTROLLER = 'statuses' EMBEDDED_ACTION = 'embed' - def display_name(account, **options) - if options[:custom_emojify] - Formatter.instance.format_display_name(account, options) - else - account.display_name.presence || account.username - end - end - - def account_action_button(account) - if user_signed_in? - if account.id == current_user.account_id - link_to settings_profile_url, class: 'button logo-button' do - safe_join([svg_logo, t('settings.edit_profile')]) - end - elsif current_account.following?(account) || current_account.requested?(account) - link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do - safe_join([svg_logo, t('accounts.unfollow')]) - end - elsif !(account.memorial? || account.moved?) - link_to account_follow_path(account), class: "button logo-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post } do - safe_join([svg_logo, t('accounts.follow')]) - end - end - elsif !(account.memorial? || account.moved?) - link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do - safe_join([svg_logo, t('accounts.follow')]) - end - end - end - - def svg_logo - content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo'), 'viewBox' => '0 0 216.4144 232.00976') - end - - def svg_logo_full - content_tag(:svg, tag(:use, 'xlink:href' => '#mastodon-svg-logo-full'), 'viewBox' => '0 0 713.35878 175.8678') - end - - def account_badge(account, all: false) - if account.bot? - content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles') - elsif (Setting.show_staff_badge && account.user_staff?) || all - content_tag(:div, class: 'roles') do - if all && !account.user_staff? - content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role') - elsif account.user_admin? - content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin') - elsif account.user_moderator? - content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator') - end - end - end - end - def link_to_more(url) link_to t('statuses.show_more'), url, class: 'load-more load-gap' end @@ -68,33 +14,6 @@ module StreamEntriesHelper end end - def hide_followers_count?(account) - Setting.hide_followers_count || account.user&.setting_hide_followers_count - end - - def account_description(account) - prepend_stats = [ - [ - number_to_human(account.statuses_count, strip_insignificant_zeros: true), - I18n.t('accounts.posts', count: account.statuses_count), - ].join(' '), - - [ - number_to_human(account.following_count, strip_insignificant_zeros: true), - I18n.t('accounts.following', count: account.following_count), - ].join(' '), - ] - - unless hide_followers_count?(account) - prepend_stats << [ - number_to_human(account.followers_count, strip_insignificant_zeros: true), - I18n.t('accounts.followers', count: account.followers_count), - ].join(' ') - end - - [prepend_stats.join(', '), account.note].join(' · ') - end - def media_summary(status) attachments = { image: 0, video: 0 } @@ -115,11 +34,13 @@ module StreamEntriesHelper def status_text_summary(status) return if status.spoiler_text.blank? + I18n.t('statuses.content_warning', warning: status.spoiler_text) end def poll_summary(status) return unless status.preloadable_poll + status.preloadable_poll.options.map { |o| "[ ] #{o}" }.join("\n") end @@ -138,14 +59,6 @@ module StreamEntriesHelper embedded_view? ? '_blank' : nil end - def acct(account) - if account.local? - "@#{account.acct}@#{Rails.configuration.x.local_domain}" - else - "@#{account.acct}" - end - end - def style_classes(status, is_predecessor, is_successor, include_threads) classes = ['entry'] classes << 'entry-predecessor' if is_predecessor |