diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bafbe1e9e1114..cfb6b15f5aea9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b55729a9ba2da8..65366be5f34d52 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. diff --git a/Gemfile b/Gemfile index d17ff1a51c3820..8266488f89fe66 100644 --- a/Gemfile +++ b/Gemfile @@ -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' diff --git a/Gemfile.lock b/Gemfile.lock index acb4b8dda98fe5..7b8ffec9ad2419 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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) diff --git a/README.md b/README.md index 6c4918e6f237bd..5ad6894ca7332a 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js index 44da423adcd6fd..97efff69c85208 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.js +++ b/app/javascript/mastodon/features/notifications/components/notification.js @@ -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, }; } diff --git a/app/javascript/mastodon/features/notifications/containers/notification_container.js b/app/javascript/mastodon/features/notifications/containers/notification_container.js index 921aa460f522b0..78576c760cbe54 100644 --- a/app/javascript/mastodon/features/notifications/containers/notification_container.js +++ b/app/javascript/mastodon/features/notifications/containers/notification_container.js @@ -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); diff --git a/app/javascript/mastodon/features/video/index.js b/app/javascript/mastodon/features/video/index.js index 3650fddb630e6d..0d0c24d7194ee8 100644 --- a/app/javascript/mastodon/features/video/index.js +++ b/app/javascript/mastodon/features/video/index.js @@ -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} /> - +
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 diff --git a/app/services/verify_link_service.rb b/app/services/verify_link_service.rb index c6557876137f77..878a2188dc3039 100644 --- a/app/services/verify_link_service.rb +++ b/app/services/verify_link_service.rb @@ -10,7 +10,7 @@ def call(field) 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 diff --git a/db/migrate/20181116173541_copy_account_stats.rb b/db/migrate/20181116173541_copy_account_stats.rb index bb523fbbd31c3f..8e27eb11b57d71 100644 --- a/db/migrate/20181116173541_copy_account_stats.rb +++ b/db/migrate/20181116173541_copy_account_stats.rb @@ -44,7 +44,7 @@ def up_slow # 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 diff --git a/lib/mastodon/migration_helpers.rb b/lib/mastodon/migration_helpers.rb index f5dc7e1c6ec15c..146eba8ec66e19 100644 --- a/lib/mastodon/migration_helpers.rb +++ b/lib/mastodon/migration_helpers.rb @@ -889,7 +889,7 @@ def check_trigger_permissions!(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: diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb index abbc31178d2d57..cf32e2f637dee0 100644 --- a/lib/mastodon/version.rb +++ b/lib/mastodon/version.rb @@ -13,7 +13,7 @@ def minor end def patch - 0 + 1 end def pre diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 3774fed6f3e8a6..facbe977f23330 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -36,6 +36,20 @@ 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 @@ 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 @@ 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)