Merge 2.7.1 (#7)

Bu işleme şunda yer alıyor:
khr 2019-02-11 00:49:05 +01:00 işlemeyi yapan: Gitea
ebeveyn 631d141ad0
işleme f9722a0aec
18 değiştirilmiş dosya ile 170 ekleme ve 30 silme

Dosyayı Görüntüle

@ -3,6 +3,20 @@ Changelog
All notable changes to this project will be documented in this file.
## [2.7.1] - 2019-01-28
### Fixed
- Fix SSO authentication not working due to missing agreement boolean ([Gargron](https://github.com/tootsuite/mastodon/pull/9915))
- Fix slow fallback of CopyAccountStats migration setting stats to 0 ([Gargron](https://github.com/tootsuite/mastodon/pull/9930))
- Fix wrong command in migration error message ([angristan](https://github.com/tootsuite/mastodon/pull/9877))
- Fix initial value of volume slider in video player and handle volume changes ([ThibG](https://github.com/tootsuite/mastodon/pull/9929))
- Fix missing hotkeys for notifications ([ThibG](https://github.com/tootsuite/mastodon/pull/9927))
- Fix being able to attach unattached media created by other users ([ThibG](https://github.com/tootsuite/mastodon/pull/9921))
- Fix unrescued SSL error during link verification ([renatolond](https://github.com/tootsuite/mastodon/pull/9914))
- Fix Firefox scrollbar color regression ([trwnh](https://github.com/tootsuite/mastodon/pull/9908))
- Fix scheduled status with media immediately creating a status ([ThibG](https://github.com/tootsuite/mastodon/pull/9894))
- Fix missing strong style for landing page description ([Kjwon15](https://github.com/tootsuite/mastodon/pull/9892))
## [2.7.0] - 2019-01-20
### Added

Dosyayı Görüntüle

@ -1,7 +1,7 @@
Contributing
============
Thank you for considering contributing to Mastodon 🐘
Thank you for considering contributing to Mastodon 🐘
You can contribute in the following ways:
@ -10,6 +10,8 @@ You can contribute in the following ways:
- Contributing code to Mastodon by fixing bugs or implementing features
- Improving the documentation
If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
## Bug reports
Bug reports and feature suggestions can be submitted to [GitHub Issues](https://github.com/tootsuite/mastodon/issues). Please make sure that you are not submitting duplicates, and that a similar report or request has not already been resolved or rejected in the past using the search function. Please also use descriptive, concise titles.

Dosyayı Görüntüle

@ -23,7 +23,7 @@ gem 'paperclip-av-transcoder', '~> 0.6'
gem 'streamio-ffmpeg', '~> 3.0'
gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.5'
gem 'addressable', '~> 2.6'
gem 'bootsnap', '~> 1.3', require: false
gem 'browser'
gem 'charlock_holmes', '~> 0.7.6'

Dosyayı Görüntüle

@ -62,7 +62,7 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.2)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
airbrussh (1.3.0)
sshkit (>= 1.6.1, != 1.7.0)
@ -290,8 +290,8 @@ GEM
json-ld (3.0.2)
multi_json (~> 1.12)
rdf (>= 2.2.8, < 4.0)
json-ld-preloaded (3.0.0)
json-ld (>= 2.2, < 4.0)
json-ld-preloaded (3.0.2)
json-ld (~> 3.0)
multi_json (~> 1.12)
rdf (~> 3.0)
jsonapi-renderer (0.2.0)
@ -363,7 +363,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.7.7)
oj (3.7.8)
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
@ -389,7 +389,7 @@ GEM
paperclip-av-transcoder (0.6.4)
av (~> 0.9.0)
paperclip (>= 2.5.2)
parallel (1.12.1)
parallel (1.13.0)
parallel_tests (2.27.1)
parallel
parser (2.6.0.0)
@ -420,7 +420,7 @@ GEM
pry (>= 0.10.4)
public_suffix (3.0.3)
puma (3.12.0)
pundit (2.0.0)
pundit (2.0.1)
activesupport (>= 3.0.0)
raabro (1.1.6)
rack (2.0.6)
@ -513,7 +513,7 @@ GEM
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.1)
rspec-rails (3.8.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
@ -525,7 +525,7 @@ GEM
rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0)
rspec-support (3.8.0)
rubocop (0.63.0)
rubocop (0.63.1)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
@ -655,7 +655,7 @@ PLATFORMS
DEPENDENCIES
active_model_serializers (~> 0.10)
active_record_query_trace (~> 1.5)
addressable (~> 2.5)
addressable (~> 2.6)
annotate (~> 2.7)
aws-sdk-s3 (~> 1.30)
better_errors (~> 2.5)

Dosyayı Görüntüle

@ -21,7 +21,7 @@ Click below to **learn more** in a video:
[youtube_demo]: https://www.youtube.com/watch?v=IPSbNdBmWKE
## Navigation
## Navigation
- [Project homepage 🐘](https://joinmastodon.org)
- [Support the development via Patreon][patreon]
@ -80,7 +80,7 @@ A **Vagrant** configuration is included for development purposes.
Mastodon is **free, open source software** licensed under **AGPLv3**.
You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository, or submit translations using Weblate. To get started, take a look at [CONTRIBUTING.md](CONTRIBUTING.md)
You can open issues for bugs you've found or features you think are missing. You can also submit pull requests to this repository, or submit translations using Weblate. To get started, take a look at [CONTRIBUTING.md](CONTRIBUTING.md). If your contributions are accepted into Mastodon, you can request to be paid through [our OpenCollective](https://opencollective.com/mastodon).
**IRC channel**: #mastodon on irc.freenode.net

Dosyayı Görüntüle

@ -29,6 +29,10 @@ class Notification extends ImmutablePureComponent {
onMoveUp: PropTypes.func.isRequired,
onMoveDown: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired,
onFavourite: PropTypes.func.isRequired,
onReblog: PropTypes.func.isRequired,
onToggleHidden: PropTypes.func.isRequired,
status: PropTypes.option,
intl: PropTypes.object.isRequired,
};
@ -64,14 +68,32 @@ class Notification extends ImmutablePureComponent {
onMention(notification.get('account'), this.context.router.history);
}
handleHotkeyFavourite = () => {
const { status } = this.props;
if (status) this.props.onFavourite(status);
}
handleHotkeyBoost = e => {
const { status } = this.props;
if (status) this.props.onReblog(status, e);
}
handleHotkeyToggleHidden = () => {
const { status } = this.props;
if (status) this.props.onToggleHidden(status);
}
getHandlers () {
return {
moveUp: this.handleMoveUp,
moveDown: this.handleMoveDown,
reply: this.handleMention,
favourite: this.handleHotkeyFavourite,
boost: this.handleHotkeyBoost,
mention: this.handleMention,
open: this.handleOpen,
openProfile: this.handleOpenProfile,
mention: this.handleMention,
reply: this.handleMention,
moveUp: this.handleMoveUp,
moveDown: this.handleMoveDown,
toggleHidden: this.handleHotkeyToggleHidden,
};
}

Dosyayı Görüntüle

@ -1,14 +1,31 @@
import { connect } from 'react-redux';
import { makeGetNotification } from '../../../selectors';
import { makeGetNotification, makeGetStatus } from '../../../selectors';
import Notification from '../components/notification';
import { openModal } from '../../../actions/modal';
import { mentionCompose } from '../../../actions/compose';
import {
reblog,
favourite,
unreblog,
unfavourite,
} from '../../../actions/interactions';
import {
hideStatus,
revealStatus,
} from '../../../actions/statuses';
import { boostModal } from '../../../initial_state';
const makeMapStateToProps = () => {
const getNotification = makeGetNotification();
const getStatus = makeGetStatus();
const mapStateToProps = (state, props) => ({
notification: getNotification(state, props.notification, props.accountId),
});
const mapStateToProps = (state, props) => {
const notification = getNotification(state, props.notification, props.accountId);
return {
notification: notification,
status: notification.get('status') ? getStatus(state, { id: notification.get('status') }) : null,
};
};
return mapStateToProps;
};
@ -17,6 +34,38 @@ const mapDispatchToProps = dispatch => ({
onMention: (account, router) => {
dispatch(mentionCompose(account, router));
},
onModalReblog (status) {
dispatch(reblog(status));
},
onReblog (status, e) {
if (status.get('reblogged')) {
dispatch(unreblog(status));
} else {
if (e.shiftKey || !boostModal) {
this.onModalReblog(status);
} else {
dispatch(openModal('BOOST', { status, onReblog: this.onModalReblog }));
}
}
},
onFavourite (status) {
if (status.get('favourited')) {
dispatch(unfavourite(status));
} else {
dispatch(favourite(status));
}
},
onToggleHidden (status) {
if (status.get('hidden')) {
dispatch(revealStatus(status.get('id')));
} else {
dispatch(hideStatus(status.get('id')));
}
},
});
export default connect(makeMapStateToProps, mapDispatchToProps)(Notification);

Dosyayı Görüntüle

@ -136,6 +136,9 @@ class Video extends React.PureComponent {
setVideoRef = c => {
this.video = c;
if (this.video) {
this.setState({ volume: this.video.volume, muted: this.video.muted });
}
}
setSeekRef = c => {
@ -302,6 +305,10 @@ class Video extends React.PureComponent {
}
}
handleVolumeChange = () => {
this.setState({ volume: this.video.volume, muted: this.video.muted });
}
handleOpenVideo = () => {
const { src, preview, width, height, alt } = this.props;
const media = fromJS({
@ -387,6 +394,7 @@ class Video extends React.PureComponent {
onTimeUpdate={this.handleTimeUpdate}
onLoadedData={this.handleLoadedData}
onProgress={this.handleProgress}
onVolumeChange={this.handleVolumeChange}
/>
<button type='button' className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}>
@ -409,7 +417,7 @@ class Video extends React.PureComponent {
<div className='video-player__buttons-bar'>
<div className='video-player__buttons left'>
<button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
<button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onMouseEnter={this.volumeSlider} onMouseLeave={this.volumeSlider} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
<button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
<div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
<div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} />
<span

Dosyayı Görüntüle

@ -845,6 +845,18 @@ $small-breakpoint: 960px;
margin-bottom: 0;
}
strong {
display: inline;
margin: 0;
padding: 0;
font-weight: 700;
background: transparent;
font-family: inherit;
font-size: inherit;
line-height: inherit;
color: lighten($darker-text-color, 10%);
}
.account {
border-bottom: 0;
padding: 0;

Dosyayı Görüntüle

@ -54,7 +54,7 @@ table {
}
html {
scrollbar-color: lighten($ui-base-color, 4%) transparent;
scrollbar-color: lighten($ui-base-color, 4%) rgba($base-overlay-background, 0.1);
}
::-webkit-scrollbar {

Dosyayı Görüntüle

@ -63,6 +63,7 @@ module Omniauthable
{
email: email || "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
password: Devise.friendly_token[0, 20],
agreement: true,
account_attributes: {
username: ensure_unique_username(auth.uid),
display_name: display_name,

Dosyayı Görüntüle

@ -295,6 +295,7 @@ class User < ApplicationRecord
def self.pam_get_user(attributes = {})
return nil unless attributes[:email]
resource =
if Devise.check_at_sign && !attributes[:email].index('@')
joins(:account).find_by(accounts: { username: attributes[:email] })
@ -304,6 +305,7 @@ class User < ApplicationRecord
if resource.blank?
resource = new(email: attributes[:email], agreement: true)
if Devise.check_at_sign && !resource[:email].index('@')
resource[:email] = Rpam2.getenv(resource.find_pam_service, attributes[:email], attributes[:password], 'email', false)
resource[:email] = "#{attributes[:email]}@#{resource.find_pam_suffix}" unless resource[:email]

Dosyayı Görüntüle

@ -66,7 +66,10 @@ class PostStatusService < BaseService
end
def schedule_status!
if @account.statuses.build(status_attributes).valid?
status_for_validation = @account.statuses.build(status_attributes)
if status_for_validation.valid?
status_for_validation.destroy
# The following transaction block is needed to wrap the UPDATEs to
# the media attachments when the scheduled status is created
@ -90,7 +93,7 @@ class PostStatusService < BaseService
raise Mastodon::ValidationError, I18n.t('media_attachments.validations.too_many') if @options[:media_ids].size > 4
@media = MediaAttachment.where(status_id: nil).where(id: @options[:media_ids].take(4).map(&:to_i))
@media = @account.media_attachments.where(status_id: nil).where(id: @options[:media_ids].take(4).map(&:to_i))
raise Mastodon::ValidationError, I18n.t('media_attachments.validations.images_and_video') if @media.size > 1 && @media.find(&:video?)
end

Dosyayı Görüntüle

@ -10,7 +10,7 @@ class VerifyLinkService < BaseService
return unless link_back_present?
field.mark_verified!
rescue HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
rescue OpenSSL::SSL::SSLError, HTTP::Error, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
Rails.logger.debug "Error fetching link #{@url}: #{e}"
nil
end

Dosyayı Görüntüle

@ -44,7 +44,7 @@ class CopyAccountStats < ActiveRecord::Migration[5.2]
# uniqueness violations that we need to skip over
Account.unscoped.select('id, statuses_count, following_count, followers_count, created_at, updated_at').find_each do |account|
begin
params = [[nil, account.id], [nil, account.statuses_count], [nil, account.following_count], [nil, account.followers_count], [nil, account.created_at], [nil, account.updated_at]]
params = [[nil, account.id], [nil, account[:statuses_count]], [nil, account[:following_count]], [nil, account[:followers_count]], [nil, account.created_at], [nil, account.updated_at]]
exec_insert('INSERT INTO account_stats (account_id, statuses_count, following_count, followers_count, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6)', nil, params)
rescue ActiveRecord::RecordNotUnique
next

Dosyayı Görüntüle

@ -889,7 +889,7 @@ table #{table}.
If you are using PostgreSQL you can solve this by logging in to the GitLab
database (#{dbname}) using a super user and running:
ALTER #{user} WITH SUPERUSER
ALTER USER #{user} WITH SUPERUSER
For MySQL you instead need to run:

Dosyayı Görüntüle

@ -13,7 +13,7 @@ module Mastodon
end
def patch
0
1
end
def pre

Dosyayı Görüntüle

@ -36,6 +36,20 @@ RSpec.describe PostStatusService, type: :service do
expect(status.params['text']).to eq 'Hi future!'
end
it 'does not immediately create a status when scheduling a status' do
account = Fabricate(:account)
media = Fabricate(:media_attachment)
future = Time.now.utc + 2.hours
status = subject.call(account, text: 'Hi future!', media_ids: [media.id], scheduled_at: future)
expect(status).to be_a ScheduledStatus
expect(status.scheduled_at).to eq future
expect(status.params['text']).to eq 'Hi future!'
expect(media.reload.status).to be_nil
expect(Status.where(text: 'Hi future!').exists?).to be_falsey
end
it 'creates response to the original status of boost' do
boosted_status = Fabricate(:status)
in_reply_to_status = Fabricate(:status, reblog: boosted_status)
@ -153,7 +167,7 @@ RSpec.describe PostStatusService, type: :service do
it 'attaches the given media to the created status' do
account = Fabricate(:account)
media = Fabricate(:media_attachment)
media = Fabricate(:media_attachment, account: account)
status = subject.call(
account,
@ -164,6 +178,19 @@ RSpec.describe PostStatusService, type: :service do
expect(media.reload.status).to eq status
end
it 'does not attach media from another account to the created status' do
account = Fabricate(:account)
media = Fabricate(:media_attachment, account: Fabricate(:account))
status = subject.call(
account,
text: "test status update",
media_ids: [media.id],
)
expect(media.reload.status).to eq nil
end
it 'does not allow attaching more than 4 files' do
account = Fabricate(:account)