Added comment sorting
• Added: - comment sorting to comments on status page - new comment sorting options popover, web setting, constants
This commit is contained in:
parent
0364a4000b
commit
260553b7e7
@ -27,7 +27,7 @@ const debouncedSave = debounce((dispatch, getState) => {
|
|||||||
api().put('/api/web/settings', { data })
|
api().put('/api/web/settings', { data })
|
||||||
.then(() => dispatch({ type: SETTING_SAVE }))
|
.then(() => dispatch({ type: SETTING_SAVE }))
|
||||||
.catch(() => { /* */ })
|
.catch(() => { /* */ })
|
||||||
}, 500, { trailing: true })
|
}, 50, { trailing: true })
|
||||||
|
|
||||||
export function saveSettings() {
|
export function saveSettings() {
|
||||||
return (dispatch, getState) => debouncedSave(dispatch, getState)
|
return (dispatch, getState) => debouncedSave(dispatch, getState)
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import { closePopover } from '../../actions/popover'
|
||||||
|
import { changeSetting, saveSettings } from '../../actions/settings'
|
||||||
|
import {
|
||||||
|
COMMENT_SORTING_TYPE_NEWEST,
|
||||||
|
COMMENT_SORTING_TYPE_OLDEST,
|
||||||
|
COMMENT_SORTING_TYPE_TOP,
|
||||||
|
} from '../../constants'
|
||||||
|
import PopoverLayout from './popover_layout'
|
||||||
|
import List from '../list'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
oldest: { id: 'comment_sort.oldest', defaultMessage: 'Oldest' },
|
||||||
|
newest: { id: 'comment_sort.newest', defaultMessage: 'Recent' },
|
||||||
|
top: { id: 'comment_sort.top', defaultMessage: 'Most Liked' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onSetCommentSortingSetting(type) {
|
||||||
|
dispatch(changeSetting(['commentSorting'], type))
|
||||||
|
dispatch(saveSettings())
|
||||||
|
dispatch(closePopover())
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
@connect(null, mapDispatchToProps)
|
||||||
|
class CommentSortingOptionsPopover extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
onSetCommentSortingSetting: PropTypes.func.isRequired,
|
||||||
|
isXS: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnClick = (type) => {
|
||||||
|
this.props.onSetCommentSortingSetting(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl, isXS } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PopoverLayout width={180} isXS={isXS}>
|
||||||
|
<List
|
||||||
|
size='large'
|
||||||
|
scrollKey='comment_sorting_options'
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
hideArrow: true,
|
||||||
|
title: intl.formatMessage(messages.newest),
|
||||||
|
onClick: () => this.handleOnClick(COMMENT_SORTING_TYPE_NEWEST),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hideArrow: true,
|
||||||
|
title: intl.formatMessage(messages.oldest),
|
||||||
|
onClick: () => this.handleOnClick(COMMENT_SORTING_TYPE_OLDEST),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
hideArrow: true,
|
||||||
|
title: intl.formatMessage(messages.top),
|
||||||
|
onClick: () => this.handleOnClick(COMMENT_SORTING_TYPE_TOP),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
small
|
||||||
|
/>
|
||||||
|
</PopoverLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,27 @@
|
|||||||
import {
|
import {
|
||||||
BREAKPOINT_EXTRA_SMALL,
|
BREAKPOINT_EXTRA_SMALL,
|
||||||
|
POPOVER_COMMENT_SORTING_OPTIONS,
|
||||||
POPOVER_DATE_PICKER,
|
POPOVER_DATE_PICKER,
|
||||||
POPOVER_EMOJI_PICKER,
|
POPOVER_EMOJI_PICKER,
|
||||||
POPOVER_GROUP_OPTIONS,
|
POPOVER_GROUP_OPTIONS,
|
||||||
POPOVER_NAV_SETTINGS,
|
POPOVER_NAV_SETTINGS,
|
||||||
POPOVER_PROFILE_OPTIONS,
|
POPOVER_PROFILE_OPTIONS,
|
||||||
POPOVER_REPOST_OPTIONS,
|
|
||||||
POPOVER_SEARCH,
|
POPOVER_SEARCH,
|
||||||
POPOVER_SIDEBAR_MORE,
|
POPOVER_SIDEBAR_MORE,
|
||||||
POPOVER_STATUS_OPTIONS,
|
POPOVER_STATUS_OPTIONS,
|
||||||
POPOVER_STATUS_SHARE,
|
|
||||||
POPOVER_STATUS_VISIBILITY,
|
POPOVER_STATUS_VISIBILITY,
|
||||||
POPOVER_USER_INFO,
|
POPOVER_USER_INFO,
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
import {
|
import {
|
||||||
|
CommentSortingOptionsPopover,
|
||||||
DatePickerPopover,
|
DatePickerPopover,
|
||||||
EmojiPickerPopover,
|
EmojiPickerPopover,
|
||||||
GroupOptionsPopover,
|
GroupOptionsPopover,
|
||||||
NavSettingsPopover,
|
NavSettingsPopover,
|
||||||
ProfileOptionsPopover,
|
ProfileOptionsPopover,
|
||||||
RepostOptionsPopover,
|
|
||||||
SearchPopover,
|
SearchPopover,
|
||||||
SidebarMorePopover,
|
SidebarMorePopover,
|
||||||
StatusOptionsPopover,
|
StatusOptionsPopover,
|
||||||
StatusSharePopover,
|
|
||||||
StatusVisibilityPopover,
|
StatusVisibilityPopover,
|
||||||
UserInfoPopover,
|
UserInfoPopover,
|
||||||
} from '../../features/ui/util/async_components'
|
} from '../../features/ui/util/async_components'
|
||||||
@ -37,16 +35,15 @@ import PopoverBase from './popover_base'
|
|||||||
const initialState = getWindowDimension()
|
const initialState = getWindowDimension()
|
||||||
|
|
||||||
const POPOVER_COMPONENTS = {}
|
const POPOVER_COMPONENTS = {}
|
||||||
|
POPOVER_COMPONENTS[POPOVER_COMMENT_SORTING_OPTIONS] = CommentSortingOptionsPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_DATE_PICKER] = DatePickerPopover
|
POPOVER_COMPONENTS[POPOVER_DATE_PICKER] = DatePickerPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_EMOJI_PICKER] = EmojiPickerPopover
|
POPOVER_COMPONENTS[POPOVER_EMOJI_PICKER] = EmojiPickerPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_GROUP_OPTIONS] = GroupOptionsPopover
|
POPOVER_COMPONENTS[POPOVER_GROUP_OPTIONS] = GroupOptionsPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_NAV_SETTINGS] = NavSettingsPopover
|
POPOVER_COMPONENTS[POPOVER_NAV_SETTINGS] = NavSettingsPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_PROFILE_OPTIONS] = ProfileOptionsPopover
|
POPOVER_COMPONENTS[POPOVER_PROFILE_OPTIONS] = ProfileOptionsPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_REPOST_OPTIONS] = RepostOptionsPopover
|
|
||||||
POPOVER_COMPONENTS[POPOVER_SEARCH] = SearchPopover
|
POPOVER_COMPONENTS[POPOVER_SEARCH] = SearchPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_SIDEBAR_MORE] = SidebarMorePopover
|
POPOVER_COMPONENTS[POPOVER_SIDEBAR_MORE] = SidebarMorePopover
|
||||||
POPOVER_COMPONENTS[POPOVER_STATUS_OPTIONS] = StatusOptionsPopover
|
POPOVER_COMPONENTS[POPOVER_STATUS_OPTIONS] = StatusOptionsPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_STATUS_SHARE] = StatusSharePopover
|
|
||||||
POPOVER_COMPONENTS[POPOVER_STATUS_VISIBILITY] = StatusVisibilityPopover
|
POPOVER_COMPONENTS[POPOVER_STATUS_VISIBILITY] = StatusVisibilityPopover
|
||||||
POPOVER_COMPONENTS[POPOVER_USER_INFO] = UserInfoPopover
|
POPOVER_COMPONENTS[POPOVER_USER_INFO] = UserInfoPopover
|
||||||
|
|
||||||
|
@ -1,25 +1,36 @@
|
|||||||
|
import { Fragment } from 'react'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { HotKeys } from 'react-hotkeys'
|
import { HotKeys } from 'react-hotkeys'
|
||||||
import classNames from 'classnames/bind'
|
import {
|
||||||
|
CX,
|
||||||
|
COMMENT_SORTING_TYPE_NEWEST,
|
||||||
|
COMMENT_SORTING_TYPE_TOP,
|
||||||
|
} from '../constants'
|
||||||
import { me, displayMedia, compactMode } from '../initial_state'
|
import { me, displayMedia, compactMode } from '../initial_state'
|
||||||
import scheduleIdleTask from '../utils/schedule_idle_task'
|
import scheduleIdleTask from '../utils/schedule_idle_task'
|
||||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||||
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
||||||
import ColumnIndicator from './column_indicator'
|
|
||||||
import StatusContent from './status_content'
|
import StatusContent from './status_content'
|
||||||
import StatusPrepend from './status_prepend'
|
import StatusPrepend from './status_prepend'
|
||||||
import StatusActionBar from './status_action_bar'
|
import StatusActionBar from './status_action_bar'
|
||||||
import StatusMedia from './status_media'
|
import StatusMedia from './status_media'
|
||||||
import StatusHeader from './status_header'
|
import StatusHeader from './status_header'
|
||||||
import CommentList from './comment_list'
|
import CommentList from './comment_list'
|
||||||
|
import Button from './button'
|
||||||
|
import Text from './text'
|
||||||
|
|
||||||
// We use the component (and not the container) since we do not want
|
// We use the component (and not the container) since we do not want
|
||||||
// to use the progress bar to show download progress
|
// to use the progress bar to show download progress
|
||||||
import Bundle from '../features/ui/util/bundle'
|
import Bundle from '../features/ui/util/bundle'
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const messages = defineMessages({
|
||||||
|
sortBy: { id: 'comment_sort.title', defaultMessage: 'Sort by' },
|
||||||
|
oldest: { id: 'comment_sort.oldest', defaultMessage: 'Oldest' },
|
||||||
|
newest: { id: 'comment_sort.newest', defaultMessage: 'Recent' },
|
||||||
|
top: { id: 'comment_sort.top', defaultMessage: 'Most Liked' },
|
||||||
|
})
|
||||||
|
|
||||||
export const textForScreenReader = (intl, status, rebloggedByText = false) => {
|
export const textForScreenReader = (intl, status, rebloggedByText = false) => {
|
||||||
if (!intl || !status) return ''
|
if (!intl || !status) return ''
|
||||||
@ -97,7 +108,9 @@ class Status extends ImmutablePureComponent {
|
|||||||
commentsLimited: PropTypes.bool,
|
commentsLimited: PropTypes.bool,
|
||||||
onOpenLikes: PropTypes.func.isRequired,
|
onOpenLikes: PropTypes.func.isRequired,
|
||||||
onOpenReposts: PropTypes.func.isRequired,
|
onOpenReposts: PropTypes.func.isRequired,
|
||||||
|
onCommentSortOpen: PropTypes.func.isRequired,
|
||||||
isComposeModalOpen: PropTypes.bool,
|
isComposeModalOpen: PropTypes.bool,
|
||||||
|
commentSortingType: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid checking props that are functions (and whose equality will always
|
// Avoid checking props that are functions (and whose equality will always
|
||||||
@ -112,6 +125,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
'isHidden',
|
'isHidden',
|
||||||
'isIntersecting',
|
'isIntersecting',
|
||||||
'isComment',
|
'isComment',
|
||||||
|
'commentSortingType',
|
||||||
]
|
]
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -361,11 +375,19 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleOnCommentSortOpen = () => {
|
||||||
|
this.props.onCommentSortOpen(this.commentSortButtonRef)
|
||||||
|
}
|
||||||
|
|
||||||
handleRef = c => {
|
handleRef = c => {
|
||||||
this.node = c
|
this.node = c
|
||||||
this._measureHeight()
|
this._measureHeight()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCommentSortButtonRef = (c) => {
|
||||||
|
this.commentSortButtonRef = c
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
@ -380,6 +402,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
isComment,
|
isComment,
|
||||||
contextType,
|
contextType,
|
||||||
isComposeModalOpen,
|
isComposeModalOpen,
|
||||||
|
commentSortingType,
|
||||||
} = this.props
|
} = this.props
|
||||||
// const { height } = this.state
|
// const { height } = this.state
|
||||||
|
|
||||||
@ -389,7 +412,6 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
if (isComment && !ancestorStatus && !isChild) {
|
if (isComment && !ancestorStatus && !isChild) {
|
||||||
// Wait to load...
|
// Wait to load...
|
||||||
// return <ColumnIndicator type='loading' />
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,6 +430,13 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sortByTitle = intl.formatMessage(messages.oldest)
|
||||||
|
if (commentSortingType === COMMENT_SORTING_TYPE_NEWEST) {
|
||||||
|
sortByTitle = intl.formatMessage(messages.newest)
|
||||||
|
} else if (commentSortingType === COMMENT_SORTING_TYPE_TOP) {
|
||||||
|
sortByTitle = intl.formatMessage(messages.top)
|
||||||
|
}
|
||||||
|
|
||||||
const handlers = (this.props.isMuted || isChild) ? {} : {
|
const handlers = (this.props.isMuted || isChild) ? {} : {
|
||||||
reply: this.handleHotkeyReply,
|
reply: this.handleHotkeyReply,
|
||||||
favorite: this.handleHotkeyFavorite,
|
favorite: this.handleHotkeyFavorite,
|
||||||
@ -421,11 +450,11 @@ class Status extends ImmutablePureComponent {
|
|||||||
toggleSensitive: this.handleHotkeyToggleSensitive,
|
toggleSensitive: this.handleHotkeyToggleSensitive,
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentClasses = cx({
|
const parentClasses = CX({
|
||||||
pb15: !isChild && !compactMode,
|
pb15: !isChild && !compactMode,
|
||||||
})
|
})
|
||||||
|
|
||||||
const containerClasses = cx({
|
const containerClasses = CX({
|
||||||
default: 1,
|
default: 1,
|
||||||
radiusSmall: !isChild && !compactMode,
|
radiusSmall: !isChild && !compactMode,
|
||||||
bgPrimary: !isChild,
|
bgPrimary: !isChild,
|
||||||
@ -436,7 +465,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
borderColorSecondary: !isChild && compactMode,
|
borderColorSecondary: !isChild && compactMode,
|
||||||
})
|
})
|
||||||
|
|
||||||
const containerClassesXS = cx({
|
const containerClassesXS = CX({
|
||||||
default: 1,
|
default: 1,
|
||||||
bgPrimary: !isChild,
|
bgPrimary: !isChild,
|
||||||
boxShadowBlock: !isChild && !compactMode,
|
boxShadowBlock: !isChild && !compactMode,
|
||||||
@ -445,7 +474,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
borderColorSecondary: !isChild,
|
borderColorSecondary: !isChild,
|
||||||
})
|
})
|
||||||
|
|
||||||
const innerContainerClasses = cx({
|
const innerContainerClasses = CX({
|
||||||
default: 1,
|
default: 1,
|
||||||
overflowHidden: 1,
|
overflowHidden: 1,
|
||||||
radiusSmall: isChild,
|
radiusSmall: isChild,
|
||||||
@ -560,17 +589,36 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
{
|
{
|
||||||
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
||||||
|
<Fragment>
|
||||||
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
!commentsLimited &&
|
||||||
|
<div className={[_s.default, _s.px15, _s.py5, _s.mb5, _s.flexRow].join(' ')}>
|
||||||
|
<Text color='secondary' size='small'>
|
||||||
|
{intl.formatMessage(messages.sortBy)}
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
isText
|
||||||
|
backgroundColor='none'
|
||||||
|
color='secondary'
|
||||||
|
className={_s.ml5}
|
||||||
|
buttonRef={this.setCommentSortButtonRef}
|
||||||
|
onClick={this.handleOnCommentSortOpen}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='medium' size='small'>
|
||||||
|
{sortByTitle}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<CommentList
|
<CommentList
|
||||||
ancestorAccountId={status.getIn(['account', 'id'])}
|
ancestorAccountId={status.getIn(['account', 'id'])}
|
||||||
commentsLimited={commentsLimited}
|
commentsLimited={commentsLimited}
|
||||||
descendants={descendantsIds}
|
descendants={descendantsIds}
|
||||||
onViewComments={this.handleClick}
|
onViewComments={this.handleClick}
|
||||||
/>
|
/>
|
||||||
|
</Fragment>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,6 +19,7 @@ export const URL_GAB_PRO = 'https://pro.gab.com'
|
|||||||
|
|
||||||
export const PLACEHOLDER_MISSING_HEADER_SRC = '/original/missing.png'
|
export const PLACEHOLDER_MISSING_HEADER_SRC = '/original/missing.png'
|
||||||
|
|
||||||
|
export const POPOVER_COMMENT_SORTING_OPTIONS = 'COMMENT_SORTING_OPTIONS'
|
||||||
export const POPOVER_DATE_PICKER = 'DATE_PICKER'
|
export const POPOVER_DATE_PICKER = 'DATE_PICKER'
|
||||||
export const POPOVER_EMOJI_PICKER = 'EMOJI_PICKER'
|
export const POPOVER_EMOJI_PICKER = 'EMOJI_PICKER'
|
||||||
export const POPOVER_GROUP_OPTIONS = 'GROUP_OPTIONS'
|
export const POPOVER_GROUP_OPTIONS = 'GROUP_OPTIONS'
|
||||||
@ -63,6 +64,10 @@ export const MODAL_UNAUTHORIZED = 'UNAUTHORIZED'
|
|||||||
export const MODAL_UNFOLLOW = 'UNFOLLOW'
|
export const MODAL_UNFOLLOW = 'UNFOLLOW'
|
||||||
export const MODAL_VIDEO = 'VIDEO'
|
export const MODAL_VIDEO = 'VIDEO'
|
||||||
|
|
||||||
|
export const COMMENT_SORTING_TYPE_NEWEST = 'newest'
|
||||||
|
export const COMMENT_SORTING_TYPE_OLDEST = 'oldest'
|
||||||
|
export const COMMENT_SORTING_TYPE_TOP = 'most-liked'
|
||||||
|
|
||||||
export const FONT_SIZES_EXTRA_SMALL = '12px'
|
export const FONT_SIZES_EXTRA_SMALL = '12px'
|
||||||
export const FONT_SIZES_SMALL = '13px'
|
export const FONT_SIZES_SMALL = '13px'
|
||||||
export const FONT_SIZES_NORMAL = '14px'
|
export const FONT_SIZES_NORMAL = '14px'
|
||||||
|
@ -30,26 +30,69 @@ import {
|
|||||||
import {
|
import {
|
||||||
MODAL_BOOST,
|
MODAL_BOOST,
|
||||||
MODAL_CONFIRM,
|
MODAL_CONFIRM,
|
||||||
|
POPOVER_COMMENT_SORTING_OPTIONS,
|
||||||
|
COMMENT_SORTING_TYPE_OLDEST,
|
||||||
|
COMMENT_SORTING_TYPE_NEWEST,
|
||||||
|
COMMENT_SORTING_TYPE_TOP,
|
||||||
} from '../constants'
|
} from '../constants'
|
||||||
import { makeGetStatus } from '../selectors'
|
import { makeGetStatus } from '../selectors'
|
||||||
import Status from '../components/status';
|
import Status from '../components/status';
|
||||||
|
|
||||||
const getDescendants = (state, status, highlightStatusId) => {
|
|
||||||
|
const sortReplies = (replyIds, state, type) => {
|
||||||
|
if (!replyIds) return replyIds
|
||||||
|
|
||||||
|
if (type === COMMENT_SORTING_TYPE_OLDEST || !type) {
|
||||||
|
return replyIds // default
|
||||||
|
} else if (type === COMMENT_SORTING_TYPE_NEWEST) {
|
||||||
|
return replyIds.reverse()
|
||||||
|
} else if (type === COMMENT_SORTING_TYPE_TOP) {
|
||||||
|
let statusList = []
|
||||||
|
replyIds.forEach((replyId) => {
|
||||||
|
const status = state.getIn(['statuses', replyId])
|
||||||
|
if (status) {
|
||||||
|
statusList.push({
|
||||||
|
id: replyId,
|
||||||
|
likeCount: status.get('favourites_count'),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
statusList.sort((a, b) => parseFloat(b.likeCount) - parseFloat(a.likeCount))
|
||||||
|
|
||||||
|
let newReplyIds = ImmutableList()
|
||||||
|
for (let i = 0; i < statusList.length; i++) {
|
||||||
|
const block = statusList[i];
|
||||||
|
newReplyIds = newReplyIds.set(i, block.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newReplyIds
|
||||||
|
}
|
||||||
|
|
||||||
|
return replyIds
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDescendants = (state, status, highlightStatusId, commentSortingType) => {
|
||||||
let descendantsIds = ImmutableList()
|
let descendantsIds = ImmutableList()
|
||||||
let indent = -1
|
let indent = -1
|
||||||
|
let index = 0
|
||||||
|
|
||||||
descendantsIds = descendantsIds.withMutations(mutable => {
|
descendantsIds = descendantsIds.withMutations(mutable => {
|
||||||
const ids = [status.get('id')]
|
const ids = [status.get('id')]
|
||||||
|
|
||||||
while (ids.length > 0) {
|
while (ids.length > 0) {
|
||||||
let id = ids.shift()
|
let id = ids.shift()
|
||||||
const replies = state.getIn(['contexts', 'replies', id])
|
|
||||||
|
let replies = state.getIn(['contexts', 'replies', id])
|
||||||
|
// Sort only Top-level replies
|
||||||
|
if (index === 0) {
|
||||||
|
replies = sortReplies(replies, state, commentSortingType)
|
||||||
|
}
|
||||||
|
|
||||||
if (status.get('id') !== id) {
|
if (status.get('id') !== id) {
|
||||||
mutable.push(ImmutableMap({
|
mutable.push(ImmutableMap({
|
||||||
statusId: id,
|
statusId: id,
|
||||||
indent: indent,
|
indent: indent,
|
||||||
isHighlighted: highlightStatusId === id,
|
isHighlighted: !!highlightStatusId && highlightStatusId === id,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +105,8 @@ const getDescendants = (state, status, highlightStatusId) => {
|
|||||||
} else {
|
} else {
|
||||||
indent = 0 // reset
|
indent = 0 // reset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -74,6 +119,7 @@ const makeMapStateToProps = () => {
|
|||||||
const mapStateToProps = (state, props) => {
|
const mapStateToProps = (state, props) => {
|
||||||
const statusId = props.id || props.params.statusId
|
const statusId = props.id || props.params.statusId
|
||||||
const username = props.params ? props.params.username : undefined
|
const username = props.params ? props.params.username : undefined
|
||||||
|
const commentSortingType = state.getIn(['settings', 'commentSorting'])
|
||||||
|
|
||||||
const status = getStatus(state, {
|
const status = getStatus(state, {
|
||||||
id: statusId,
|
id: statusId,
|
||||||
@ -113,7 +159,7 @@ const makeMapStateToProps = () => {
|
|||||||
//
|
//
|
||||||
|
|
||||||
if (status && status.get('replies_count') > 0 && !fetchedContext) {
|
if (status && status.get('replies_count') > 0 && !fetchedContext) {
|
||||||
descendantsIds = getDescendants(state, status)
|
descendantsIds = getDescendants(state, status, null, commentSortingType)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isComment = !!status ? !!status.get('in_reply_to_id') : false
|
const isComment = !!status ? !!status.get('in_reply_to_id') : false
|
||||||
@ -123,6 +169,7 @@ const makeMapStateToProps = () => {
|
|||||||
ancestorStatus,
|
ancestorStatus,
|
||||||
descendantsIds,
|
descendantsIds,
|
||||||
isComment,
|
isComment,
|
||||||
|
commentSortingType,
|
||||||
isComposeModalOpen: state.getIn(['modal', 'modalType']) === 'COMPOSE',
|
isComposeModalOpen: state.getIn(['modal', 'modalType']) === 'COMPOSE',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,6 +290,15 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onCommentSortOpen(targetRef, callback) {
|
||||||
|
dispatch(openPopover(POPOVER_COMMENT_SORTING_OPTIONS, {
|
||||||
|
targetRef,
|
||||||
|
callback,
|
||||||
|
position: 'top',
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(makeMapStateToProps, mapDispatchToProps)(Status);
|
export default connect(makeMapStateToProps, mapDispatchToProps)(Status);
|
||||||
|
@ -6,6 +6,7 @@ export function BlockDomainModal() { return import(/* webpackChunkName: "compone
|
|||||||
export function BlockedAccounts() { return import(/* webpackChunkName: "features/blocked_accounts" */'../../blocked_accounts') }
|
export function BlockedAccounts() { return import(/* webpackChunkName: "features/blocked_accounts" */'../../blocked_accounts') }
|
||||||
export function BlockedDomains() { return import(/* webpackChunkName: "features/blocked_domains" */'../../blocked_domains') }
|
export function BlockedDomains() { return import(/* webpackChunkName: "features/blocked_domains" */'../../blocked_domains') }
|
||||||
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
|
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
|
||||||
|
export function CommentSortingOptionsPopover() { return import(/* webpackChunkName: "components/comment_sorting_options_popover" */'../../../components/popover/comment_sorting_options_popover') }
|
||||||
export function CommunityTimeline() { return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline') }
|
export function CommunityTimeline() { return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline') }
|
||||||
export function CommunityTimelineSettingsModal() { return import(/* webpackChunkName: "components/community_timeline_settings_modal" */'../../../components/modal/community_timeline_settings_modal') }
|
export function CommunityTimelineSettingsModal() { return import(/* webpackChunkName: "components/community_timeline_settings_modal" */'../../../components/modal/community_timeline_settings_modal') }
|
||||||
export function Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') }
|
export function Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') }
|
||||||
|
@ -2,6 +2,7 @@ import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings'
|
|||||||
import { STORE_HYDRATE } from '../actions/store'
|
import { STORE_HYDRATE } from '../actions/store'
|
||||||
import { EMOJI_USE } from '../actions/emojis'
|
import { EMOJI_USE } from '../actions/emojis'
|
||||||
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists'
|
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists'
|
||||||
|
import { COMMENT_SORTING_TYPE_OLDEST } from '../constants'
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable'
|
import { Map as ImmutableMap, fromJS } from 'immutable'
|
||||||
import uuid from '../utils/uuid'
|
import uuid from '../utils/uuid'
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ const initialState = ImmutableMap({
|
|||||||
saved: true,
|
saved: true,
|
||||||
onboarded: false,
|
onboarded: false,
|
||||||
skinTone: 1,
|
skinTone: 1,
|
||||||
|
commentSorting: COMMENT_SORTING_TYPE_OLDEST,
|
||||||
|
|
||||||
displayOptions: ImmutableMap({
|
displayOptions: ImmutableMap({
|
||||||
fontSize: 'normal',
|
fontSize: 'normal',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user