about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock12
-rw-r--r--app/javascript/mastodon/containers/status_container.js15
-rw-r--r--app/javascript/mastodon/features/status/index.js15
-rw-r--r--app/lib/language_detector.rb4
-rw-r--r--spec/lib/language_detector_spec.rb10
6 files changed, 49 insertions, 11 deletions
diff --git a/Gemfile b/Gemfile
index 0c4d911c8..66b83cfa1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,7 +5,7 @@ ruby '>= 2.3.0', '< 2.6.0'
 
 gem 'pkg-config', '~> 1.3'
 
-gem 'puma', '~> 3.11'
+gem 'puma', '~> 3.12'
 gem 'rails', '~> 5.2.1'
 gem 'thor', '~> 0.20'
 
@@ -117,7 +117,7 @@ group :test do
   gem 'rspec-sidekiq', '~> 3.0'
   gem 'simplecov', '~> 0.16', require: false
   gem 'webmock', '~> 3.4'
-  gem 'parallel_tests', '~> 2.21'
+  gem 'parallel_tests', '~> 2.23'
 end
 
 group :development do
diff --git a/Gemfile.lock b/Gemfile.lock
index 1dd20f123..1f8243b8f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -373,7 +373,7 @@ GEM
       addressable (~> 2.3)
       nokogiri (~> 1.5)
       omniauth (~> 1.2)
-    omniauth-saml (1.10.0)
+    omniauth-saml (1.10.1)
       omniauth (~> 1.3, >= 1.3.2)
       ruby-saml (~> 1.7)
     orm_adapter (0.5.0)
@@ -392,7 +392,7 @@ GEM
       av (~> 0.9.0)
       paperclip (>= 2.5.2)
     parallel (1.12.1)
-    parallel_tests (2.21.3)
+    parallel_tests (2.23.0)
       parallel
     parser (2.5.1.2)
       ast (~> 2.4.0)
@@ -421,7 +421,7 @@ GEM
     pry-rails (0.3.6)
       pry (>= 0.10.4)
     public_suffix (3.0.3)
-    puma (3.11.4)
+    puma (3.12.0)
     pundit (1.1.0)
       activesupport (>= 3.0.0)
     raabro (1.1.6)
@@ -535,7 +535,7 @@ GEM
       ruby-progressbar (~> 1.7)
       unicode-display_width (~> 1.0, >= 1.0.1)
     ruby-progressbar (1.9.0)
-    ruby-saml (1.7.2)
+    ruby-saml (1.9.0)
       nokogiri (>= 1.5.10)
     rufus-scheduler (3.5.2)
       fugit (~> 1.1, >= 1.1.5)
@@ -724,7 +724,7 @@ DEPENDENCIES
   ox (~> 2.10)
   paperclip (~> 6.0)
   paperclip-av-transcoder (~> 0.6)
-  parallel_tests (~> 2.21)
+  parallel_tests (~> 2.23)
   pg (~> 1.1)
   pghero (~> 2.2)
   pkg-config (~> 1.3)
@@ -733,7 +733,7 @@ DEPENDENCIES
   private_address_check (~> 0.5)
   pry-byebug (~> 3.6)
   pry-rails (~> 0.3)
-  puma (~> 3.11)
+  puma (~> 3.12)
   pundit (~> 1.1)
   rack-attack (~> 5.4)
   rack-cors (~> 1.0)
diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js
index bbc0d5e96..b3555c76e 100644
--- a/app/javascript/mastodon/containers/status_container.js
+++ b/app/javascript/mastodon/containers/status_container.js
@@ -36,6 +36,8 @@ const messages = defineMessages({
   redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
   redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.' },
   blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
+  replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
+  replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
 });
 
 const makeMapStateToProps = () => {
@@ -51,7 +53,18 @@ const makeMapStateToProps = () => {
 const mapDispatchToProps = (dispatch, { intl }) => ({
 
   onReply (status, router) {
-    dispatch(replyCompose(status, router));
+    dispatch((_, getState) => {
+      let state = getState();
+      if (state.getIn(['compose', 'text']).trim().length !== 0) {
+        dispatch(openModal('CONFIRM', {
+          message: intl.formatMessage(messages.replyMessage),
+          confirm: intl.formatMessage(messages.replyConfirm),
+          onConfirm: () => dispatch(replyCompose(status, router)),
+        }));
+      } else {
+        dispatch(replyCompose(status, router));
+      }
+    });
   },
 
   onModalReblog (status) {
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index 7d1bc2ca4..2cd17b805 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -54,6 +54,8 @@ const messages = defineMessages({
   revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
   hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
   detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' },
+  replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
+  replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
 });
 
 const makeMapStateToProps = () => {
@@ -98,6 +100,7 @@ const makeMapStateToProps = () => {
       status,
       ancestorsIds,
       descendantsIds,
+      askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
     };
   };
 
@@ -119,6 +122,7 @@ class Status extends ImmutablePureComponent {
     ancestorsIds: ImmutablePropTypes.list,
     descendantsIds: ImmutablePropTypes.list,
     intl: PropTypes.object.isRequired,
+    askReplyConfirmation: PropTypes.bool,
   };
 
   state = {
@@ -157,7 +161,16 @@ class Status extends ImmutablePureComponent {
   }
 
   handleReplyClick = (status) => {
-    this.props.dispatch(replyCompose(status, this.context.router.history));
+    let { askReplyConfirmation, dispatch, intl } = this.props;
+    if (askReplyConfirmation) {
+      dispatch(openModal('CONFIRM', {
+        message: intl.formatMessage(messages.replyMessage),
+        confirm: intl.formatMessage(messages.replyConfirm),
+        onConfirm: () => dispatch(replyCompose(status, this.context.router.history)),
+      }));
+    } else {
+      dispatch(replyCompose(status, this.context.router.history));
+    }
   }
 
   handleModalReblog = (status) => {
diff --git a/app/lib/language_detector.rb b/app/lib/language_detector.rb
index 688d21fd8..58c8e2069 100644
--- a/app/lib/language_detector.rb
+++ b/app/lib/language_detector.rb
@@ -12,6 +12,7 @@ class LanguageDetector
   def detect(text, account)
     input_text = prepare_text(text)
     return if input_text.blank?
+
     detect_language_code(input_text) || default_locale(account)
   end
 
@@ -33,6 +34,7 @@ class LanguageDetector
 
   def detect_language_code(text)
     return if unreliable_input?(text)
+
     result = @identifier.find_language(text)
     iso6391(result.language.to_s).to_sym if result.reliable?
   end
@@ -75,6 +77,6 @@ class LanguageDetector
   end
 
   def default_locale(account)
-    account.user_locale&.to_sym || I18n.default_locale
+    return account.user_locale&.to_sym || I18n.default_locale if account.local?
   end
 end
diff --git a/spec/lib/language_detector_spec.rb b/spec/lib/language_detector_spec.rb
index cdc51a656..0fa2a59ef 100644
--- a/spec/lib/language_detector_spec.rb
+++ b/spec/lib/language_detector_spec.rb
@@ -42,6 +42,7 @@ describe LanguageDetector do
 
   describe 'detect' do
     let(:account_without_user_locale) { Fabricate(:user, locale: nil).account }
+    let(:account_remote) { Fabricate(:account, domain: 'joinmastodon.org') }
 
     it 'detects english language for basic strings' do
       strings = [
@@ -104,6 +105,15 @@ describe LanguageDetector do
         end
       end
 
+      describe 'remote user' do
+        it 'nil for foreign user when language is not present' do
+          string = '안녕하세요'
+          result = described_class.instance.detect(string, account_remote)
+
+          expect(result).to eq nil
+        end
+      end
+
       describe 'with a non-`en` default locale' do
         around(:each) do |example|
           before = I18n.default_locale