Add autofollow option to invites (#7805)
* Add autofollow option to invites * Trigger CodeClimate rebuild
This commit is contained in:
		| @@ -3,6 +3,7 @@ | ||||
| class Auth::RegistrationsController < Devise::RegistrationsController | ||||
|   layout :determine_layout | ||||
|  | ||||
|   before_action :set_invite, only: [:new, :create] | ||||
|   before_action :check_enabled_registrations, only: [:new, :create] | ||||
|   before_action :configure_sign_up_params, only: [:create] | ||||
|   before_action :set_sessions, only: [:edit, :update] | ||||
| @@ -51,7 +52,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController | ||||
|   end | ||||
|  | ||||
|   def allowed_registrations? | ||||
|     Setting.open_registrations || (invite_code.present? && Invite.find_by(code: invite_code)&.valid_for_use?) | ||||
|     Setting.open_registrations || @invite&.valid_for_use? | ||||
|   end | ||||
|  | ||||
|   def invite_code | ||||
| @@ -68,6 +69,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController | ||||
|     @instance_presenter = InstancePresenter.new | ||||
|   end | ||||
|  | ||||
|   def set_invite | ||||
|     @invite = invite_code.present? ? Invite.find_by(code: invite_code) : nil | ||||
|   end | ||||
|  | ||||
|   def determine_layout | ||||
|     %w(edit update).include?(action_name) ? 'admin' : 'auth' | ||||
|   end | ||||
|   | ||||
| @@ -11,7 +11,7 @@ class InvitesController < ApplicationController | ||||
|     authorize :invite, :create? | ||||
|  | ||||
|     @invites = invites | ||||
|     @invite  = Invite.new(expires_in: 1.day.to_i) | ||||
|     @invite  = Invite.new | ||||
|   end | ||||
|  | ||||
|   def create | ||||
| @@ -42,6 +42,6 @@ class InvitesController < ApplicationController | ||||
|   end | ||||
|  | ||||
|   def resource_params | ||||
|     params.require(:invite).permit(:max_uses, :expires_in) | ||||
|     params.require(:invite).permit(:max_uses, :expires_in, :autofollow) | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -458,23 +458,31 @@ | ||||
| } | ||||
|  | ||||
| .account-card { | ||||
|   padding: 14px 10px; | ||||
|   background: $simple-background-color; | ||||
|   border-radius: 4px; | ||||
|   text-align: left; | ||||
|   box-shadow: 0 0 15px rgba($base-shadow-color, 0.2); | ||||
|   background: $simple-background-color; | ||||
|  | ||||
|   .detailed-status__display-name { | ||||
|   &__header { | ||||
|     background-size: cover; | ||||
|     background-position: center center; | ||||
|     height: 90px; | ||||
|     border-radius: 4px 4px 0 0; | ||||
|   } | ||||
|  | ||||
|   & > .detailed-status__display-name { | ||||
|     display: block; | ||||
|     overflow: hidden; | ||||
|     margin-bottom: 15px; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     padding: 10px; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-bottom: 0; | ||||
|     } | ||||
|  | ||||
|     & > div { | ||||
|       float: left; | ||||
|     & > div:first-child { | ||||
|       flex: 0 0 auto; | ||||
|       margin-right: 10px; | ||||
|       width: 48px; | ||||
|       height: 48px; | ||||
| @@ -483,9 +491,11 @@ | ||||
|     .avatar { | ||||
|       display: block; | ||||
|       border-radius: 4px; | ||||
|       margin: 0; | ||||
|     } | ||||
|  | ||||
|     .display-name { | ||||
|       flex: 1 0 auto; | ||||
|       display: block; | ||||
|       max-width: 100%; | ||||
|       overflow: hidden; | ||||
| @@ -493,6 +503,10 @@ | ||||
|       text-overflow: ellipsis; | ||||
|       cursor: default; | ||||
|  | ||||
|       & > .detailed-status__display-name { | ||||
|         margin-bottom: 0; | ||||
|       } | ||||
|  | ||||
|       strong { | ||||
|         font-weight: 500; | ||||
|         color: $ui-base-color; | ||||
| @@ -519,9 +533,28 @@ | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .account__header__content { | ||||
|     font-size: 14px; | ||||
|     color: $inverted-text-color; | ||||
|   .counter { | ||||
|     box-sizing: border-box; | ||||
|     flex: 0 0 auto; | ||||
|     color: $light-text-color; | ||||
|     padding: 0 10px; | ||||
|     cursor: default; | ||||
|     text-align: center; | ||||
|     position: relative; | ||||
|     line-height: 24px; | ||||
|  | ||||
|     .counter-label { | ||||
|       font-size: 12px; | ||||
|       display: block; | ||||
|       text-transform: uppercase; | ||||
|     } | ||||
|  | ||||
|     .counter-number { | ||||
|       font-weight: 500; | ||||
|       font-size: 16px; | ||||
|       color: $inverted-text-color; | ||||
|       font-family: 'mastodon-font-display', sans-serif; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #  uses       :integer          default(0), not null | ||||
| #  created_at :datetime         not null | ||||
| #  updated_at :datetime         not null | ||||
| #  autofollow :boolean          default(FALSE), not null | ||||
| # | ||||
|  | ||||
| class Invite < ApplicationRecord | ||||
|   | ||||
| @@ -2,13 +2,25 @@ | ||||
|  | ||||
| class BootstrapTimelineService < BaseService | ||||
|   def call(source_account) | ||||
|     bootstrap_timeline_accounts.each do |target_account| | ||||
|       FollowService.new.call(source_account, target_account) | ||||
|     end | ||||
|     @source_account = source_account | ||||
|  | ||||
|     autofollow_inviter! | ||||
|     autofollow_bootstrap_timeline_accounts! | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def autofollow_inviter! | ||||
|     return unless @source_account&.user&.invite&.autofollow? | ||||
|     FollowService.new.call(@source_account, @source_account.user.invite.user.account) | ||||
|   end | ||||
|  | ||||
|   def autofollow_bootstrap_timeline_accounts! | ||||
|     bootstrap_timeline_accounts.each do |target_account| | ||||
|       FollowService.new.call(@source_account, target_account) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def bootstrap_timeline_accounts | ||||
|     return @bootstrap_timeline_accounts if defined?(@bootstrap_timeline_accounts) | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,11 @@ | ||||
| = simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| | ||||
|   = render 'shared/error_messages', object: resource | ||||
|  | ||||
|   - if @invite.present? && @invite.autofollow? | ||||
|     .fields-group{ style: 'margin-bottom: 30px' } | ||||
|       %p.hint{ style: 'text-align: center' }= t('invites.invited_by') | ||||
|       = render 'authorize_follows/card', account: @invite.user.account | ||||
|  | ||||
|   = f.simple_fields_for :account do |ff| | ||||
|     .input-with-append | ||||
|       = ff.input :username, autofocus: true, placeholder: t('simple_form.labels.defaults.username'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.username'), :autocomplete => 'off' } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| .account-card | ||||
|   .account-card__header{ style: "background-image: url(#{account.header.url(:original)})" } | ||||
|   .detailed-status__display-name | ||||
|     %div | ||||
|       = image_tag account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar' | ||||
| @@ -9,5 +10,14 @@ | ||||
|         %strong.emojify= display_name(account, custom_emojify: true) | ||||
|         %span @#{account.acct} | ||||
|  | ||||
|   - if account.note? | ||||
|     .account__header__content.emojify= Formatter.instance.simplified_format(account) | ||||
|     .counter | ||||
|       %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true | ||||
|       %span.counter-label= t('accounts.posts') | ||||
|  | ||||
|     .counter | ||||
|       %span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true | ||||
|       %span.counter-label= t('accounts.following') | ||||
|  | ||||
|     .counter | ||||
|       %span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true | ||||
|       %span.counter-label= t('accounts.followers') | ||||
|   | ||||
| @@ -5,5 +5,8 @@ | ||||
|     = f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: lambda { |num| I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt') | ||||
|     = f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt') | ||||
|  | ||||
|   .fields-group | ||||
|     = f.input :autofollow, wrapper: :with_label | ||||
|  | ||||
|   .actions | ||||
|     = f.button :button, t('invites.generate'), type: :submit | ||||
|   | ||||
| @@ -514,6 +514,7 @@ en: | ||||
|       '86400': 1 day | ||||
|     expires_in_prompt: Never | ||||
|     generate: Generate | ||||
|     invited_by: 'You were invited by:' | ||||
|     max_uses: | ||||
|       one: 1 use | ||||
|       other: "%{count} uses" | ||||
|   | ||||
| @@ -3,6 +3,7 @@ en: | ||||
|   simple_form: | ||||
|     hints: | ||||
|       defaults: | ||||
|         autofollow: People who sign up through the invite will automatically follow you | ||||
|         avatar: PNG, GIF or JPG. At most 2MB. Will be downscaled to 400x400px | ||||
|         bot: This account mainly performs automated actions and might not be monitored | ||||
|         digest: Only sent after a long period of inactivity and only if you have received any personal messages in your absence | ||||
| @@ -30,6 +31,7 @@ en: | ||||
|           name: Label | ||||
|           value: Content | ||||
|       defaults: | ||||
|         autofollow: Invite to follow your account | ||||
|         avatar: Avatar | ||||
|         bot: This is a bot account | ||||
|         confirm_new_password: Confirm new password | ||||
|   | ||||
							
								
								
									
										17
									
								
								db/migrate/20180615122121_add_autofollow_to_invites.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								db/migrate/20180615122121_add_autofollow_to_invites.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| require Rails.root.join('lib', 'mastodon', 'migration_helpers') | ||||
|  | ||||
| class AddAutofollowToInvites < ActiveRecord::Migration[5.2] | ||||
|   include Mastodon::MigrationHelpers | ||||
|  | ||||
|   disable_ddl_transaction! | ||||
|  | ||||
|   def change | ||||
|     safety_assured do | ||||
|       add_column_with_default :invites, :autofollow, :bool, default: false, allow_null: false | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def down | ||||
|     remove_column :invites, :autofollow | ||||
|   end | ||||
| end | ||||
| @@ -10,7 +10,7 @@ | ||||
| # | ||||
| # It's strongly recommended that you check this file into your version control system. | ||||
|  | ||||
| ActiveRecord::Schema.define(version: 2018_06_09_104432) do | ||||
| ActiveRecord::Schema.define(version: 2018_06_15_122121) do | ||||
|  | ||||
|   # These are extensions that must be enabled in order to support this database | ||||
|   enable_extension "plpgsql" | ||||
| @@ -219,6 +219,7 @@ ActiveRecord::Schema.define(version: 2018_06_09_104432) do | ||||
|     t.integer "uses", default: 0, null: false | ||||
|     t.datetime "created_at", null: false | ||||
|     t.datetime "updated_at", null: false | ||||
|     t.boolean "autofollow", default: false, null: false | ||||
|     t.index ["code"], name: "index_invites_on_code", unique: true | ||||
|     t.index ["user_id"], name: "index_invites_on_user_id" | ||||
|   end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user