about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTakeshi Umeda <noel.yoshiba@gmail.com>2020-04-19 04:52:39 +0900
committerGitHub <noreply@github.com>2020-04-18 21:52:39 +0200
commit2c7128c7f0ee3073acb9897cda88255982368193 (patch)
treec9036cd0d7a023f0532ad35e9362ebb3f19d2af4
parenta1ce9cbb67facf705379355b9c8ec19c521b419c (diff)
Add local only to hashtag timeline (#13502)
-rw-r--r--app/controllers/tags_controller.rb9
-rw-r--r--app/javascript/mastodon/actions/timelines.js3
-rw-r--r--app/javascript/mastodon/containers/timeline_container.js2
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js7
-rw-r--r--app/javascript/mastodon/features/hashtag_timeline/index.js16
-rw-r--r--app/javascript/mastodon/features/standalone/hashtag_timeline/index.js14
-rw-r--r--app/views/tags/show.html.haml2
7 files changed, 36 insertions, 17 deletions
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index b0bc2f6b7..da0add71a 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -10,6 +10,7 @@ class TagsController < ApplicationController
   before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
   before_action :authenticate_user!, if: :whitelist_mode?
   before_action :set_tag
+  before_action :set_local
   before_action :set_body_classes
   before_action :set_instance_presenter
 
@@ -24,7 +25,7 @@ class TagsController < ApplicationController
       format.rss do
         expires_in 0, public: true
 
-        @statuses = HashtagQueryService.new.call(@tag, filter_params).limit(PAGE_SIZE)
+        @statuses = HashtagQueryService.new.call(@tag, filter_params, nil, @local).limit(PAGE_SIZE)
         @statuses = cache_collection(@statuses, Status)
 
         render xml: RSS::TagSerializer.render(@tag, @statuses)
@@ -33,7 +34,7 @@ class TagsController < ApplicationController
       format.json do
         expires_in 3.minutes, public: public_fetch_mode?
 
-        @statuses = HashtagQueryService.new.call(@tag, filter_params, current_account, params[:local]).paginate_by_max_id(PAGE_SIZE, params[:max_id])
+        @statuses = HashtagQueryService.new.call(@tag, filter_params, current_account, @local).paginate_by_max_id(PAGE_SIZE, params[:max_id])
         @statuses = cache_collection(@statuses, Status)
 
         render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
@@ -47,6 +48,10 @@ class TagsController < ApplicationController
     @tag = Tag.usable.find_normalized!(params[:id])
   end
 
+  def set_local
+    @local = truthy_param?(:local)
+  end
+
   def set_body_classes
     @body_classes = 'with-modals'
   end
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index cdd2111f8..50840cacc 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -113,12 +113,13 @@ export const expandAccountTimeline         = (accountId, { maxId, withReplies }
 export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
 export const expandAccountMediaTimeline    = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
 export const expandListTimeline            = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
-export const expandHashtagTimeline         = (hashtag, { maxId, tags } = {}, done = noOp) => {
+export const expandHashtagTimeline         = (hashtag, { maxId, tags, local } = {}, done = noOp) => {
   return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, {
     max_id: maxId,
     any:    parseTags(tags, 'any'),
     all:    parseTags(tags, 'all'),
     none:   parseTags(tags, 'none'),
+    local:  local,
   }, done);
 };
 
diff --git a/app/javascript/mastodon/containers/timeline_container.js b/app/javascript/mastodon/containers/timeline_container.js
index 54f8eb310..ed8095f90 100644
--- a/app/javascript/mastodon/containers/timeline_container.js
+++ b/app/javascript/mastodon/containers/timeline_container.js
@@ -38,7 +38,7 @@ export default class TimelineContainer extends React.PureComponent {
     let timeline;
 
     if (hashtag) {
-      timeline = <HashtagTimeline hashtag={hashtag} />;
+      timeline = <HashtagTimeline hashtag={hashtag} local={local} />;
     } else {
       timeline = <PublicTimeline local={local} />;
     }
diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js
index 9c39b158a..956f16734 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.js
@@ -4,6 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import Toggle from 'react-toggle';
 import AsyncSelect from 'react-select/async';
+import SettingToggle from '../../notifications/components/setting_toggle';
 
 const messages = defineMessages({
   placeholder: { id: 'hashtag.column_settings.select.placeholder', defaultMessage: 'Enter hashtags…' },
@@ -87,6 +88,8 @@ class ColumnSettings extends React.PureComponent {
   };
 
   render () {
+    const { settings, onChange } = this.props;
+
     return (
       <div>
         <div className='column-settings__row'>
@@ -106,6 +109,10 @@ class ColumnSettings extends React.PureComponent {
             {this.modeSelect('none')}
           </div>
         )}
+
+        <div className='column-settings__row'>
+          <SettingToggle settings={settings} settingPath={['local']} onChange={onChange} label={<FormattedMessage id='community.column_settings.local_only' defaultMessage='Local only' />} />
+        </div>
       </div>
     );
   }
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js
index 28200e6c2..3e06e3652 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.js
@@ -98,21 +98,21 @@ class HashtagTimeline extends React.PureComponent {
 
   componentDidMount () {
     const { dispatch } = this.props;
-    const { id, tags } = this.props.params;
+    const { id, tags, local } = this.props.params;
 
     this._subscribe(dispatch, id, tags);
-    dispatch(expandHashtagTimeline(id, { tags }));
+    dispatch(expandHashtagTimeline(id, { tags, local }));
   }
 
   componentWillReceiveProps (nextProps) {
     const { dispatch, params } = this.props;
-    const { id, tags } = nextProps.params;
+    const { id, tags, local } = nextProps.params;
 
-    if (id !== params.id || !isEqual(tags, params.tags)) {
+    if (id !== params.id || !isEqual(tags, params.tags) || !isEqual(local, params.local)) {
       this._unsubscribe();
       this._subscribe(dispatch, id, tags);
-      this.props.dispatch(clearTimeline(`hashtag:${id}`));
-      this.props.dispatch(expandHashtagTimeline(id, { tags }));
+      dispatch(clearTimeline(`hashtag:${id}`));
+      dispatch(expandHashtagTimeline(id, { tags, local }));
     }
   }
 
@@ -125,8 +125,8 @@ class HashtagTimeline extends React.PureComponent {
   }
 
   handleLoadMore = maxId => {
-    const { id, tags } = this.props.params;
-    this.props.dispatch(expandHashtagTimeline(id, { maxId, tags }));
+    const { id, tags, local } = this.props.params;
+    this.props.dispatch(expandHashtagTimeline(id, { maxId, tags, local }));
   }
 
   render () {
diff --git a/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js b/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js
index 73919c39d..d3d8a6507 100644
--- a/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js
+++ b/app/javascript/mastodon/features/standalone/hashtag_timeline/index.js
@@ -24,19 +24,25 @@ class HashtagTimeline extends React.PureComponent {
     isLoading: PropTypes.bool.isRequired,
     hasMore: PropTypes.bool.isRequired,
     hashtag: PropTypes.string.isRequired,
+    local: PropTypes.bool.isRequired,
+  };
+
+  static defaultProps = {
+    local: false,
   };
 
   componentDidMount () {
-    const { dispatch, hashtag } = this.props;
+    const { dispatch, hashtag, local } = this.props;
 
-    dispatch(expandHashtagTimeline(hashtag));
+    dispatch(expandHashtagTimeline(hashtag, { local }));
   }
 
   handleLoadMore = () => {
-    const maxId = this.props.statusIds.last();
+    const { dispatch, hashtag, local, statusIds } = this.props;
+    const maxId = statusIds.last();
 
     if (maxId) {
-      this.props.dispatch(expandHashtagTimeline(this.props.hashtag, { maxId }));
+      dispatch(expandHashtagTimeline(hashtag, { maxId, local }));
     }
   }
 
diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml
index 630702277..19dadd36a 100644
--- a/app/views/tags/show.html.haml
+++ b/app/views/tags/show.html.haml
@@ -12,5 +12,5 @@
   %h1= "##{@tag.name}"
   %p= t('about.about_hashtag_html', hashtag: @tag.name)
 
-#mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name)) }}
+#mastodon-timeline{ data: { props: Oj.dump(default_props.merge(hashtag: @tag.name, local: @local)) }}
 #modal-container