diff --git a/Gemfile.lock b/Gemfile.lock index b01ac36eb28..2467b76ccde 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -39,7 +39,8 @@ GEM i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.4.0) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) arel (7.1.4) ast (2.3.0) autoprefixer-rails (6.5.0.2) @@ -98,7 +99,7 @@ GEM warden (~> 1.2.3) diff-lcs (1.2.5) docile (1.1.5) - domain_name (0.5.20160826) + domain_name (0.5.20161129) unf (>= 0.0.5, < 1.0.0) doorkeeper (4.2.0) railties (>= 4.2) @@ -121,7 +122,7 @@ GEM ruby-progressbar (~> 1.4) globalid (0.3.7) activesupport (>= 4.1.0) - goldfinger (1.1.0) + goldfinger (1.1.2) addressable (~> 2.4) http (~> 2.0) nokogiri (~> 1.6) @@ -138,7 +139,7 @@ GEM highline (1.7.8) hiredis (0.6.1) htmlentities (4.3.4) - http (2.0.3) + http (2.1.0) addressable (~> 2.3) http-cookie (~> 1.0) http-form_data (~> 1.0.1) @@ -226,6 +227,7 @@ GEM slop (~> 3.4) pry-rails (0.3.4) pry (>= 0.9.10) + public_suffix (2.0.4) puma (3.6.0) rabl (0.13.1) activesupport (>= 2.3.14) diff --git a/app/assets/javascripts/components/features/account/components/header.jsx b/app/assets/javascripts/components/features/account/components/header.jsx index adf9ab5ae11..6ae5ac002bf 100644 --- a/app/assets/javascripts/components/features/account/components/header.jsx +++ b/app/assets/javascripts/components/features/account/components/header.jsx @@ -61,10 +61,10 @@ const Header = React.createClass({ const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) }; return ( -
+
-
+
diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 88808b0850e..290b370a9a9 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -147,6 +147,12 @@ } } +@media screen and (max-height: 800px) { + .account__header__avatar, .account__header__content { + display: none; + } +} + .account__header__content { word-wrap: break-word; font-weight: 300; @@ -585,4 +591,4 @@ pointer-events: none; bottom: 0; left: 0; -} \ No newline at end of file +} diff --git a/app/controllers/remote_follow_controller.rb b/app/controllers/remote_follow_controller.rb new file mode 100644 index 00000000000..5e923c88fe8 --- /dev/null +++ b/app/controllers/remote_follow_controller.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +class RemoteFollowController < ApplicationController + layout 'public' + + before_action :set_account + before_action :check_account_suspension + + def new + @remote_follow = RemoteFollow.new + end + + def create + @remote_follow = RemoteFollow.new(resource_params) + + if @remote_follow.valid? + resource = Goldfinger.finger("acct:#{@remote_follow.acct}") + redirect_url_link = resource&.link('http://ostatus.org/schema/1.0/subscribe') + + if redirect_url_link.nil? || redirect_url_link.template.nil? + @remote_follow.errors.add(:acct, I18n.t('remote_follow.missing_resource')) + render(:new) && return + end + + redirect_to Addressable::Template.new(redirect_url_link.template).expand(uri: "acct:#{@account.username}@#{Rails.configuration.x.local_domain}").to_s + else + render :new + end + rescue Goldfinger::Error + @remote_follow.errors.add(:acct, I18n.t('remote_follow.missing_resource')) + render :new + end + + private + + def resource_params + params.require(:remote_follow).permit(:acct) + end + + def set_account + @account = Account.find_local!(params[:account_username]) + end + + def check_account_suspension + head 410 if @account.suspended? + end +end diff --git a/app/models/remote_follow.rb b/app/models/remote_follow.rb new file mode 100644 index 00000000000..13281a4fcca --- /dev/null +++ b/app/models/remote_follow.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class RemoteFollow + include ActiveModel::Validations + + attr_accessor :acct + + validates :acct, presence: true + + def initialize(attrs = {}) + @acct = attrs[:acct] + end +end diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml index 01e63920589..1c6b5f0f676 100644 --- a/app/views/accounts/_header.html.haml +++ b/app/views/accounts/_header.html.haml @@ -5,8 +5,11 @@ = link_to t('accounts.unfollow'), unfollow_account_path(@account), data: { method: :post }, class: 'button' - else = link_to t('accounts.follow'), follow_account_path(@account), data: { method: :post }, class: 'button' - - .avatar= image_tag @account.avatar.url( :original) + - else + .controls + .remote-follow + = link_to t('accounts.remote_follow'), account_remote_follow_path(@account), class: 'button' + .avatar= image_tag @account.avatar.url(:original) %h1.name = display_name(@account) %small diff --git a/app/views/authorize_follow/_card.html.haml b/app/views/authorize_follow/_card.html.haml new file mode 100644 index 00000000000..a9b02c74610 --- /dev/null +++ b/app/views/authorize_follow/_card.html.haml @@ -0,0 +1,11 @@ +.account-card + .detailed-status__display-name + %div + = image_tag account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar' + + %span.display-name + %strong= display_name(account) + %span= "@#{account.acct}" + + - unless account.note.blank? + .account__header__content= Formatter.instance.simplified_format(account) diff --git a/app/views/authorize_follow/new.html.haml b/app/views/authorize_follow/new.html.haml index 44bf575ff46..95601253e60 100644 --- a/app/views/authorize_follow/new.html.haml +++ b/app/views/authorize_follow/new.html.haml @@ -5,17 +5,7 @@ .follow-prompt %h2= t('authorize_follow.prompt_html', self: current_account.username) - .account-card - .detailed-status__display-name - %div - = image_tag @account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar' - - %span.display-name - %strong= display_name(@account) - %span= "@#{@account.acct}" - - - unless @account.note.blank? - .account__header__content= Formatter.instance.simplified_format(@account) + = render partial: 'card', locals: { account: @account } = form_tag authorize_follow_path, method: :post, class: 'simple_form' do = hidden_field_tag :acct, @account.acct diff --git a/app/views/remote_follow/new.html.haml b/app/views/remote_follow/new.html.haml new file mode 100644 index 00000000000..e88ccccce53 --- /dev/null +++ b/app/views/remote_follow/new.html.haml @@ -0,0 +1,13 @@ +.form-container + .follow-prompt + %h2= t('remote_follow.prompt') + + = render partial: 'authorize_follow/card', locals: { account: @account } + + = simple_form_for @remote_follow, as: :remote_follow, url: account_remote_follow_path(@account) do |f| + = render 'shared/error_messages', object: @remote_follow + + = f.input :acct, placeholder: t('remote_follow.acct') + + .actions + = f.button :button, t('remote_follow.proceed'), type: :submit diff --git a/config/locales/en.yml b/config/locales/en.yml index f57c7202627..e166fc7170a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -14,6 +14,7 @@ en: people_followed_by: People whom %{name} follows people_who_follow: People who follow %{name} posts: Posts + remote_follow: Remote follow unfollow: Unfollow application_mailer: signature: Mastodon notifications from %{instance} @@ -71,6 +72,11 @@ en: pagination: next: Next prev: Prev + remote_follow: + acct: Enter your username@domain you want to follow from + missing_resource: Could not find the required redirect URL for your account + proceed: Proceed to follow + prompt: 'You are going to follow:' settings: edit_profile: Edit profile preferences: Preferences diff --git a/config/routes.rb b/config/routes.rb index 842fbe71ed5..18c239c48a5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -31,6 +31,9 @@ Rails.application.routes.draw do end end + get :remote_follow, to: 'remote_follow#new' + post :remote_follow, to: 'remote_follow#create' + member do get :followers get :following