Merge remote-tracking branch 'tootsuite/master' into glitchsoc/master

This commit is contained in:
Jenkins 2018-01-15 06:17:15 +00:00
commit 0c7dc6c781
13 changed files with 51 additions and 13 deletions

View file

@ -4,6 +4,7 @@ class Api::Web::PushSubscriptionsController < Api::BaseController
respond_to :json respond_to :json
before_action :require_user! before_action :require_user!
protect_from_forgery with: :exception
def create def create
params.require(:subscription).require(:endpoint) params.require(:subscription).require(:endpoint)

View file

@ -37,6 +37,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
columns: ImmutablePropTypes.list.isRequired, columns: ImmutablePropTypes.list.isRequired,
isModalOpen: PropTypes.bool.isRequired,
singleColumn: PropTypes.bool, singleColumn: PropTypes.bool,
children: PropTypes.node, children: PropTypes.node,
}; };
@ -144,7 +145,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
} }
render () { render () {
const { columns, children, singleColumn } = this.props; const { columns, children, singleColumn, isModalOpen } = this.props;
const { shouldAnimate } = this.state; const { shouldAnimate } = this.state;
const columnIndex = getIndex(this.context.router.history.location.pathname); const columnIndex = getIndex(this.context.router.history.location.pathname);
@ -159,7 +160,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
} }
return ( return (
<div className='columns-area' ref={this.setRef}> <div className={`columns-area ${ isModalOpen ? 'unscrollable' : '' }`} ref={this.setRef}>
{columns.map(column => { {columns.map(column => {
const params = column.get('params', null) === null ? null : column.get('params').toJS(); const params = column.get('params', null) === null ? null : column.get('params').toJS();

View file

@ -3,6 +3,7 @@ import ColumnsArea from '../components/columns_area';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
columns: state.getIn(['settings', 'columns']), columns: state.getIn(['settings', 'columns']),
isModalOpen: !!state.get('modal').modalType,
}); });
export default connect(mapStateToProps, null, null, { withRef: true })(ColumnsArea); export default connect(mapStateToProps, null, null, { withRef: true })(ColumnsArea);

View file

@ -1613,6 +1613,10 @@
justify-content: flex-start; justify-content: flex-start;
overflow-x: auto; overflow-x: auto;
position: relative; position: relative;
&.unscrollable {
overflow-x: hidden;
}
} }
@media screen and (min-width: 360px) { @media screen and (min-width: 360px) {

View file

@ -170,6 +170,10 @@ class User < ApplicationRecord
settings.default_privacy || (account.locked? ? 'private' : 'public') settings.default_privacy || (account.locked? ? 'private' : 'public')
end end
def allows_digest_emails?
settings.notification_emails['digest']
end
def token_for_app(a) def token_for_app(a)
return nil if a.nil? || a.owner != self return nil if a.nil? || a.owner != self
Doorkeeper::AccessToken Doorkeeper::AccessToken

View file

@ -30,7 +30,7 @@ class ActivityPub::FetchRemoteStatusService < BaseService
end end
def actor_id def actor_id
first_of_value(@json['attributedTo']) value_or_id(first_of_value(@json['attributedTo']))
end end
def trustworthy_attribution?(uri, attributed_to) def trustworthy_attribution?(uri, attributed_to)

View file

@ -9,7 +9,7 @@ class DigestMailerWorker
def perform(user_id) def perform(user_id)
@user = User.find(user_id) @user = User.find(user_id)
deliver_digest if user_receives_digest? deliver_digest if @user.allows_digest_emails?
end end
private private
@ -18,8 +18,4 @@ class DigestMailerWorker
NotificationMailer.digest(user.account).deliver_now! NotificationMailer.digest(user.account).deliver_now!
user.touch(:last_emailed_at) user.touch(:last_emailed_at)
end end
def user_receives_digest?
user.settings.notification_emails['digest']
end
end end

View file

@ -0,0 +1,24 @@
# frozen_string_literal: true
require 'sidekiq-scheduler'
class Scheduler::EmailScheduler
include Sidekiq::Worker
def perform
eligible_users.find_each do |user|
next unless user.allows_digest_emails?
DigestMailerWorker.perform_async(user.id)
end
end
private
def eligible_users
User.confirmed
.joins(:account)
.where(accounts: { silenced: false, suspended: false })
.where(disabled: false)
.where('current_sign_in_at < ?', 20.days.ago)
.where('last_emailed_at IS NULL OR last_emailed_at < ?', 20.days.ago)
end
end

View file

@ -0,0 +1,3 @@
# frozen_string_literal: true
ActionController::Base.log_warning_on_csrf_failure = false

View file

@ -561,12 +561,14 @@ en:
blackberry: Blackberry blackberry: Blackberry
chrome: Chrome chrome: Chrome
edge: Microsoft Edge edge: Microsoft Edge
electron: Electron
firefox: Firefox firefox: Firefox
generic: Unknown browser generic: Unknown browser
ie: Internet Explorer ie: Internet Explorer
micro_messenger: MicroMessenger micro_messenger: MicroMessenger
nokia: Nokia S40 Ovi Browser nokia: Nokia S40 Ovi Browser
opera: Opera opera: Opera
otter: Otter
phantom_js: PhantomJS phantom_js: PhantomJS
qq: QQ Browser qq: QQ Browser
safari: Safari safari: Safari

View file

@ -4,7 +4,7 @@ en:
hints: hints:
defaults: defaults:
avatar: PNG, GIF or JPG. At most 2MB. Will be downscaled to 120x120px avatar: PNG, GIF or JPG. At most 2MB. Will be downscaled to 120x120px
digest: Sent after a long period of inactivity with a summary of mentions you've received in your absence digest: Only sent after a long period of inactivity and only if you have received any personal messages in your absence
display_name: display_name:
one: <span class="name-counter">1</span> character left one: <span class="name-counter">1</span> character left
other: <span class="name-counter">%{count}</span> characters left other: <span class="name-counter">%{count}</span> characters left

View file

@ -27,3 +27,6 @@
ip_cleanup_scheduler: ip_cleanup_scheduler:
cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *' cron: '<%= Random.rand(0..59) %> <%= Random.rand(3..5) %> * * *'
class: Scheduler::IpCleanupScheduler class: Scheduler::IpCleanupScheduler
email_scheduler:
cron: '0 10 * * 2'
class: Scheduler::EmailScheduler

View file

@ -171,11 +171,10 @@ namespace :mastodon do
end end
namespace :emails do namespace :emails do
desc 'Send out digest e-mails' desc 'Send out digest e-mails (deprecated)'
task digest: :environment do task digest: :environment do
User.confirmed.joins(:account).where(accounts: { silenced: false, suspended: false }).where('current_sign_in_at < ?', 20.days.ago).find_each do |user| # No-op
DigestMailerWorker.perform_async(user.id) # This task is now executed via sidekiq-scheduler
end
end end
end end