forked from mastodon/mastodon
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
update hashtags timeline to only imastodon
for mastodon#8904
- Loading branch information
Showing
11 changed files
with
349 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
app/javascript/mastodon/features/imas_hashtag_timeline/components/column_settings.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import ImmutablePropTypes from 'react-immutable-proptypes'; | ||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | ||
import Button from '../../../components/button'; | ||
import SettingToggle from '../components/setting_toggle'; | ||
import SettingText from '../components/setting_text'; | ||
import { Map as ImmutableMap } from 'immutable'; | ||
|
||
const messages = defineMessages({ | ||
filter_regex: { id: 'tag.column_settings.filter_regex', defaultMessage: 'Filter out by regular expressions' }, | ||
show_local_only: { id: 'tag.column_settings.show_local_only', defaultMessage: 'Show local only' }, | ||
settings: { id: 'tag.settings', defaultMessage: 'Column settings' }, | ||
add_favourite_tags_public: { id: 'tag.add_favourite.public', defaultMessage: 'add in the favourite tags (Public)' }, | ||
add_favourite_tags_unlisted: { id: 'tag.add_favourite.unlisted', defaultMessage: 'add in the favourite tags (Unlisted)' }, | ||
remove_favourite_tags: { id: 'tag.remove_favourite', defaultMessage: 'Remove from the favourite tags' }, | ||
}); | ||
|
||
@injectIntl | ||
export default class ColumnSettings extends React.PureComponent { | ||
|
||
static propTypes = { | ||
tag: PropTypes.string.isRequired, | ||
settings: ImmutablePropTypes.map.isRequired, | ||
onChange: PropTypes.func.isRequired, | ||
addFavouriteTags: PropTypes.func.isRequired, | ||
removeFavouriteTags: PropTypes.func.isRequired, | ||
isRegistered: PropTypes.bool.isRequired, | ||
intl: PropTypes.object.isRequired, | ||
}; | ||
|
||
addFavouriteTags = (visibility) => { | ||
this.props.addFavouriteTags(this.props.tag, visibility); | ||
}; | ||
|
||
addPublic = () => { | ||
this.addFavouriteTags('public'); | ||
}; | ||
|
||
addUnlisted = () => { | ||
this.addFavouriteTags('unlisted'); | ||
}; | ||
|
||
removeFavouriteTags = () => { | ||
this.props.removeFavouriteTags(this.props.tag); | ||
}; | ||
|
||
render () { | ||
const { tag, settings, onChange, intl, isRegistered } = this.props; | ||
const initialSettings = ImmutableMap({ | ||
shows: ImmutableMap({ | ||
local: false, | ||
}), | ||
|
||
regex: ImmutableMap({ | ||
body: '', | ||
}), | ||
}); | ||
|
||
const favouriteTagButton = (isRegistered) => { | ||
if(isRegistered) { | ||
return ( | ||
<div className='column-settings__row'> | ||
<Button className='favourite-tags__remove-button-in-column' text={intl.formatMessage(messages.remove_favourite_tags)} onClick={this.removeFavouriteTags} block /> | ||
</div> | ||
); | ||
} else { | ||
return ( | ||
<div className='column-settings__row'> | ||
<Button className='favourite-tags__add-button-in-column' text={intl.formatMessage(messages.add_favourite_tags_public)} onClick={this.addPublic} block /> | ||
<Button className='favourite-tags__add-button-in-column' text={intl.formatMessage(messages.add_favourite_tags_unlisted)} onClick={this.addUnlisted} block /> | ||
</div> | ||
); | ||
} | ||
}; | ||
|
||
return ( | ||
<div> | ||
{favouriteTagButton(isRegistered)} | ||
<span className='column-settings__section'><FormattedMessage id='tag.column_settings.basic' defaultMessage='Basic' /></span> | ||
|
||
<div className='column-settings__row'> | ||
<SettingToggle tag={tag} prefix='hashtag_timeline' settings={settings.get(`${tag}`, initialSettings)} settingKey={['shows', 'local']} onChange={onChange} label={intl.formatMessage(messages.show_local_only)} /> | ||
</div> | ||
|
||
<span className='column-settings__section'><FormattedMessage id='tag.column_settings.advanced' defaultMessage='Advanced' /></span> | ||
|
||
<div className='column-settings__row'> | ||
<SettingText tag={tag} prefix='hashtag_timeline' settings={settings.get(`${tag}`, initialSettings)} settingKey={['regex', 'body']} onChange={onChange} label={intl.formatMessage(messages.filter_regex)} /> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
} |
File renamed without changes.
File renamed without changes.
31 changes: 31 additions & 0 deletions
31
...avascript/mastodon/features/imas_hashtag_timeline/containers/column_settings_container.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { connect } from 'react-redux'; | ||
import ColumnSettings from '../components/column_settings'; | ||
import { changeSetting, saveSettings } from '../../../actions/settings'; | ||
import { addFavouriteTags, removeFavouriteTags } from '../../../actions/favourite_tags'; | ||
|
||
const mapStateToProps = (state, { tag }) => ({ | ||
settings: state.getIn(['settings', 'tag']), | ||
isRegistered: state.getIn(['favourite_tags', 'tags']).some(t => t.get('name') === tag), | ||
}); | ||
|
||
const mapDispatchToProps = dispatch => ({ | ||
|
||
onChange (tag, key, checked) { | ||
dispatch(changeSetting(['tag', `${tag}`, ...key], checked)); | ||
}, | ||
|
||
onSave () { | ||
dispatch(saveSettings()); | ||
}, | ||
|
||
addFavouriteTags (tag, visibility) { | ||
dispatch(addFavouriteTags(tag, visibility)); | ||
}, | ||
|
||
removeFavouriteTags (tag) { | ||
dispatch(removeFavouriteTags(tag)); | ||
}, | ||
|
||
}); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings); |
File renamed without changes.
126 changes: 126 additions & 0 deletions
126
app/javascript/mastodon/features/imas_hashtag_timeline/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import React from 'react'; | ||
import { connect } from 'react-redux'; | ||
import PropTypes from 'prop-types'; | ||
import StatusListContainer from './containers/status_list_container'; | ||
import Column from '../../components/column'; | ||
import ColumnHeader from '../../components/column_header'; | ||
import ColumnSettingsContainer from './containers/column_settings_container'; | ||
import { expandHashtagTimeline } from '../../actions/timelines'; | ||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { connectHashtagStream } from '../../actions/streaming'; | ||
import { isEqual } from 'lodash'; | ||
|
||
const mapStateToProps = (state, props) => ({ | ||
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0, | ||
isLocal: state.getIn(['settings', 'tag', `${props.params.id}`, 'shows', 'local'], false), | ||
}); | ||
|
||
export default @connect(mapStateToProps) | ||
class HashtagTimeline extends React.PureComponent { | ||
|
||
disconnects = []; | ||
|
||
static propTypes = { | ||
params: PropTypes.object.isRequired, | ||
columnId: PropTypes.string, | ||
dispatch: PropTypes.func.isRequired, | ||
shouldUpdateScroll: PropTypes.func, | ||
hasUnread: PropTypes.bool, | ||
multiColumn: PropTypes.bool, | ||
isLocal: PropTypes.bool, | ||
}; | ||
|
||
handlePin = () => { | ||
const { columnId, dispatch } = this.props; | ||
|
||
if (columnId) { | ||
dispatch(removeColumn(columnId)); | ||
} else { | ||
dispatch(addColumn('HASHTAG', { id: this.props.params.id })); | ||
} | ||
} | ||
|
||
handleMove = (dir) => { | ||
const { columnId, dispatch } = this.props; | ||
dispatch(moveColumn(columnId, dir)); | ||
} | ||
|
||
handleHeaderClick = () => { | ||
this.column.scrollTop(); | ||
} | ||
|
||
_subscribe (dispatch, id, isLocal) { | ||
this.disconnect = dispatch(connectHashtagStream(id, isLocal)); | ||
} | ||
|
||
_unsubscribe () { | ||
this.disconnects.map(disconnect => disconnect()); | ||
this.disconnects = []; | ||
} | ||
|
||
componentDidMount () { | ||
const { dispatch, isLocal } = this.props; | ||
const { id } = this.props.params; | ||
|
||
dispatch(expandHashtagTimeline(id, isLocal)); | ||
this._subscribe(dispatch, id, isLocal); | ||
} | ||
|
||
componentWillReceiveProps (nextProps) { | ||
if (nextProps.params.id !== this.props.params.id || nextProps.isLocal !== this.props.isLocal) { | ||
this.props.dispatch(expandHashtagTimeline(nextProps.params.id, nextProps.isLocal)); | ||
this._unsubscribe(); | ||
this._subscribe(this.props.dispatch, nextProps.params.id, nextProps.isLocal); | ||
} | ||
} | ||
|
||
componentWillUnmount () { | ||
this._unsubscribe(); | ||
} | ||
|
||
setRef = c => { | ||
this.column = c; | ||
} | ||
|
||
handleLoadMore = maxId => { | ||
this.props.dispatch(expandHashtagTimeline(this.props.params.id, { maxId, isLocal: this.props.isLocal })); | ||
} | ||
|
||
render () { | ||
const { shouldUpdateScroll, hasUnread, columnId, multiColumn } = this.props; | ||
const { id } = this.props.params; | ||
const pinned = !!columnId; | ||
|
||
return ( | ||
<Column ref={this.setRef} label={`#${id}`}> | ||
<ColumnHeader | ||
icon='hashtag' | ||
active={hasUnread} | ||
title={id} | ||
onPin={this.handlePin} | ||
onMove={this.handleMove} | ||
onClick={this.handleHeaderClick} | ||
pinned={pinned} | ||
multiColumn={multiColumn} | ||
showBackButton | ||
> | ||
<ColumnSettingsContainer | ||
tag={id} | ||
/> | ||
</ColumnHeader> | ||
|
||
<StatusListContainer | ||
tag={id} | ||
trackScroll={!pinned} | ||
scrollKey={`hashtag_timeline-${columnId}`} | ||
timelineId={`hashtag:${id}`} | ||
onLoadMore={this.handleLoadMore} | ||
emptyMessage={<FormattedMessage id='empty_column.hashtag' defaultMessage='There is nothing in this hashtag yet.' />} | ||
shouldUpdateScroll={shouldUpdateScroll} | ||
/> | ||
</Column> | ||
); | ||
} | ||
|
||
} |
93 changes: 93 additions & 0 deletions
93
app/javascript/mastodon/features/standalone/imas_hashtag_timeline/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import React from 'react'; | ||
import { connect } from 'react-redux'; | ||
import PropTypes from 'prop-types'; | ||
import ImmutablePropTypes from 'react-immutable-proptypes'; | ||
import { expandHashtagTimeline } from '../../../actions/timelines'; | ||
import { connectHashtagStream } from '../../../actions/streaming'; | ||
import Masonry from 'react-masonry-infinite'; | ||
import { List as ImmutableList } from 'immutable'; | ||
import DetailedStatusContainer from '../../status/containers/detailed_status_container'; | ||
import { debounce } from 'lodash'; | ||
import LoadingIndicator from '../../../components/loading_indicator'; | ||
|
||
const mapStateToProps = (state, { hashtag }) => ({ | ||
statusIds: state.getIn(['timelines', `hashtag:${hashtag}`, 'items'], ImmutableList()), | ||
isLoading: state.getIn(['timelines', `hashtag:${hashtag}`, 'isLoading'], false), | ||
hasMore: state.getIn(['timelines', `hashtag:${hashtag}`, 'hasMore'], false), | ||
}); | ||
|
||
export default @connect(mapStateToProps) | ||
class HashtagTimeline extends React.PureComponent { | ||
|
||
static propTypes = { | ||
dispatch: PropTypes.func.isRequired, | ||
statusIds: ImmutablePropTypes.list.isRequired, | ||
isLoading: PropTypes.bool.isRequired, | ||
hasMore: PropTypes.bool.isRequired, | ||
hashtag: PropTypes.string.isRequired, | ||
}; | ||
|
||
componentDidMount () { | ||
const { dispatch, hashtag } = this.props; | ||
|
||
dispatch(expandHashtagTimeline(hashtag)); | ||
this.disconnect = dispatch(connectHashtagStream(hashtag, hashtag)); | ||
} | ||
|
||
componentWillUnmount () { | ||
if (this.disconnect) { | ||
this.disconnect(); | ||
this.disconnect = null; | ||
} | ||
} | ||
|
||
handleLoadMore = () => { | ||
const maxId = this.props.statusIds.last(); | ||
|
||
if (maxId) { | ||
this.props.dispatch(expandHashtagTimeline(this.props.hashtag, { maxId })); | ||
} | ||
} | ||
|
||
setRef = c => { | ||
this.masonry = c; | ||
} | ||
|
||
handleHeightChange = debounce(() => { | ||
if (!this.masonry) { | ||
return; | ||
} | ||
|
||
this.masonry.forcePack(); | ||
}, 50) | ||
|
||
render () { | ||
const { statusIds, hasMore, isLoading } = this.props; | ||
|
||
const sizes = [ | ||
{ columns: 1, gutter: 0 }, | ||
{ mq: '415px', columns: 1, gutter: 10 }, | ||
{ mq: '640px', columns: 2, gutter: 10 }, | ||
{ mq: '960px', columns: 3, gutter: 10 }, | ||
{ mq: '1255px', columns: 3, gutter: 10 }, | ||
]; | ||
|
||
const loader = (isLoading && statusIds.isEmpty()) ? <LoadingIndicator key={0} /> : undefined; | ||
|
||
return ( | ||
<Masonry ref={this.setRef} className='statuses-grid' hasMore={hasMore} loadMore={this.handleLoadMore} sizes={sizes} loader={loader}> | ||
{statusIds.map(statusId => ( | ||
<div className='statuses-grid__item' key={statusId}> | ||
<DetailedStatusContainer | ||
id={statusId} | ||
compact | ||
measureHeight | ||
onHeightChange={this.handleHeightChange} | ||
/> | ||
</div> | ||
)).toArray()} | ||
</Masonry> | ||
); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters