diff --git a/Gemfile b/Gemfile index 2427217331..02cd3c73b6 100644 --- a/Gemfile +++ b/Gemfile @@ -29,7 +29,7 @@ gem 'browser' gem 'charlock_holmes', '~> 0.7.6' gem 'iso-639' gem 'chewy', '~> 5.0' -gem 'cld3', '~> 3.2.3' +gem 'cld3', '~> 3.2.4' gem 'devise', '~> 4.6' gem 'devise-two-factor', '~> 3.0' @@ -42,7 +42,7 @@ gem 'omniauth-cas', '~> 1.1' gem 'omniauth-saml', '~> 1.10' gem 'omniauth', '~> 1.9' -gem 'doorkeeper', '~> 5.0' +gem 'doorkeeper', '~> 5.1' gem 'fast_blank', '~> 1.0' gem 'fastimage' gem 'goldfinger', '~> 2.1' @@ -143,7 +143,7 @@ group :development do end group :production do - gem 'lograge', '~> 0.10' + gem 'lograge', '~> 0.11' gem 'redis-rails', '~> 5.0' end diff --git a/Gemfile.lock b/Gemfile.lock index 6b362fefb0..e0fedab877 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,16 +76,16 @@ GEM av (0.9.0) cocaine (~> 0.5.3) aws-eventstream (1.0.2) - aws-partitions (1.147.0) - aws-sdk-core (3.48.3) + aws-partitions (1.151.0) + aws-sdk-core (3.48.4) aws-eventstream (~> 1.0, >= 1.0.2) aws-partitions (~> 1.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.16.0) + aws-sdk-kms (1.17.0) aws-sdk-core (~> 3, >= 3.48.2) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.36.0) + aws-sdk-s3 (1.36.1) aws-sdk-core (~> 3, >= 3.48.2) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.0) @@ -143,8 +143,8 @@ GEM elasticsearch (>= 2.0.0) elasticsearch-dsl chunky_png (1.3.10) - cld3 (3.2.3) - ffi (>= 1.1.0, < 1.10.0) + cld3 (3.2.4) + ffi (>= 1.1.0, < 1.11.0) climate_control (0.2.0) cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) @@ -184,8 +184,8 @@ GEM docile (1.3.0) domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) - doorkeeper (5.0.2) - railties (>= 4.2) + doorkeeper (5.1.0) + railties (>= 5) dotenv (2.7.2) dotenv-rails (2.7.2) dotenv (= 2.7.2) @@ -212,7 +212,7 @@ GEM multipart-post (>= 1.2, < 3) fast_blank (1.0.0) fastimage (2.1.5) - ffi (1.9.25) + ffi (1.10.0) fog-core (2.1.0) builder excon (~> 0.58) @@ -320,7 +320,7 @@ GEM letter_opener (~> 1.0) railties (>= 3.2) link_header (0.0.8) - lograge (0.10.0) + lograge (0.11.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) @@ -642,7 +642,7 @@ GEM activesupport (>= 4.2) rack-proxy (>= 0.6.1) railties (>= 4.2) - webpush (0.3.7) + webpush (0.3.8) hkdf (~> 0.2) jwt (~> 2.0) websocket-driver (0.7.0) @@ -675,14 +675,14 @@ DEPENDENCIES capybara (~> 3.16) charlock_holmes (~> 0.7.6) chewy (~> 5.0) - cld3 (~> 3.2.3) + cld3 (~> 3.2.4) climate_control (~> 0.2) concurrent-ruby derailed_benchmarks devise (~> 4.6) devise-two-factor (~> 3.0) devise_pam_authenticatable2 (~> 9.2) - doorkeeper (~> 5.0) + doorkeeper (~> 5.1) dotenv-rails (~> 2.7) fabrication (~> 2.20) faker (~> 1.9) @@ -709,7 +709,7 @@ DEPENDENCIES letter_opener (~> 1.7) letter_opener_web (~> 1.3) link_header (~> 0.0) - lograge (~> 0.10) + lograge (~> 0.11) makara (~> 0.4) mario-redis-lock (~> 1.2) memory_profiler diff --git a/app/javascript/core/public.js b/app/javascript/core/public.js index f00709dad0..4be75647af 100644 --- a/app/javascript/core/public.js +++ b/app/javascript/core/public.js @@ -41,3 +41,26 @@ delegate(document, '.modal-button', 'click', e => { window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); }); + +const getProfileAvatarAnimationHandler = (swapTo) => { + //animate avatar gifs on the profile page when moused over + return ({ target }) => { + const swapSrc = target.getAttribute(swapTo); + //only change the img source if autoplay is off and the image src is actually different + if(target.getAttribute('data-autoplay') === 'false' && target.src !== swapSrc) { + target.src = swapSrc; + } + }; +}; + +delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original')); + +delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static')); + +delegate(document, '#account_header', 'change', ({ target }) => { + const header = document.querySelector('.card .card__img img'); + const [file] = target.files || []; + const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc; + + header.src = url; +}); diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js index d47b788ce1..13514fa0ff 100644 --- a/app/javascript/mastodon/features/compose/components/compose_form.js +++ b/app/javascript/mastodon/features/compose/components/compose_form.js @@ -41,17 +41,16 @@ class ComposeForm extends ImmutablePureComponent { static propTypes = { intl: PropTypes.object.isRequired, text: PropTypes.string.isRequired, - suggestion_token: PropTypes.string, suggestions: ImmutablePropTypes.list, spoiler: PropTypes.bool, privacy: PropTypes.string, - spoiler_text: PropTypes.string, + spoilerText: PropTypes.string, focusDate: PropTypes.instanceOf(Date), caretPosition: PropTypes.number, preselectDate: PropTypes.instanceOf(Date), - is_submitting: PropTypes.bool, - is_changing_upload: PropTypes.bool, - is_uploading: PropTypes.bool, + isSubmitting: PropTypes.bool, + isChangingUpload: PropTypes.bool, + isUploading: PropTypes.bool, onChange: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired, onClearSuggestions: PropTypes.func.isRequired, @@ -86,10 +85,10 @@ class ComposeForm extends ImmutablePureComponent { } // Submit disabled: - const { is_submitting, is_changing_upload, is_uploading, anyMedia } = this.props; - const fulltext = [this.props.spoiler_text, countableText(this.props.text)].join(''); + const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props; + const fulltext = [this.props.spoilerText, countableText(this.props.text)].join(''); - if (is_submitting || is_uploading || is_changing_upload || length(fulltext) > maxChars || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { + if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxChars || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { return; } @@ -134,7 +133,7 @@ class ComposeForm extends ImmutablePureComponent { this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd); this.autosuggestTextarea.textarea.focus(); - } else if(prevProps.is_submitting && !this.props.is_submitting) { + } else if(prevProps.isSubmitting && !this.props.isSubmitting) { this.autosuggestTextarea.textarea.focus(); } else if (this.props.spoiler !== prevProps.spoiler) { if (this.props.spoiler) { @@ -163,9 +162,9 @@ class ComposeForm extends ImmutablePureComponent { render () { const { intl, onPaste, showSearch, anyMedia } = this.props; - const disabled = this.props.is_submitting; - const text = [this.props.spoiler_text, countableText(this.props.text)].join(''); - const disabledButton = disabled || this.props.is_uploading || this.props.is_changing_upload || length(text) > maxChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia); + const disabled = this.props.isSubmitting; + const text = [this.props.spoilerText, countableText(this.props.text)].join(''); + const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxChars || (text.length !== 0 && text.trim().length === 0 && !anyMedia); let publishText = ''; if (this.props.privacy === 'private' || this.props.privacy === 'direct') { @@ -183,7 +182,7 @@ class ComposeForm extends ImmutablePureComponent {
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.js b/app/javascript/mastodon/features/compose/components/poll_form.js index 4fb95f3c9f..383e37eb65 100644 --- a/app/javascript/mastodon/features/compose/components/poll_form.js +++ b/app/javascript/mastodon/features/compose/components/poll_form.js @@ -26,6 +26,7 @@ class Option extends React.PureComponent { isPollMultiple: PropTypes.bool, onChange: PropTypes.func.isRequired, onRemove: PropTypes.func.isRequired, + onToggleMultiple: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; @@ -37,13 +38,24 @@ class Option extends React.PureComponent { this.props.onRemove(this.props.index); }; + handleToggleMultiple = e => { + this.props.onToggleMultiple(); + e.preventDefault(); + e.stopPropagation(); + }; + render () { const { isPollMultiple, title, index, intl } = this.props; return (