Albums almost done, group, chat moderation, photo, video page updates
This commit is contained in:
mgabdev
2020-12-21 13:25:05 -05:00
parent a2ffbadedb
commit ee91809e8d
45 changed files with 1013 additions and 509 deletions

View File

@@ -7,10 +7,23 @@ export const ALBUMS_FETCH_REQUEST = 'ALBUMS_FETCH_REQUEST'
export const ALBUMS_FETCH_SUCCESS = 'ALBUMS_FETCH_SUCCESS'
export const ALBUMS_FETCH_FAIL = 'ALBUMS_FETCH_FAIL'
export const ALBUMS_CREATE_REQUEST = 'ALBUMS_CREATE_REQUEST'
export const ALBUMS_CREATE_SUCCESS = 'ALBUMS_CREATE_SUCCESS'
export const ALBUMS_CREATE_FAIL = 'ALBUMS_CREATE_FAIL'
export const ALBUMS_EXPAND_REQUEST = 'ALBUMS_EXPAND_REQUEST'
export const ALBUMS_EXPAND_SUCCESS = 'ALBUMS_EXPAND_SUCCESS'
export const ALBUMS_EXPAND_FAIL = 'ALBUMS_EXPAND_FAIL'
export const ALBUM_CREATE_REQUEST = 'ALBUM_CREATE_REQUEST'
export const ALBUM_CREATE_SUCCESS = 'ALBUM_CREATE_SUCCESS'
export const ALBUM_CREATE_FAIL = 'ALBUM_CREATE_FAIL'
export const ALBUM_REMOVE_REQUEST = 'ALBUM_REMOVE_REQUEST'
export const ALBUM_REMOVE_SUCCESS = 'ALBUM_REMOVE_SUCCESS'
export const ALBUM_REMOVE_FAIL = 'ALBUM_REMOVE_FAIL'
export const ALBUM_EDIT_REQUEST = 'ALBUM_EDIT_REQUEST'
export const ALBUM_EDIT_SUCCESS = 'ALBUM_EDIT_SUCCESS'
export const ALBUM_EDIT_FAIL = 'ALBUM_EDIT_FAIL'
export const ALBUM_UPDATE_MEDIA_REQUEST = 'ALBUM_UPDATE_MEDIA_REQUEST'
export const ALBUM_UPDATE_MEDIA_SUCCESS = 'ALBUM_UPDATE_MEDIA_SUCCESS'
export const ALBUM_UPDATE_MEDIA_FAIL = 'ALBUM_UPDATE_MEDIA_FAIL'
export const ALBUMS_REMOVE_REQUEST = 'ALBUMS_REMOVE_REQUEST'
export const ALBUMS_REMOVE_SUCCESS = 'ALBUMS_REMOVE_SUCCESS'
export const ALBUMS_REMOVE_FAIL = 'ALBUMS_REMOVE_FAIL'

View File

@@ -1,8 +1,13 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { CX } from '../constants'
import { openModal } from '../actions/modal'
import {
CX,
MODAL_ALBUM_CREATE,
} from '../constants'
import Button from './button'
import Icon from './icon'
import Image from './image'
@@ -10,19 +15,14 @@ import Text from './text'
class Album extends React.PureComponent {
handleOnClick = (e) => {
//
}
handleOnOpenAlbumCreation = () => {
handleOnOpenAlbumCreate = () => {
this.props.openAlbumCreate()
}
render() {
const {
album,
isAddable,
isDummy,
} = this.props
const title = isAddable ? 'New album' : 'Album title'
@@ -31,29 +31,26 @@ class Album extends React.PureComponent {
return (
<div className={[_s.d, _s.minW162PX, _s.px5, _s.flex1].join(' ')}>
{
!isDummy &&
<Button
noClasses
className={[_s.d, _s.noUnderline, _s.noOutline, _s.bgTransparent].join(' ')}
to={to}
onClick={isAddable ? this.handleOnOpenAlbumCreation : undefined}
>
<div className={[_s.d, _s.w100PC, _s.mt5, _s.mb10].join(' ')}>
<div className={[_s.d, _s.w100PC, _s.pt100PC].join(' ')}>
<div className={[_s.d, _s.posAbs, _s.top0, _s.w100PC, _s.right0, _s.bottom0, _s.left0].join(' ')}>
<div className={[_s.d, _s.w100PC, _s.h100PC, _s.aiCenter, _s.jcCenter, _s.radiusSmall, _s.bgTertiary, _s.border1PX, _s.borderColorSecondary].join(' ')}>
{ isAddable && <Icon id='add' size='20px' /> }
</div>
<Button
noClasses
className={[_s.d, _s.noUnderline, _s.cursorPointer, _s.outlineNone, _s.bgTransparent].join(' ')}
to={to}
onClick={isAddable ? this.handleOnOpenAlbumCreate : undefined}
>
<div className={[_s.d, _s.w100PC, _s.mt5, _s.mb10].join(' ')}>
<div className={[_s.d, _s.w100PC, _s.pt100PC].join(' ')}>
<div className={[_s.d, _s.posAbs, _s.top0, _s.w100PC, _s.right0, _s.bottom0, _s.left0].join(' ')}>
<div className={[_s.d, _s.w100PC, _s.h100PC, _s.aiCenter, _s.jcCenter, _s.radiusSmall, _s.bgTertiary, _s.border1PX, _s.borderColorSecondary].join(' ')}>
{ isAddable && <Icon id='add' size='20px' /> }
</div>
</div>
</div>
<div className={[_s.d, _s.w100PC, _s.pt7, _s.mb15].join(' ')}>
<Text weight='bold'>{title}</Text>
{ !isAddable && <Text color='secondary' size='small' className={_s.mt5}>{subtitle}</Text> }
</div>
</Button>
}
</div>
<div className={[_s.d, _s.w100PC, _s.pt7, _s.mb15].join(' ')}>
<Text weight='bold'>{title}</Text>
{ !isAddable && <Text color='secondary' size='small' className={_s.mt5}>{subtitle}</Text> }
</div>
</Button>
</div>
)
}
@@ -63,7 +60,12 @@ class Album extends React.PureComponent {
Album.propTypes = {
album: ImmutablePropTypes.map,
isAddable: PropTypes.bool,
isDummy: PropTypes.bool,
}
export default Album
const mapDispatchToProps = (dispatch) => ({
openAlbumCreate() {
dispatch(openModal(MODAL_ALBUM_CREATE))
}
})
export default connect(null, mapDispatchToProps)(Album)

View File

@@ -28,7 +28,7 @@ class DeckColumnHeader extends React.PureComponent {
} = this.props
return (
<div data-sort-header className={[_s.d, _s.w100PC, _s.flexRow, _s.aiCenter, _s.h60PX, _s.px15, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary, _s.bgPrimary].join(' ')}>
<div data-sort-header className={[_s.d, _s.w100PC, _s.overflowHidden, _s.flexRow, _s.aiCenter, _s.h60PX, _s.px15, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary, _s.bgPrimary].join(' ')}>
<div data-sort-header className={[_s.d, _s.flexRow, _s.mr15, _s.cursorEWResize].join(' ')}>
<span className={[_s.d, _s.w1PX, _s.h24PX, _s.mr2, _s.bgSecondary].join(' ')} />
<span className={[_s.d, _s.w1PX, _s.h24PX, _s.mr2, _s.bgSecondary].join(' ')} />
@@ -36,7 +36,7 @@ class DeckColumnHeader extends React.PureComponent {
</div>
{ !!icon && <Icon id={icon} className={[_s.cPrimary, _s.mr15].join(' ')} size='18px' /> }
<div className={[_s.d, _s.flexRow, _s.aiEnd].join(' ')}>
<div className={[_s.d, _s.flexRow, _s.aiEnd, _s.flexShrink1, _s.overflowHidden, _s.textOverflowEllipsis2].join(' ')}>
{ !!title && <Text size='extraLarge' weight='medium'>{title}</Text> }
{ !!subtitle && <Text className={_s.ml5} color='secondary'>{subtitle}</Text> }
</div>

View File

@@ -99,9 +99,6 @@ class GroupHeader extends ImmutablePureComponent {
})
}
// : todo :
// {group.get('archived') && <Icon id='lock' title={intl.formatMessage(messages.group_archived)} />}
return (
<div className={[_s.d, _s.z1, _s.w100PC, _s.mb15].join(' ')}>
<Responsive max={BREAKPOINT_EXTRA_SMALL}>

View File

@@ -14,23 +14,41 @@ class MediaItem extends ImmutablePureComponent {
state = {
loaded: false,
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
visible: true,
}
componentDidMount() {
if (this.props.attachment.get('blurhash')) {
const { attachment } = this.props
if (!attachment) return
if (attachment.get('blurhash')) {
this._decode()
}
this.setState({
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
})
}
componentDidUpdate(prevProps) {
if (prevProps.attachment.get('blurhash') !== this.props.attachment.get('blurhash') && this.props.attachment.get('blurhash')) {
const { attachment } = this.props
const { prevAttachment } = prevProps
if (prevAttachment !== attachment) {
this._decode()
return
}
if (prevAttachment.get('blurhash') !== attachment.get('blurhash') && attachment.get('blurhash')) {
this._decode()
}
}
_decode() {
const hash = this.props.attachment.get('blurhash')
_decode = () => {
const { attachment } = this.props
if (!attachment) return
const hash = attachment.get('blurhash')
const pixels = decode(hash, 160, 160)
if (pixels && this.canvas) {
@@ -41,7 +59,7 @@ class MediaItem extends ImmutablePureComponent {
}
}
setCanvasRef = c => {
setCanvasRef = (c) => {
this.canvas = c
}
@@ -50,7 +68,10 @@ class MediaItem extends ImmutablePureComponent {
}
hoverToPlay() {
return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1
const { attachment } = this.props
if (!attachment) return
return !autoPlayGif && ['gifv', 'video'].indexOf(attachment.get('type')) !== -1
}
render() {
@@ -60,104 +81,152 @@ class MediaItem extends ImmutablePureComponent {
isSmall,
} = this.props
const { visible, loaded } = this.state
if (!attachment || !account) return null
const status = attachment.get('status')
const title = status.get('spoiler_text') || attachment.get('description')
const attachmentType = attachment.get('type')
const aspectRatio = attachment.getIn(['meta', 'aspect'])
const isVideo = attachmentType === 'video'
let badge = null
if (attachmentType === 'video') {
if (isVideo) {
const duration = attachment.getIn(['meta', 'duration'])
badge = (duration / 60).toFixed(2)
} else if (attachmentType === 'gifv') {
badge = 'GIF'
}
const statusUrl = `/${account.getIn(['acct'])}/posts/${status.get('id')}`
const isSmallRatio = aspectRatio < 1
const isSquare = aspectRatio === 1
const containerClasses = CX({
d: 1,
posAbs: 1,
top0: 1,
h100PC: 1,
// w100PC: 1,
py2: !isSmall,
px2: !isSmall,
px5: 1,
flex1: !isSmallRatio && !isSquare,
minW198PX: !isVideo && !isSmallRatio && !isSquare,
minW232PX: isVideo && !isSmallRatio && !isSquare,
minW120PX: isSmallRatio,
minW162PX: isSquare,
})
const linkClasses = CX({
const paddedContainerClasses = CX({
d: 1,
w100PC: 1,
// h100PC: 1,
overflowHidden: 1,
border1PX: 1,
borderColorPrimary: 1,
h100PC: isSmallRatio || isSquare,
pt100PC: isSmallRatio || isSquare || !isVideo,
pt5625PC: isVideo && !isSmallRatio && !isSquare,
})
const statusUrl = `/${account.getIn(['acct'])}/posts/${status.get('id')}`;
// : todo : fix dimensions to be like albums
return (
<div className={[_s.d, _s.pt25PC].join(' ')}>
<div className={containerClasses}>
<NavLink
to={statusUrl}
title={title}
className={linkClasses}
>
{
(!loaded || !visible) &&
<canvas
height='100%'
width='100%'
ref={this.setCanvasRef}
className={[_s.d, _s.w100PC, _s.h100PC, _s.z2].join(' ')}
/>
}
<div className={containerClasses}>
<NavLink
className={[_s.d, _s.noUnderline, _s.outlineNone, _s.bgTransparent, _s.flexGrow1].join(' ')}
to={statusUrl}
title={title}
>
<div className={[_s.d, _s.mt5, _s.mb10, _s.flexGrow1].join(' ')}>
<div className={paddedContainerClasses}>
<div className={[_s.d, _s.posAbs, _s.top0, _s.right0, _s.left0, _s.bottom0].join(' ')}>
<div className={[_s.d, _s.h100PC, _s.aiCenter, _s.jcCenter, _s.radiusSmall, _s.overflowHidden].join(' ')}>
{
(!loaded || !visible) &&
<canvas
height='100%'
width='100%'
ref={this.setCanvasRef}
className={[_s.d, _s.w100PC, _s.h100PC, _s.z2].join(' ')}
/>
}
{
visible &&
<Image
height='100%'
width=''
src={attachment.get('preview_url')}
alt={attachment.get('description')}
title={attachment.get('description')}
onLoad={this.handleImageLoad}
className={_s.z1}
/>
}
{
visible &&
<Image
height='100%'
width=''
src={attachment.get('preview_url')}
alt={attachment.get('description')}
title={attachment.get('description')}
onLoad={this.handleImageLoad}
className={_s.z1}
/>
}
<div className={[_s.d, _s.aiCenter, _s.jcCenter, _s.h100PC, _s.w100PC, _s.z3, _s.posAbs].join(' ')}>
{
!visible &&
<Icon
id='hidden'
size='22px'
className={[_s.cWhite].join('')}
/>
}
{
!!badge &&
<div className={[_s.d, _s.posAbs, _s.radiusSmall, _s.bgBlackOpaque, _s.px5, _s.py5, _s.mr5, _s.mt5, _s.mb5, _s.bottom0, _s.right0].join(' ')}>
<Text size='extraSmall' color='white'>
{badge}
</Text>
{
(!visible || !!badge) &&
<div className={[_s.d, _s.aiCenter, _s.jcCenter, _s.h100PC, _s.w100PC, _s.z3, _s.posAbs].join(' ')}>
{
!visible &&
<Icon
id='hidden'
size='22px'
className={[_s.cWhite].join('')}
/>
}
{
!!badge &&
<div className={[_s.d, _s.posAbs, _s.radiusSmall, _s.bgBlackOpaque, _s.px5, _s.py5, _s.mr5, _s.mt5, _s.mb5, _s.bottom0, _s.right0].join(' ')}>
<Text size='extraSmall' color='white'>
{badge}
</Text>
</div>
}
</div>
}
</div>
}
</div>
</div>
</NavLink>
</div>
</div>
</NavLink>
</div>
)
// return (
// <div className={[_s.d, _s.pt25PC].join(' ')}>
// <div className={containerClasses}>
// <NavLink
// to={statusUrl}
// title={title}
// className={linkClasses}
// >
// {
// (!loaded || !visible) &&
// <canvas
// height='100%'
// width='100%'
// ref={this.setCanvasRef}
// className={[_s.d, _s.w100PC, _s.h100PC, _s.z2].join(' ')}
// />
// }
// {
// visible &&
// <Image
// height='100%'
// width=''
// src={attachment.get('preview_url')}
// alt={attachment.get('description')}
// title={attachment.get('description')}
// onLoad={this.handleImageLoad}
// className={_s.z1}
// />
// }
// </NavLink>
// </div>
// </div>
// )
}
}
MediaItem.propTypes = {
isDummy: PropTypes.bool.isRequired,
account: ImmutablePropTypes.map.isRequired,
attachment: ImmutablePropTypes.map.isRequired,
isSmall: PropTypes.bool,

View File

@@ -1 +1,29 @@
// : todo :
import React from 'react'
import PropTypes from 'prop-types'
import { defineMessages, injectIntl } from 'react-intl'
import ModalLayout from './modal_layout'
import AlbumCreate from '../../features/album_create'
class AlbumCreateModal extends React.PureComponent {
render() {
const { onClose } = this.props
return (
<ModalLayout
title='Create Album'
width={500}
onClose={onClose}
>
<AlbumCreate isModal />
</ModalLayout>
)
}
}
AlbumCreateModal.propTypes = {
onClose: PropTypes.func.isRequired,
}
export default AlbumCreateModal

View File

@@ -1,29 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { defineMessages, injectIntl } from 'react-intl'
import ModalLayout from './modal_layout'
import BookmarkCollectionEdit from '../../features/bookmark_collection_edit'
class BookmarkCollectionEditModal extends React.PureComponent {
render() {
const { onClose } = this.props
return (
<ModalLayout
title='Edit Bookmark Collection'
width={500}
onClose={onClose}
>
<BookmarkCollectionEdit isModal />
</ModalLayout>
)
}
}
BookmarkCollectionEditModal.propTypes = {
onClose: PropTypes.func.isRequired,
}
export default BookmarkCollectionEditModal

View File

@@ -39,12 +39,6 @@ class MediaGalleryPanel extends ImmutablePureComponent {
}
}
// componentWillReceiveProps(nextProps) {
// if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
// this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, { limit: 8 }))
// }
// }
render() {
const {
account,

View File

@@ -81,8 +81,6 @@ class StatusOptionsPopover extends ImmutablePureComponent {
handleGroupRemoveAccount = () => {
const { status } = this.props
// : todo : check
this.props.onGroupRemoveAccount(status.getIn(['group', 'id']), status.getIn(['account', 'id']))
}

View File

@@ -65,6 +65,19 @@ class DeckSidebar extends ImmutablePureComponent {
<div className={[_s.d].join(' ')}>
<Button
to='/'
isText
title='Go home'
aria-label='Go home'
color='none'
backgroundColor='none'
className={[_s.d, _s.jcCenter, _s.noSelect, _s.noUnderline, _s.mt15, _s.mb15, _s.cursorPointer, _s.px10, _s.mr5].join(' ')}
icon='back'
iconSize='20px'
iconClassName={_s.fillNavigationBrand}
/>
<h1 className={[_s.d].join(' ')}>
<Button
to='/'

View File

@@ -51,7 +51,6 @@ export const POPOVER_VIDEO_STATS = 'VIDEO_STATS'
export const MODAL_ALBUM_CREATE = 'ALBUM_CREATE'
export const MODAL_BLOCK_ACCOUNT = 'BLOCK_ACCOUNT'
export const MODAL_BOOKMARK_COLLECTION_CREATE = 'BOOKMARK_COLLECTION_CREATE'
export const MODAL_BOOKMARK_COLLECTION_EDIT = 'BOOKMARK_COLLECTION_EDIT'
export const MODAL_BOOST = 'BOOST'
export const MODAL_CHAT_CONVERSATION_CREATE = 'CHAT_CONVERSATION_CREATE'
export const MODAL_CHAT_CONVERSATION_DELETE = 'CHAT_CONVERSATION_DELETE'

View File

@@ -3,76 +3,60 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { injectIntl, defineMessages } from 'react-intl'
import { expandAccountMediaTimeline } from '../actions/timelines'
import { getAccountGallery } from '../selectors'
import { me } from '../initial_state'
import {
fetchAccountAlbums,
expandAccountAlbums,
} from '../actions/albums'
import ColumnIndicator from '../components/column_indicator'
import Heading from '../components/heading'
import TabBar from '../components/tab_bar'
import MediaItem from '../components/media_item'
import LoadMore from '../components/load_more'
import Block from '../components/block'
import Image from '../components/image'
import Album from '../components/album'
import Dummy from '../components/dummy'
import MediaGalleryPlaceholder from '../components/placeholder/media_gallery_placeholder'
class AccountAlbums extends ImmutablePureComponent {
// componentDidMount() {
// const { accountId, mediaType } = this.props
componentDidMount() {
const { accountId, mediaType } = this.props
// if (accountId && accountId !== -1) {
// this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType }))
// }
// }
if (accountId && accountId !== -1) {
this.props.onFetchAccountAlbums(accountId)
}
}
// componentWillReceiveProps(nextProps) {
// if (
// (nextProps.accountId && nextProps.accountId !== this.props.accountId) ||
// (nextProps.accountId && nextProps.mediaType !== this.props.mediaType)
// ) {
// this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, {
// mediaType: nextProps.mediaType,
// }))
// }
// }
componentWillReceiveProps(nextProps) {
if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
this.props.onFetchAccountAlbums(nextProps.accountId)
}
}
// handleScrollToBottom = () => {
// if (this.props.hasMore) {
// this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined)
// }
// }
handleLoadMore = () => {
const { accountId, hasMore } = this.props
if (accountId && accountId !== -1 && hasMore) {
this.props.onExpandAccountAlbums(accountId)
}
}
// handleScroll = (e) => {
// const { scrollTop, scrollHeight, clientHeight } = e.target
// const offset = scrollHeight - scrollTop - clientHeight
// if (150 > offset && !this.props.isLoading) {
// this.handleScrollToBottom()
// }
// }
// handleLoadMore = (maxId) => {
// if (this.props.accountId && this.props.accountId !== -1) {
// this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, {
// maxId,
// mediaType: this.props.mediaType,
// }))
// }
// }
// handleLoadOlder = (e) => {
// e.preventDefault()
// this.handleScrollToBottom()
// }
handleLoadOlder = (e) => {
e.preventDefault()
this.handleLoadMore()
}
render() {
const {
account,
isMe,
albums,
account,
accountId,
hasMore,
isLoading,
} = this.props
if (!account) return null
const hasAlbums = !!albums ? albums.size > 0 : false
return (
<Block>
@@ -95,103 +79,68 @@ class AccountAlbums extends ImmutablePureComponent {
<div className={[_s.d, _s.w100PC, _s.flexRow, _s.flexWrap, _s.px10, _s.mb15, _s.pb10].join(' ')}>
{ isMe && <Album isAddable /> }
<Album />
<Album />
<Album />
<Album />
<Album />
<Album isDummy />
<Album isDummy />
<Album isDummy />
<Album isDummy />
<Album isDummy />
<Album isDummy />
{
hasAlbums &&
albums.map((albums, i) => (
<Album
key={album.get('id')}
album={album}
account={account}
/>
))
}
{
Array.apply(null, { length: 8}).map((_, i) => (
<Dummy className={[_s.d, _s.minW162PX, _s.px5, _s.flex1].join(' ')} />
))
}
{
!isLoading && !hasAlbums && me !== accountId &&
<ColumnIndicator type='error' message='No albums exist' />
}
</div>
{
hasMore && !(isLoading && !hasAlbums) &&
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
}
</Block>
)
// const {
// attachments,
// isLoading,
// hasMore,
// intl,
// account,
// } = this.props
// return (
// <Block>
// <div
// role='feed'
// onScroll={this.handleScroll}
// className={[_s.d, _s.flexRow, _s.flexWrap, _s.py5, _s.px5].join(' ')}
// >
// {
// attachments.map((attachment, i) => (
// <MediaItem
// key={attachment.get('id')}
// attachment={attachment}
// account={account}
// />
// ))
// }
// {
// isLoading && attachments.size === 0 &&
// <div className={[_s.d, _s.w100PC].join(' ')}>
// <MediaGalleryPlaceholder />
// </div>
// }
// {
// !isLoading && attachments.size === 0 &&
// <ColumnIndicator type='error' message={intl.formatMessage(messages.none)} />
// }
// </div>
// {
// hasMore && !(isLoading && attachments.size === 0) &&
// <LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
// }
// </Block>
// )
}
}
const messages = defineMessages({
none: { id: 'account_gallery.none', defaultMessage: 'No media to show.' },
})
const mapStateToProps = (state, { account, mediaType }) => {
const accountId = !!account ? account.get('id') : -1
return {
accountId,
attachments: getAccountGallery(state, accountId, mediaType),
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading']),
hasMore: state.getIn(['timelines', `account:${accountId}:media`, 'hasMore']),
albums: state.getIn(['album_lists', accountId, 'items']),
isLoading: state.getIn(['album_lists', accountId, 'isLoading'], false),
hasMore: state.getIn(['album_lists', accountId, 'hasMore'], false),
}
}
const mapDispatchToProps = (dispatch) => ({
onFetchAccountAlbums(accountId) {
},
onExpandAccountAlbums(accountId) {
},
})
AccountAlbums.propTypes = {
dispatch: PropTypes.func.isRequired,
account: ImmutablePropTypes.map,
accountId: PropTypes.string,
attachments: ImmutablePropTypes.list.isRequired,
albums: ImmutablePropTypes.list,
isLoading: PropTypes.bool,
hasMore: PropTypes.bool,
intl: PropTypes.object.isRequired,
mediaType: PropTypes.oneOf([
'photo',
'video',
]),
}
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(AccountAlbums))
export default connect(mapStateToProps, mapDispatchToProps)(AccountAlbums)

View File

@@ -0,0 +1,172 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { injectIntl, defineMessages } from 'react-intl'
import { expandAccountMediaTimeline } from '../actions/timelines'
import { getAccountGallery } from '../selectors'
import ColumnIndicator from '../components/column_indicator'
import MediaItem from '../components/media_item'
import Heading from '../components/heading'
import TabBar from '../components/tab_bar'
import LoadMore from '../components/load_more'
import Block from '../components/block'
import Dummy from '../components/dummy'
import MediaGalleryPlaceholder from '../components/placeholder/media_gallery_placeholder'
class AccountPhotoGallery extends ImmutablePureComponent {
componentDidMount() {
const { accountId } = this.props
if (accountId && accountId !== -1) {
this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType: 'photo' }))
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, {
mediaType: 'photo',
}))
}
}
handleScrollToBottom = () => {
if (this.props.hasMore) {
this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined)
}
}
handleScroll = (e) => {
const { scrollTop, scrollHeight, clientHeight } = e.target
const offset = scrollHeight - scrollTop - clientHeight
if (150 > offset && !this.props.isLoading) {
this.handleScrollToBottom()
}
}
handleLoadMore = (maxId) => {
if (this.props.accountId && this.props.accountId !== -1) {
this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, {
maxId,
mediaType: 'photo',
}))
}
}
handleLoadOlder = (e) => {
e.preventDefault()
this.handleScrollToBottom()
}
render() {
const {
attachments,
isLoading,
hasMore,
intl,
account,
} = this.props
if (!account) return null
const hasAttachments = !!attachments ? attachments.size > 0 : false
console.log("account, isLoading, attachments:", account, isLoading, attachments, hasAttachments)
return (
<Block>
<div className={[_s.d, _s.px10, _s.py10].join(' ')}>
<div className={[_s.d, _s.px5, _s.py5, _s.mb10].join(' ')}>
<Heading size='h2'>Photos</Heading>
</div>
<TabBar tabs={[
{
title: 'All Photos',
to: `/${account.get('username')}/photos`,
},
{
title: 'Albums',
isActive: true,
to: `/${account.get('username')}/albums`,
},
]}/>
</div>
<div
role='feed'
onScroll={this.handleScroll}
className={[_s.d, _s.w100PC, _s.flexRow, _s.flexWrap, _s.px10, _s.mb15, _s.pb10].join(' ')}
>
{
hasAttachments &&
<React.Fragment>
{
attachments.map((attachment, i) => (
<MediaItem
key={attachment.get('id')}
attachment={attachment}
account={account}
/>
))
}
{
Array.apply(null, { length: 8}).map((_, i) => (
<Dummy className={[_s.d, _s.minW198PX, _s.px5, _s.flex1].join(' ')} />
))
}
</React.Fragment>
}
{
isLoading && !hasAttachments &&
<div className={[_s.d, _s.w100PC].join(' ')}>
<MediaGalleryPlaceholder />
</div>
}
{
!isLoading && !hasAttachments &&
<ColumnIndicator type='error' message={intl.formatMessage(messages.none)} />
}
</div>
{
hasMore && !(isLoading && !hasAttachments) &&
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
}
</Block>
)
}
}
const messages = defineMessages({
none: { id: 'account_gallery.none', defaultMessage: 'No media to show.' },
})
const mapStateToProps = (state, { account }) => {
const accountId = !!account ? account.get('id') : -1
return {
accountId,
attachments: getAccountGallery(state, accountId, 'photo'),
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading']),
hasMore: state.getIn(['timelines', `account:${accountId}:media`, 'hasMore']),
}
}
AccountPhotoGallery.propTypes = {
dispatch: PropTypes.func.isRequired,
account: ImmutablePropTypes.map,
accountId: PropTypes.string,
attachments: ImmutablePropTypes.list.isRequired,
isLoading: PropTypes.bool,
hasMore: PropTypes.bool,
intl: PropTypes.object.isRequired,
}
export default injectIntl(connect(mapStateToProps)(AccountPhotoGallery))

View File

@@ -8,27 +8,27 @@ import { expandAccountMediaTimeline } from '../actions/timelines'
import { getAccountGallery } from '../selectors'
import ColumnIndicator from '../components/column_indicator'
import MediaItem from '../components/media_item'
import Dummy from '../components/dummy'
import LoadMore from '../components/load_more'
import Block from '../components/block'
import Heading from '../components/heading'
import TabBar from '../components/tab_bar'
import MediaGalleryPlaceholder from '../components/placeholder/media_gallery_placeholder'
class AccountGallery extends ImmutablePureComponent {
class AccountVideoGallery extends ImmutablePureComponent {
componentDidMount() {
const { accountId, mediaType } = this.props
const { accountId } = this.props
if (accountId && accountId !== -1) {
this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType }))
this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType: 'video' }))
}
}
componentWillReceiveProps(nextProps) {
if (
(nextProps.accountId && nextProps.accountId !== this.props.accountId) ||
(nextProps.accountId && nextProps.mediaType !== this.props.mediaType)
) {
if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, {
mediaType: nextProps.mediaType,
mediaType: 'video',
}))
}
}
@@ -52,7 +52,7 @@ class AccountGallery extends ImmutablePureComponent {
if (this.props.accountId && this.props.accountId !== -1) {
this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, {
maxId,
mediaType: this.props.mediaType,
mediaType: 'video',
}))
}
}
@@ -73,39 +73,63 @@ class AccountGallery extends ImmutablePureComponent {
if (!account) return null
const hasAttachments = !!attachments ? attachments.size > 0 : false
return (
<Block>
<div className={[_s.d, _s.px10, _s.py10].join(' ')}>
<div className={[_s.d, _s.px5, _s.py5, _s.mb10].join(' ')}>
<Heading size='h2'>Videos</Heading>
</div>
<TabBar tabs={[
{
title: 'All Videos',
to: `/${account.get('username')}/videos`,
},
]}/>
</div>
<div
role='feed'
onScroll={this.handleScroll}
className={[_s.d, _s.flexRow, _s.flexWrap, _s.py5, _s.px5].join(' ')}
className={[_s.d, _s.w100PC, _s.flexRow, _s.flexWrap, _s.px10, _s.mb15, _s.pb10].join(' ')}
>
{
attachments.map((attachment, i) => (
<MediaItem
key={attachment.get('id')}
attachment={attachment}
account={account}
/>
))
hasAttachments &&
<React.Fragment>
{
attachments.map((attachment, i) => (
<MediaItem
key={attachment.get('id')}
attachment={attachment}
account={account}
/>
))
}
{
Array.apply(null, { length: 8 }).map((_, i) => (
<Dummy className={[_s.d, _s.minW232PX, _s.px5, _s.flex1].join(' ')} />
))
}
</React.Fragment>
}
{
isLoading && attachments.size === 0 &&
isLoading && !hasAttachments &&
<div className={[_s.d, _s.w100PC].join(' ')}>
<MediaGalleryPlaceholder />
</div>
}
{
!isLoading && attachments.size === 0 &&
!isLoading && !hasAttachments &&
<ColumnIndicator type='error' message={intl.formatMessage(messages.none)} />
}
</div>
{
hasMore && !(isLoading && attachments.size === 0) &&
hasMore && !(isLoading && !hasAttachments) &&
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
}
</Block>
@@ -118,18 +142,18 @@ const messages = defineMessages({
none: { id: 'account_gallery.none', defaultMessage: 'No media to show.' },
})
const mapStateToProps = (state, { account, mediaType }) => {
const mapStateToProps = (state, { account }) => {
const accountId = !!account ? account.get('id') : -1
return {
accountId,
attachments: getAccountGallery(state, accountId, mediaType),
attachments: getAccountGallery(state, accountId, 'video'),
isLoading: state.getIn(['timelines', `account:${accountId}:media`, 'isLoading']),
hasMore: state.getIn(['timelines', `account:${accountId}:media`, 'hasMore']),
}
}
AccountGallery.propTypes = {
AccountVideoGallery.propTypes = {
dispatch: PropTypes.func.isRequired,
account: ImmutablePropTypes.map,
accountId: PropTypes.string,
@@ -137,14 +161,6 @@ AccountGallery.propTypes = {
isLoading: PropTypes.bool,
hasMore: PropTypes.bool,
intl: PropTypes.object.isRequired,
mediaType: PropTypes.oneOf([
'photo',
'video',
]),
}
AccountGallery.defaultProps = {
mediaType: 'both'
}
export default injectIntl(connect(mapStateToProps)(AccountGallery))
export default injectIntl(connect(mapStateToProps)(AccountVideoGallery))

View File

@@ -1 +1,67 @@
// : todo :
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { defineMessages, injectIntl } from 'react-intl'
import { createAlbum } from '../actions/albums'
import { closeModal } from '../actions/modal'
import Button from '../components/button'
import Input from '../components/input'
import Form from '../components/form'
import Text from '../components/text'
class AlbumCreate extends React.PureComponent {
state = {
value: '',
}
onChange = (value) => {
this.setState({ value })
}
handleOnSubmit = () => {
this.props.onSubmit(this.state.value)
}
render() {
const { value } = this.state
const isDisabled = !value
return (
<Form>
<Input
title='Title'
placeholder='Album title'
value={value}
onChange={this.onChange}
/>
<Button
isDisabled={isDisabled}
onClick={this.handleOnSubmit}
className={[_s.mt10].join(' ')}
>
<Text color='inherit' align='center'>
Create
</Text>
</Button>
</Form>
)
}
}
const mapDispatchToProps = (dispatch, { isModal }) => ({
onSubmit(title) {
if (isModal) dispatch(closeModal())
dispatch(createBookmarkCollection(title))
},
})
AlbumCreate.propTypes = {
onSubmit: PropTypes.func.isRequired,
isModal: PropTypes.bool,
}
export default connect(null, mapDispatchToProps)(AlbumCreate)

View File

@@ -1,100 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { defineMessages, injectIntl } from 'react-intl'
import {
updateBookmarkCollection,
removeBookmarkCollection,
} from '../actions/bookmarks'
import { closeModal } from '../actions/modal'
import Button from '../components/button'
import Input from '../components/input'
import Form from '../components/form'
import Text from '../components/text'
class BookmarkCollectionEdit extends React.PureComponent {
state = {
value: '',
}
componentDidMount() {
if (!this.props.bookmarkCollection) {
this.props.onFetchBookmarkCollection(this.props.bookmarkCollectionId)
}
}
onChange = (value) => {
this.setState({ value })
}
handleOnSubmit = () => {
this.props.onSubmit(this.state.value)
}
handleOnRemove = () => {
this.props.onRemove()
}
render() {
const { value } = this.state
const isDisabled = !value
return (
<Form>
<Input
title='Title'
placeholder='Bookmark collection title'
value={value}
onChange={this.onChange}
/>
<Button
isDisabled={isDisabled}
onClick={this.handleOnSubmit}
className={[_s.mt10].join(' ')}
>
<Text color='inherit' align='center'>
Update
</Text>
</Button>
<Button
backgroundColor='danger'
color='white'
onClick={this.handleOnRemove}
className={[_s.mt10].join(' ')}
>
<Text color='inherit' align='center'>
Update
</Text>
</Button>
</Form>
)
}
}
const mapStateToProps = (state, { bookmarkCollectionId }) => ({
bookmarkCollection: state.getIn(['bookmark_collections', bookmarkCollectionId]),
})
const mapDispatchToProps = (dispatch, { isModal, bookmarkCollectionId }) => ({
onSubmit(title) {
if (isModal) dispatch(closeModal())
dispatch(updateBookmarkCollection(title))
},
onRemove() {
if (isModal) dispatch(closeModal())
dispatch(removeBookmarkCollection(bookmarkCollectionId))
},
})
BookmarkCollectionEdit.propTypes = {
onSubmit: PropTypes.func.isRequired,
onRemove: PropTypes.func.isRequired,
isModal: PropTypes.bool,
}
export default connect(mapStateToProps, mapDispatchToProps)(BookmarkCollectionEdit)

View File

@@ -10,6 +10,7 @@ import {
import { me, meUsername} from '../initial_state'
import {
GAB_DECK_MAX_ITEMS,
URL_GAB_PRO,
MODAL_PRO_UPGRADE,
} from '../constants'
import {
@@ -22,6 +23,7 @@ import { openModal } from '../actions/modal'
import WrappedBundle from './ui/util/wrapped_bundle'
import DeckColumn from '../components/deck_column'
import Text from '../components/text'
import Button from '../components/button'
import {
AccountTimeline,
Compose,
@@ -186,6 +188,15 @@ class Deck extends React.PureComponent {
const isEmpty = gabDeckOrder.size === 0
const title = (
<span className={[_s.d, _s.flexRow, _s.jcCenter, _s.aiCenter].join(' ')}>
<span className={[_s.d, _s.mr2].join(' ')}>
Gab Deck for Gab
</span>
<span className={[_s.bgPro, _s.cBlack, _s.radiusSmall, _s.px5, _s.py5].join(' ')}>PRO</span>
</span>
)
return (
<SortableContainer
axis='x'
@@ -199,16 +210,29 @@ class Deck extends React.PureComponent {
<DeckColumn title='Compose' icon='pencil' noButtons>
<WrappedBundle component={Compose} />
</DeckColumn>
{ /** : todo : */
{
!isPro &&
<DeckColumn title='Gab Deck for GabPRO' icon='pro' noButtons>
<DeckColumn title={title} icon='pro' noButtons>
<div className={[_s.d, _s.px15, _s.py15].join(' ')}>
<Text>
Gab Deck for GabPRO. Some text about what it does and some buttons on going pro to use it.
GabDeck is a unique way to customize your Gab experience. Upgrade to GabPRO to unlock the GabDeck.
</Text>
<div className={[_s.mt15, _s.d, _s.flexRow].join(' ')}>
<Button href={URL_GAB_PRO}>
<Text color='inherit' className={_s.px10}>
Upgrade to GabPRO
</Text>
</Button>
</div>
</div>
</DeckColumn>
}
<DeckColumn title='Explore' icon='explore' noButtons>
<WrappedBundle component={ExploreTimeline} />
</DeckColumn>
<DeckColumn title='News' icon='news' noButtons>
<WrappedBundle component={News} componentParams={{ isSmall: true }} />
</DeckColumn>
<DeckColumn />
</React.Fragment>
}

View File

@@ -97,7 +97,6 @@ class ChatMessageScrollingList extends ImmutablePureComponent {
}
getCurrentChatMessageIndex = (id) => {
// : todo :
return this.props.chatMessageIds.indexOf(id)
}

View File

@@ -53,7 +53,8 @@ import DeckPage from '../../pages/deck_page'
import {
About,
AccountAlbums,
AccountGallery,
AccountPhotoGallery,
AccountVideoGallery,
AccountTimeline,
AccountCommentsTimeline,
AlbumCreate,
@@ -277,17 +278,18 @@ class SwitchingArea extends React.PureComponent {
<WrappedRoute path='/:username/followers' page={ProfilePage} component={Followers} content={children} />
<WrappedRoute path='/:username/following' page={ProfilePage} component={Following} content={children} />
<WrappedRoute path='/:username/photos' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ noSidebar: true, mediaType: 'photo' }} />
<WrappedRoute path='/:username/videos' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ noSidebar: true, mediaType: 'video' }} />
<WrappedRoute path='/:username/albums' page={ProfilePage} component={AccountAlbums} content={children} componentParams={{ noSidebar: true, mediaType: 'photo' }} />
<WrappedRoute path='/:username/photos' exact page={ProfilePage} component={AccountPhotoGallery} content={children} componentParams={{ noSidebar: true }} />
{ /* <WrappedRoute path='/:username/albums/:albumId' page={ProfilePage} component={AccountGallery} content={children} componentParams={{ noSidebar: true }} /> */ }
<WrappedRoute path='/:username/videos' exact page={ProfilePage} component={AccountVideoGallery} content={children} componentParams={{ noSidebar: true }} />
<WrappedRoute path='/:username/albums' exact page={ProfilePage} component={AccountAlbums} content={children} componentParams={{ noSidebar: true }} />
<WrappedRoute path='/:username/album_create' page={ModalPage} component={AlbumCreate} content={children} componentParams={{ title: 'Create Album', page: 'create-album' }} />
<WrappedRoute path='/:username/album_edit/:albumId' page={ModalPage} component={AlbumCreate} content={children} componentParams={{ title: 'Create Album', page: 'edit-album' }} />
{ /* <WrappedRoute path='/:username/albums/create' exact page={ModalPage} component={AlbumCreate} content={children} componentParams={{ title: 'Create Album', page: 'create-album' }} /> */ }
{ /* <WrappedRoute path='/:username/albums/:albumId/edit' page={ModalPage} component={AlbumCreate} content={children} componentParams={{ title: 'Edit Album', page: 'edit-album' }} /> */ }
<WrappedRoute path='/:username/likes' page={ProfilePage} component={LikedStatuses} content={children} />
<WrappedRoute path='/:username/bookmark_collections/create' page={ModalPage} component={BookmarkCollectionCreate} content={children} componentParams={{ title: 'Create Bookmark Collection', page: 'create-bookmark-collection' }} />
<WrappedRoute path='/:username/bookmark_collections/:bookmarkCollectionId' page={ProfilePage} component={BookmarkedStatuses} content={children} />
<WrappedRoute path='/:username/bookmark_collections/:bookmarkCollectionId/edit' page={ModalPage} component={BookmarkCollectionEdit} content={children} componentParams={{ title: 'Edit Bookmark Collection', page: 'edit-bookmark-collection' }} />
<WrappedRoute path='/:username/bookmark_collections/:bookmarkCollectionId/edit' page={ModalPage} component={BookmarkCollectionCreate} content={children} componentParams={{ title: 'Edit Bookmark Collection', page: 'edit-bookmark-collection' }} />
<WrappedRoute path='/:username/bookmark_collections' page={ProfilePage} component={BookmarkCollections} content={children} />
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={StatusFeature} content={children} componentParams={{ title: 'Status', page: 'status' }} />

View File

@@ -3,7 +3,8 @@ export function AboutSidebar() { return import(/* webpackChunkName: "components/
export function AccountTimeline() { return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline') }
export function AccountCommentsTimeline() { return import(/* webpackChunkName: "features/account_comments_timeline" */'../../account_comments_timeline') }
export function AccountAlbums() { return import(/* webpackChunkName: "features/account_albums" */'../../account_albums') }
export function AccountGallery() { return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery') }
export function AccountPhotoGallery() { return import(/* webpackChunkName: "features/account_photo_gallery" */'../../account_photo_gallery') }
export function AccountVideoGallery() { return import(/* webpackChunkName: "features/account_video_gallery" */'../../account_video_gallery') }
export function AlbumCreate() { return import(/* webpackChunkName: "features/album_create" */'../../album_create') }
export function AlbumCreateModal() { return import(/* webpackChunkName: "components/album_create_modal" */'../../../components/modal/album_create_modal') }
export function Assets() { return import(/* webpackChunkName: "features/about/assets" */'../../about/assets') }
@@ -12,8 +13,6 @@ export function BlockedAccounts() { return import(/* webpackChunkName: "features
export function BookmarkCollections() { return import(/* webpackChunkName: "features/bookmark_collections" */'../../bookmark_collections') }
export function BookmarkCollectionCreate() { return import(/* webpackChunkName: "features/bookmark_collection_create" */'../../bookmark_collection_create') }
export function BookmarkCollectionCreateModal() { return import(/* webpackChunkName: "components/bookmark_collection_create_modal" */'../../../components/modal/bookmark_collection_create_modal') }
export function BookmarkCollectionEdit() { return import(/* webpackChunkName: "features/bookmark_collection_edit" */'../../bookmark_collection_edit') }
export function BookmarkCollectionEditModal() { return import(/* webpackChunkName: "components/bookmark_collection_edit_modal" */'../../../components/modal/bookmark_collection_edit_modal') }
export function BookmarkedStatuses() { return import(/* webpackChunkName: "features/bookmarked_statuses" */'../../bookmarked_statuses') }
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
export function CaliforniaConsumerProtection() { return import(/* webpackChunkName: "features/california_consumer_protection" */'../../about/california_consumer_protection') }

View File

@@ -34,7 +34,10 @@ class GroupPage extends ImmutablePureComponent {
const isMember = !!relationships ? relationships.get('member') : false
const unavailable = isPrivate && !isMember
if (!!group) {
if (group.get('archived')) return null
}
return (
<GroupLayout
title={'Group'}

View File

@@ -0,0 +1,59 @@
import {
Map as ImmutableMap,
List as ImmutableList,
} from 'immutable'
import { me } from '../initial_state'
import {
ALBUMS_FETCH_REQUEST,
ALBUMS_FETCH_SUCCESS,
ALBUMS_FETCH_FAIL,
ALBUMS_EXPAND_REQUEST,
ALBUMS_EXPAND_SUCCESS,
ALBUMS_EXPAND_FAIL,
} from '../actions/albums'
const initialState = ImmutableMap({})
const setListFailed = (state, id) => {
return state.setIn([id], ImmutableMap({
next: null,
items: ImmutableList(),
isLoading: false,
}))
}
const normalizeList = (state, id, albums, next) => {
return state.setIn([id], ImmutableMap({
next,
items: ImmutableList(albums.map(item => item.id)),
isLoading: false,
}))
}
const appendToList = (state, id, albums, next) => {
return state.updateIn([id], (map) => {
return map
.set('next', next)
.set('isLoading', false)
.update('items', (list) => {
return list.concat(albums.map(item => item.id))
})
})
}
export default function album_lists(state = initialState, action) {
switch(action.type) {
case ALBUMS_FETCH_REQUEST:
case ALBUMS_EXPAND_REQUEST:
return state.setIn([action.accountId, 'isLoading'], true)
case ALBUMS_FETCH_SUCCESS:
return normalizeList(state, action.accountId, action.albums, action.next)
case ALBUMS_EXPAND_SUCCESS:
return appendToList(state, action.accountId, action.albums, action.next)
case ALBUMS_FETCH_FAIL:
case ALBUMS_EXPAND_FAIL:
return setListFailed(state, action.accountId)
default:
return state;
}
};

View File

@@ -3,6 +3,7 @@ import { loadingBarReducer } from 'react-redux-loading-bar'
import accounts from './accounts'
import accounts_counters from './accounts_counters'
import albums from './albums'
import album_lists from './album_lists'
import bookmark_collections from './bookmark_collections'
import chats from './chats'
import chat_conversation_lists from './chat_conversation_lists'
@@ -55,6 +56,8 @@ import user_lists from './user_lists'
const reducers = {
accounts,
accounts_counters,
// albums,
// album_lists,
bookmark_collections,
chats,
chat_conversation_lists,