diff options
Diffstat (limited to 'app/javascript')
10 files changed, 58 insertions, 46 deletions
diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js index 79b08bdda..080d665f4 100644 --- a/app/javascript/mastodon/actions/streaming.js +++ b/app/javascript/mastodon/actions/streaming.js @@ -73,7 +73,7 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => { export const connectUserStream = () => connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification); export const connectCommunityStream = ({ onlyMedia } = {}) => connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`); -export const connectPublicStream = ({ onlyMedia } = {}) => connectTimelineStream(`public${onlyMedia ? ':media' : ''}`, `public${onlyMedia ? ':media' : ''}`); +export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) => connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`); export const connectHashtagStream = (id, tag, accept) => connectTimelineStream(`hashtag:${id}`, `hashtag&tag=${tag}`, null, accept); export const connectDirectStream = () => connectTimelineStream('direct', 'direct'); export const connectListStream = id => connectTimelineStream(`list:${id}`, `list&list=${id}`); diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js index 861827d33..01f0fb015 100644 --- a/app/javascript/mastodon/actions/timelines.js +++ b/app/javascript/mastodon/actions/timelines.js @@ -107,7 +107,7 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) { }; export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done); -export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done); +export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, max_id: maxId, only_media: !!onlyMedia }, done); export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done); export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId }); export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true }); diff --git a/app/javascript/mastodon/features/public_timeline/components/column_settings.js b/app/javascript/mastodon/features/public_timeline/components/column_settings.js new file mode 100644 index 000000000..756b6fe06 --- /dev/null +++ b/app/javascript/mastodon/features/public_timeline/components/column_settings.js @@ -0,0 +1,30 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, FormattedMessage } from 'react-intl'; +import SettingToggle from '../../notifications/components/setting_toggle'; + +export default @injectIntl +class ColumnSettings extends React.PureComponent { + + static propTypes = { + settings: ImmutablePropTypes.map.isRequired, + onChange: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + columnId: PropTypes.string, + }; + + render () { + const { settings, onChange } = this.props; + + return ( + <div> + <div className='column-settings__row'> + <SettingToggle settings={settings} settingPath={['other', 'onlyMedia']} onChange={onChange} label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media only' />} /> + <SettingToggle settings={settings} settingPath={['other', 'onlyRemote']} onChange={onChange} label={<FormattedMessage id='community.column_settings.remote_only' defaultMessage='Remote only' />} /> + </div> + </div> + ); + } + +} diff --git a/app/javascript/mastodon/features/public_timeline/containers/column_settings_container.js b/app/javascript/mastodon/features/public_timeline/containers/column_settings_container.js index c56caa59e..8c9e8aef4 100644 --- a/app/javascript/mastodon/features/public_timeline/containers/column_settings_container.js +++ b/app/javascript/mastodon/features/public_timeline/containers/column_settings_container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import ColumnSettings from '../../community_timeline/components/column_settings'; +import ColumnSettings from '../components/column_settings'; import { changeSetting } from '../../../actions/settings'; import { changeColumnParams } from '../../../actions/columns'; diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js index 7aabd7f6e..988b1b070 100644 --- a/app/javascript/mastodon/features/public_timeline/index.js +++ b/app/javascript/mastodon/features/public_timeline/index.js @@ -19,11 +19,13 @@ const mapStateToProps = (state, { columnId }) => { const columns = state.getIn(['settings', 'columns']); const index = columns.findIndex(c => c.get('uuid') === uuid); const onlyMedia = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyMedia']) : state.getIn(['settings', 'public', 'other', 'onlyMedia']); + const onlyRemote = (columnId && index >= 0) ? columns.get(index).getIn(['params', 'other', 'onlyRemote']) : state.getIn(['settings', 'public', 'other', 'onlyRemote']); const timelineState = state.getIn(['timelines', `public${onlyMedia ? ':media' : ''}`]); return { hasUnread: !!timelineState && timelineState.get('unread') > 0, onlyMedia, + onlyRemote, }; }; @@ -47,15 +49,16 @@ class PublicTimeline extends React.PureComponent { multiColumn: PropTypes.bool, hasUnread: PropTypes.bool, onlyMedia: PropTypes.bool, + onlyRemote: PropTypes.bool, }; handlePin = () => { - const { columnId, dispatch, onlyMedia } = this.props; + const { columnId, dispatch, onlyMedia, onlyRemote } = this.props; if (columnId) { dispatch(removeColumn(columnId)); } else { - dispatch(addColumn('PUBLIC', { other: { onlyMedia } })); + dispatch(addColumn(onlyRemote ? 'REMOTE' : 'PUBLIC', { other: { onlyMedia, onlyRemote } })); } } @@ -69,19 +72,19 @@ class PublicTimeline extends React.PureComponent { } componentDidMount () { - const { dispatch, onlyMedia } = this.props; + const { dispatch, onlyMedia, onlyRemote } = this.props; - dispatch(expandPublicTimeline({ onlyMedia })); - this.disconnect = dispatch(connectPublicStream({ onlyMedia })); + dispatch(expandPublicTimeline({ onlyMedia, onlyRemote })); + this.disconnect = dispatch(connectPublicStream({ onlyMedia, onlyRemote })); } componentDidUpdate (prevProps) { - if (prevProps.onlyMedia !== this.props.onlyMedia) { - const { dispatch, onlyMedia } = this.props; + if (prevProps.onlyMedia !== this.props.onlyMedia || prevProps.onlyRemote !== this.props.onlyRemote) { + const { dispatch, onlyMedia, onlyRemote } = this.props; this.disconnect(); - dispatch(expandPublicTimeline({ onlyMedia })); - this.disconnect = dispatch(connectPublicStream({ onlyMedia })); + dispatch(expandPublicTimeline({ onlyMedia, onlyRemote })); + this.disconnect = dispatch(connectPublicStream({ onlyMedia, onlyRemote })); } } @@ -97,13 +100,13 @@ class PublicTimeline extends React.PureComponent { } handleLoadMore = maxId => { - const { dispatch, onlyMedia } = this.props; + const { dispatch, onlyMedia, onlyRemote } = this.props; - dispatch(expandPublicTimeline({ maxId, onlyMedia })); + dispatch(expandPublicTimeline({ maxId, onlyMedia, onlyRemote })); } render () { - const { intl, shouldUpdateScroll, columnId, hasUnread, multiColumn, onlyMedia } = this.props; + const { intl, shouldUpdateScroll, columnId, hasUnread, multiColumn, onlyMedia, onlyRemote } = this.props; const pinned = !!columnId; return ( @@ -122,7 +125,7 @@ class PublicTimeline extends React.PureComponent { </ColumnHeader> <StatusListContainer - timelineId={`public${onlyMedia ? ':media' : ''}`} + timelineId={`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`} onLoadMore={this.handleLoadMore} trackScroll={!pinned} scrollKey={`public_timeline-${columnId}`} diff --git a/app/javascript/mastodon/features/ui/components/__tests__/column-test.js b/app/javascript/mastodon/features/ui/components/__tests__/column-test.js index 89cb2458d..d2791ce08 100644 --- a/app/javascript/mastodon/features/ui/components/__tests__/column-test.js +++ b/app/javascript/mastodon/features/ui/components/__tests__/column-test.js @@ -5,30 +5,21 @@ import ColumnHeader from '../column_header'; describe('<Column />', () => { describe('<ColumnHeader /> click handler', () => { - const originalRaf = global.requestAnimationFrame; - - beforeEach(() => { - global.requestAnimationFrame = jest.fn(); - }); - - afterAll(() => { - global.requestAnimationFrame = originalRaf; - }); - it('runs the scroll animation if the column contains scrollable content', () => { const wrapper = mount( <Column heading='notifications'> <div className='scrollable' /> </Column>, ); + const scrollToMock = jest.fn(); + wrapper.find(Column).find('.scrollable').getDOMNode().scrollTo = scrollToMock; wrapper.find(ColumnHeader).find('button').simulate('click'); - expect(global.requestAnimationFrame.mock.calls.length).toEqual(1); + expect(scrollToMock).toHaveBeenCalledWith({ behavior: 'smooth', top: 0 }); }); it('does not try to scroll if there is no scrollable content', () => { const wrapper = mount(<Column heading='notifications' />); wrapper.find(ColumnHeader).find('button').simulate('click'); - expect(global.requestAnimationFrame.mock.calls.length).toEqual(0); }); }); }); diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js index 8bc4bfc0e..9b03cf26d 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.js +++ b/app/javascript/mastodon/features/ui/components/columns_area.js @@ -37,6 +37,7 @@ const componentMap = { 'HOME': HomeTimeline, 'NOTIFICATIONS': Notifications, 'PUBLIC': PublicTimeline, + 'REMOTE': PublicTimeline, 'COMMUNITY': CommunityTimeline, 'HASHTAG': HashtagTimeline, 'DIRECT': DirectTimeline, diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index 711f34965..3be0aee49 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -543,12 +543,6 @@ $small-breakpoint: 960px; flex: 0 0 auto; } - &__avatar { - width: 44px; - height: 44px; - background-size: 44px 44px; - } - .display-name { font-size: 15px; @@ -749,12 +743,6 @@ $small-breakpoint: 960px; display: flex; align-items: center; } - - .account__avatar { - width: 44px; - height: 44px; - background-size: 44px 44px; - } } &__counters__wrapper { diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 6c33b709d..65a3bab8d 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -1318,8 +1318,13 @@ .account__avatar { @include avatar-radius; + display: block; position: relative; + width: 36px; + height: 36px; + background-size: 36px 36px; + &-inline { display: inline-block; vertical-align: middle; diff --git a/app/javascript/styles/mastodon/widgets.scss b/app/javascript/styles/mastodon/widgets.scss index ca050a8d9..5b97d1ec4 100644 --- a/app/javascript/styles/mastodon/widgets.scss +++ b/app/javascript/styles/mastodon/widgets.scss @@ -93,12 +93,6 @@ display: flex; align-items: center; } - - .account__avatar { - width: 44px; - height: 44px; - background-size: 44px 44px; - } } .trends__item { |