Merge remote-tracking branch 'tootsuite/master' into glitchsoc/master
This commit is contained in:
commit
0c7dc6c781
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
ActionController::Base.log_warning_on_csrf_failure = false
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue