progress
This commit is contained in:
parent
196a906cec
commit
055b5a430f
@ -4,52 +4,80 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
|
||||
|
||||
respond_to :json
|
||||
before_action :set_status
|
||||
before_action :verify_own_status
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
render json: {}, status: :ok
|
||||
@accounts = load_accounts
|
||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_accounts
|
||||
#
|
||||
scope = default_accounts
|
||||
scope = scope.where.not(id: current_account.excluded_from_timeline_account_ids) unless current_account.nil?
|
||||
scope.merge(paginated_favourites).to_a
|
||||
end
|
||||
|
||||
def default_accounts
|
||||
#
|
||||
Account
|
||||
.includes(:favourites, :account_stat)
|
||||
.references(:favourites)
|
||||
.where(favourites: { status_id: @status.id })
|
||||
end
|
||||
|
||||
def paginated_favourites
|
||||
#
|
||||
Favourite.paginate_by_max_id(
|
||||
limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||
params[:max_id],
|
||||
params[:since_id]
|
||||
)
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def next_path
|
||||
#
|
||||
if records_continue?
|
||||
api_v1_status_favourited_by_index_url pagination_params(max_id: pagination_max_id)
|
||||
end
|
||||
end
|
||||
|
||||
def prev_path
|
||||
#
|
||||
unless @accounts.empty?
|
||||
api_v1_status_favourited_by_index_url pagination_params(since_id: pagination_since_id)
|
||||
end
|
||||
end
|
||||
|
||||
def pagination_max_id
|
||||
#
|
||||
@accounts.last.favourites.last.id
|
||||
end
|
||||
|
||||
def pagination_since_id
|
||||
#
|
||||
@accounts.first.favourites.first.id
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
#
|
||||
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||
end
|
||||
|
||||
def set_status
|
||||
#
|
||||
@status = Status.find(params[:status_id])
|
||||
authorize @status, :show?
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
#
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
def verify_own_status
|
||||
unless @status.account.id == current_account.id
|
||||
render json: {}, status: 404
|
||||
end
|
||||
end
|
||||
end
|
@ -99,7 +99,7 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def current_theme
|
||||
'light'
|
||||
'default'
|
||||
# : todo :
|
||||
# current_user.setting_theme
|
||||
end
|
||||
|
@ -258,8 +258,7 @@ export const fetchListSuggestions = (q) => (dispatch, getState) => {
|
||||
const params = {
|
||||
q,
|
||||
resolve: false,
|
||||
limit: 4,
|
||||
following: true,
|
||||
limit: 25,
|
||||
};
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
|
@ -4,6 +4,7 @@ import { me } from '../initial_state'
|
||||
export const GIFS_CLEAR_RESULTS = 'GIFS_CLEAR_RESULTS'
|
||||
export const GIF_SET_SELECTED = 'GIF_SET_SELECTED'
|
||||
export const GIF_CHANGE_SEARCH_TEXT = 'GIF_CHANGE_SEARCH_TEXT'
|
||||
export const GIF_CLEAR_SELECTED = 'GIF_CLEAR_SELECTED'
|
||||
|
||||
export const GIF_RESULTS_FETCH_REQUEST = 'GIF_RESULTS_FETCH_REQUEST'
|
||||
export const GIF_RESULTS_FETCH_SUCCESS = 'GIF_RESULTS_FETCH_SUCCESS'
|
||||
|
@ -135,6 +135,8 @@ class Account extends ImmutablePureComponent {
|
||||
isOutline={true}
|
||||
color='brand'
|
||||
backgroundColor='none'
|
||||
icon={actionIcon}
|
||||
iconSize='10px'
|
||||
>
|
||||
{actionTitle}
|
||||
</Button>
|
||||
|
@ -265,7 +265,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
className={textareaClasses}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={false}
|
||||
dautoFocus={false}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
// onKeyDown={this.onKeyDown}
|
||||
|
@ -138,6 +138,7 @@ export default class Button extends PureComponent {
|
||||
cursorPointer: 1,
|
||||
textAlignCenter: 1,
|
||||
outlineNone: 1,
|
||||
// outlineOnFocus: !isText,
|
||||
flexRow: !!children && !!icon,
|
||||
cursorNotAllowed: isDisabled,
|
||||
opacity05: isDisabled,
|
||||
@ -221,6 +222,9 @@ export default class Button extends PureComponent {
|
||||
)
|
||||
}
|
||||
|
||||
const isLogout = href === '/auth/sign_out'
|
||||
const dataMethod = isLogout ? 'delete' : undefined
|
||||
|
||||
const options = {
|
||||
rel,
|
||||
target,
|
||||
@ -230,6 +234,7 @@ export default class Button extends PureComponent {
|
||||
className: classes,
|
||||
href: href || undefined,
|
||||
ref: this.setRef,
|
||||
'data-method': dataMethod,
|
||||
...handlers,
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
import classnames from 'classnames/bind'
|
||||
|
||||
// Bind CSS Modules global variable `_s` to classNames module
|
||||
const cx = classnames.bind(_s)
|
||||
import { CX } from '../constants'
|
||||
|
||||
/**
|
||||
* Renders a divider component
|
||||
@ -18,7 +15,7 @@ export default class Divider extends PureComponent {
|
||||
render() {
|
||||
const { isSmall, isInvisible } = this.props
|
||||
|
||||
const classes = cx({
|
||||
const classes = CX({
|
||||
default: 1,
|
||||
borderBottom1PX: !isInvisible,
|
||||
borderColorSecondary: !isInvisible,
|
||||
|
@ -31,13 +31,13 @@ export default class Heading extends PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, size, center } = this.props
|
||||
const { children, size, isCentered } = this.props
|
||||
|
||||
// Each size has it's own custom style
|
||||
const classes = cx({
|
||||
default: 1,
|
||||
text: 1,
|
||||
textAlignCenter: center,
|
||||
textAlignCenter: isCentered,
|
||||
|
||||
colorPrimary: [SIZES.h1, SIZES.h2].indexOf(size) > -1,
|
||||
colorSecondary: [SIZES.h3, SIZES.h4, SIZES.h5].indexOf(size) > -1,
|
||||
|
@ -54,11 +54,12 @@ class LinkFooter extends PureComponent {
|
||||
text: intl.formatMessage(messages.help),
|
||||
requiresUser: true,
|
||||
},
|
||||
{
|
||||
onClick: onOpenHotkeys,
|
||||
text: intl.formatMessage(messages.hotkeys),
|
||||
requiresUser: true,
|
||||
},
|
||||
// : todo :
|
||||
// {
|
||||
// onClick: onOpenHotkeys,
|
||||
// text: intl.formatMessage(messages.hotkeys),
|
||||
// requiresUser: true,
|
||||
// },
|
||||
{
|
||||
to: '/auth/edit',
|
||||
text: intl.formatMessage(messages.security),
|
||||
|
@ -56,6 +56,8 @@ export default class ListItem extends PureComponent {
|
||||
flexRow: 1,
|
||||
alignItemsCenter: 1,
|
||||
width100PC: 1,
|
||||
outlineNone: 1,
|
||||
bgTransparent: 1,
|
||||
bgSubtle_onHover: 1,
|
||||
borderColorSecondary: !isLast,
|
||||
borderBottom1PX: !isLast,
|
||||
|
@ -8,7 +8,7 @@ import SettingSwitch from '../setting_switch'
|
||||
import Text from '../text'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'community_timeline_settings', defaultMessage: 'Community Timeline Settings' },
|
||||
title: { id: 'community_timeline_settings', defaultMessage: 'Community Feed Settings' },
|
||||
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
|
||||
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
|
||||
showInSidebar: { id: 'show_in_sidebar', defaultMessage: 'Show in Sidebar' },
|
||||
@ -18,8 +18,7 @@ const mapStateToProps = (state) => ({
|
||||
settings: state.getIn(['settings', 'community']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch, { onClose }) => {
|
||||
return {
|
||||
const mapDispatchToProps = (dispatch, { onClose }) => ({
|
||||
onChange(key, checked) {
|
||||
dispatch(changeSetting(['community', ...key], checked))
|
||||
},
|
||||
@ -27,8 +26,7 @@ const mapDispatchToProps = (dispatch, { onClose }) => {
|
||||
dispatch(saveSettings())
|
||||
onClose()
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@ -39,6 +37,7 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
|
||||
intl: PropTypes.object.isRequired,
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onSave: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
@ -47,10 +46,16 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, settings, onChange, onClose } = this.props
|
||||
const {
|
||||
intl,
|
||||
settings,
|
||||
onChange,
|
||||
onClose,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
onClose={onClose}
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
>
|
||||
|
@ -14,8 +14,6 @@ class ConfirmationModal extends PureComponent {
|
||||
confirm: PropTypes.any.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
secondary: PropTypes.string,
|
||||
onSecondary: PropTypes.func,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onCancel: PropTypes.func,
|
||||
}
|
||||
@ -29,11 +27,6 @@ class ConfirmationModal extends PureComponent {
|
||||
this.props.onConfirm()
|
||||
}
|
||||
|
||||
handleSecondary = () => {
|
||||
this.props.onClose()
|
||||
this.props.onSecondary()
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
const { onClose, onCancel } = this.props
|
||||
onClose()
|
||||
@ -49,7 +42,6 @@ class ConfirmationModal extends PureComponent {
|
||||
title,
|
||||
message,
|
||||
confirm,
|
||||
secondary
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
@ -74,19 +66,11 @@ class ConfirmationModal extends PureComponent {
|
||||
onClick={this.handleCancel}
|
||||
className={[_s.mr10, _s.flexGrow1].join(' ')}
|
||||
>
|
||||
<Text size='medium' weight='bold' color='inherit'>
|
||||
<Text size='medium' weight='bold' align='center' color='inherit'>
|
||||
<FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
{ /**
|
||||
: todo :
|
||||
*/
|
||||
secondary !== undefined && (
|
||||
<Button text={secondary} onClick={this.handleSecondary} />
|
||||
)
|
||||
}
|
||||
|
||||
<Button
|
||||
backgroundColor='brand'
|
||||
color='white'
|
||||
@ -94,7 +78,7 @@ class ConfirmationModal extends PureComponent {
|
||||
ref={this.setRef}
|
||||
className={_s.flexGrow1}
|
||||
>
|
||||
<Text size='medium' weight='bold' color='inherit'>
|
||||
<Text size='medium' weight='bold' align='center' color='inherit'>
|
||||
{confirm}
|
||||
</Text>
|
||||
</Button>
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { changeSetting, saveSettings } from '../../actions/settings'
|
||||
import {
|
||||
DEFAULT_THEME,
|
||||
DEFAULT_FONT_SIZE,
|
||||
FONT_SIZES,
|
||||
} from '../../constants'
|
||||
import ModalLayout from './modal_layout'
|
||||
import Button from '../button'
|
||||
import Text from '../text'
|
||||
@ -12,12 +18,15 @@ const messages = defineMessages({
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
settings: state.getIn(['notifications', 'filter']),
|
||||
displayOptionsSettings: state.getIn(['settings', 'displayOptions']),
|
||||
fontSize: state.getIn(['settings', 'displayOptions', 'fontSize'], DEFAULT_FONT_SIZE),
|
||||
theme: state.getIn(['settings', 'displayOptions', 'theme'], DEFAULT_THEME),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onChange(path, value) {
|
||||
dispatch(setFilter(path, value))
|
||||
onChange(key, value) {
|
||||
dispatch(changeSetting(['displayOptions', key], value))
|
||||
dispatch(saveSettings())
|
||||
},
|
||||
})
|
||||
|
||||
@ -27,34 +36,47 @@ export default
|
||||
class DisplayOptionsModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
fontSize: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
displayOptionsSettings: ImmutablePropTypes.map,
|
||||
theme: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClose()
|
||||
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||
updateOnProps = [
|
||||
'fontSize',
|
||||
'displayOptionsSettings',
|
||||
'theme',
|
||||
]
|
||||
|
||||
handleOnFontSizeChange = (e) => {
|
||||
const fontSizeNames = Object.keys(FONT_SIZES)
|
||||
const index = fontSizeNames[e.target.value]
|
||||
|
||||
this.props.onChange('fontSize', index)
|
||||
}
|
||||
|
||||
// document.documentElement.style.setProperty("--color-surface", "black");
|
||||
handleOnThemeSelected = (e) => {
|
||||
this.props.onChange('theme', e.target.value)
|
||||
}
|
||||
|
||||
handleOnRadiusKeyDisabled = (key, checked) => {
|
||||
this.props.onChange(key, checked)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
account,
|
||||
fontSize,
|
||||
displayOptionsSettings,
|
||||
intl,
|
||||
settings,
|
||||
onChange,
|
||||
theme,
|
||||
onClose,
|
||||
} = this.props
|
||||
|
||||
// theme - light, muted, dark
|
||||
// text size - extra small, small, normal, medium, large, extra large
|
||||
// rounded borders
|
||||
const fontSizeNames = Object.keys(FONT_SIZES)
|
||||
const currentFontSizeIndex = fontSizeNames.indexOf(fontSize)
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
@ -64,79 +86,107 @@ class DisplayOptionsModal extends ImmutablePureComponent {
|
||||
>
|
||||
|
||||
<div className={[_s.default, _s.mb15].join(' ')}>
|
||||
<Text>
|
||||
<Text align='center' color='secondary' size='medium'>
|
||||
{intl.formatMessage(messages.message)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.mb10].join(' ')}>
|
||||
<Text weight='bold' color='secondary'>
|
||||
<div className={[_s.default, _s.mb15].join(' ')}>
|
||||
<Text weight='bold' size='small' color='secondary'>
|
||||
Font Size
|
||||
</Text>
|
||||
<div className={[_s.default, _s.radiusSmall, _s.mt10, _s.py15, _s.px15, _s.bgTertiary].join(' ')}>
|
||||
test
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<span className={[_s.default, _s.text, _s.colorPrimary].join(' ')} style={{fontSize: '12px'}}>
|
||||
Aa
|
||||
</span>
|
||||
<input
|
||||
type='range'
|
||||
min='0'
|
||||
value={currentFontSizeIndex}
|
||||
max={fontSizeNames.length - 1}
|
||||
onInput={this.handleOnFontSizeChange}
|
||||
onChange={this.handleOnFontSizeChange}
|
||||
className={[_s.flexGrow1, _s.outlineNone, _s.ml15, _s.mr15].join(' ')}
|
||||
/>
|
||||
<span className={[_s.default, _s.text, _s.colorPrimary].join(' ')} style={{fontSize: '18px'}}>
|
||||
Aa
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.mb10].join(' ')}>
|
||||
<Text weight='bold' color='secondary'>
|
||||
<div className={[_s.default, _s.mb15].join(' ')}>
|
||||
<Text weight='bold' size='small' color='secondary'>
|
||||
Rounded
|
||||
</Text>
|
||||
<div className={[_s.default, _s.radiusSmall, _s.mt10, _s.py15, _s.px15, _s.bgTertiary].join(' ')}>
|
||||
<SettingSwitch
|
||||
prefix='notification'
|
||||
settings={settings}
|
||||
settingPath={'onlyVerified'}
|
||||
onChange={onChange}
|
||||
label={'Small Radius'}
|
||||
prefix='displayOptions'
|
||||
settings={displayOptionsSettings}
|
||||
settingPath={'radiusSmallDisabled'}
|
||||
onChange={this.handleOnRadiusKeyDisabled}
|
||||
label={'Small Radius Disabled'}
|
||||
/>
|
||||
|
||||
<SettingSwitch
|
||||
prefix='notification'
|
||||
settings={settings}
|
||||
settingPath={'onlyVerified'}
|
||||
onChange={onChange}
|
||||
label={'Circle Radius'}
|
||||
prefix='displayOptions'
|
||||
settings={displayOptionsSettings}
|
||||
settingPath={'radiusCircleDisabled'}
|
||||
onChange={this.handleOnRadiusKeyDisabled}
|
||||
label={'Circles Disabled'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.mb10].join(' ')}>
|
||||
<Text weight='bold' color='secondary'>
|
||||
<Text weight='bold' size='small' color='secondary'>
|
||||
Theme
|
||||
</Text>
|
||||
<div className={[_s.default, _s.radiusSmall, _s.flexRow, _s.mt10, _s.py15, _s.px15, _s.bgTertiary].join(' ')}>
|
||||
<div className={[_s.default, _s.radiusSmall, _s.flexRow, _s.mt10, _s.py10, _s.bgTertiary].join(' ')}>
|
||||
|
||||
<div className={[_s.default, _s.py10, _s.px10, _s.flexGrow1].join(' ')}>
|
||||
<div className={[_s.default, _s.bgPrimary, _s.radiusSmall]}>
|
||||
<Text>
|
||||
Light
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<ThemeBlock
|
||||
title='Light'
|
||||
value='light'
|
||||
checked={theme === 'light'}
|
||||
onChange={this.handleOnThemeSelected}
|
||||
style={{
|
||||
borderColor: '#ececed',
|
||||
backgroundColor: '#fff',
|
||||
color: '#2d3436',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className={[_s.default, _s.py10, _s.px10, _s.flexGrow1].join(' ')}>
|
||||
<div className={[_s.default, _s.bgPrimary, _s.radiusSmall]}>
|
||||
<Text>
|
||||
Muted
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<ThemeBlock
|
||||
title='Muted'
|
||||
value='muted'
|
||||
checked={theme === 'muted'}
|
||||
onChange={this.handleOnThemeSelected}
|
||||
style={{
|
||||
borderColor: '#424141',
|
||||
backgroundColor: '#222',
|
||||
color: '#fff',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className={[_s.default, _s.py10, _s.px10, _s.flexGrow1].join(' ')}>
|
||||
<div className={[_s.default, _s.bgPrimary, _s.radiusSmall]}>
|
||||
<Text>
|
||||
Black
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<ThemeBlock
|
||||
title='Black'
|
||||
value='black'
|
||||
checked={theme === 'black'}
|
||||
onChange={this.handleOnThemeSelected}
|
||||
style={{
|
||||
borderColor: '#212020',
|
||||
backgroundColor: '#13171b',
|
||||
color: '#cccbcb',
|
||||
}}
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={[_s.mlAuto, _s.mrAuto].join(' ')}>
|
||||
<Button>
|
||||
<Text size='medium' color='inherit'>
|
||||
<div className={[_s.mlAuto, _s.my10, _s.mrAuto].join(' ')}>
|
||||
<Button onClick={onClose}>
|
||||
<Text size='medium' color='inherit' className={_s.px10}>
|
||||
Done
|
||||
</Text>
|
||||
</Button>
|
||||
@ -147,3 +197,54 @@ class DisplayOptionsModal extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ThemeBlock extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
checked: PropTypes.bool,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
title: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
checked,
|
||||
onChange,
|
||||
title,
|
||||
value,
|
||||
style,
|
||||
} = this.props
|
||||
|
||||
const id = `theme-${value}`
|
||||
|
||||
return (
|
||||
<label className={[_s.default, _s.px10, _s.flexGrow1].join(' ')} htmlFor={id}>
|
||||
<div
|
||||
className={[_s.default, _s.borderBottom6PX, _s.alignItemsCenter, _s.flexRow, _s.py10, _s.px15, _s.radiusSmall].join(' ')}
|
||||
style={style}
|
||||
>
|
||||
<input
|
||||
type='radio'
|
||||
name='theme'
|
||||
value={value}
|
||||
id={id}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<Text
|
||||
align='center'
|
||||
size='medium'
|
||||
weight='bold'
|
||||
color='inherit'
|
||||
className={[_s.py10, _s.flexGrow1].join(' ')}
|
||||
>
|
||||
{title}
|
||||
</Text>
|
||||
</div>
|
||||
</label>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { deleteList } from '../../actions/lists'
|
||||
import ConfirmationModal from './confirmation_modal'
|
||||
@ -9,24 +11,24 @@ const messages = defineMessages({
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onConfirm(listId) {
|
||||
dispatch(deleteList(listId))
|
||||
},
|
||||
onConfirm: (listId) => dispatch(deleteList(listId)),
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(null, mapDispatchToProps)
|
||||
class ListDeleteModal extends PureComponent {
|
||||
class ListDeleteModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
list: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
list: ImmutablePropTypes.map.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onConfirm(this.props.list.get('id'))
|
||||
// : todo :
|
||||
// redirect back to /lists
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -14,19 +14,20 @@ class ListEditorModal extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
listId: PropTypes.string.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, onClose, listId } = this.props
|
||||
const { intl, onClose, id } = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
noPadding
|
||||
>
|
||||
<ListEdit listId={listId} />
|
||||
<ListEdit id={id} />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ const mapStateToProps = (state) => ({
|
||||
settings: state.getIn(['settings', 'list']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch, { onClose }) => {
|
||||
return {
|
||||
const mapDispatchToProps = (dispatch, { onClose }) => ({
|
||||
onChange(key, checked) {
|
||||
dispatch(changeSetting(['list', ...key], checked))
|
||||
},
|
||||
@ -30,8 +29,7 @@ const mapDispatchToProps = (dispatch, { onClose }) => {
|
||||
dispatch(saveSettings())
|
||||
onClose()
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
|
@ -29,6 +29,8 @@ import {
|
||||
MODAL_MUTE,
|
||||
MODAL_PRO_UPGRADE,
|
||||
MODAL_REPORT,
|
||||
MODAL_STATUS_LIKES,
|
||||
MODAL_STATUS_REPOSTS,
|
||||
MODAL_STATUS_REVISIONS,
|
||||
MODAL_UNAUTHORIZED,
|
||||
MODAL_UNFOLLOW,
|
||||
@ -60,6 +62,8 @@ import {
|
||||
MuteModal,
|
||||
ProUpgradeModal,
|
||||
ReportModal,
|
||||
StatusLikesModal,
|
||||
StatusRepostsModal,
|
||||
StatusRevisionsModal,
|
||||
UnauthorizedModal,
|
||||
UnfollowModal,
|
||||
@ -92,6 +96,8 @@ MODAL_COMPONENTS[MODAL_MEDIA] = MediaModal
|
||||
MODAL_COMPONENTS[MODAL_MUTE] = MuteModal
|
||||
MODAL_COMPONENTS[MODAL_PRO_UPGRADE] = ProUpgradeModal
|
||||
MODAL_COMPONENTS[MODAL_REPORT] = ReportModal
|
||||
MODAL_COMPONENTS[MODAL_STATUS_LIKES] = StatusLikesModal
|
||||
MODAL_COMPONENTS[MODAL_STATUS_REPOSTS] = StatusRepostsModal
|
||||
MODAL_COMPONENTS[MODAL_STATUS_REVISIONS] = StatusRevisionsModal
|
||||
MODAL_COMPONENTS[MODAL_UNAUTHORIZED] = UnauthorizedModal
|
||||
MODAL_COMPONENTS[MODAL_UNFOLLOW] = UnfollowModal
|
||||
|
@ -0,0 +1,44 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import StatusLikes from '../../features/status_likes'
|
||||
import ModalLayout from './modal_layout'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'likes', defaultMessage: 'Likes' },
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class StatusLikesModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
onClose,
|
||||
status,
|
||||
} = this.props
|
||||
|
||||
const params = {
|
||||
statusId: status.get('id'),
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
noPadding
|
||||
>
|
||||
<StatusLikes params={params} />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import StatusReposts from '../../features/status_reposts'
|
||||
import ModalLayout from './modal_layout'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'reposts', defaultMessage: 'Reposts' },
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class StatusRepostsModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
onClose,
|
||||
status,
|
||||
} = this.props
|
||||
|
||||
const params = {
|
||||
statusId: status.get('id'),
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
noPadding
|
||||
>
|
||||
<StatusReposts params={params} />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { muteAccount } from '../../actions/accounts'
|
||||
|
||||
const messages = defineMessages({
|
||||
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||
account: state.getIn(['mutes', 'new', 'account']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onConfirm(account, notifications) {
|
||||
dispatch(muteAccount(account.get('id'), notifications))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class UnfollowModal extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.button.focus()
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClose()
|
||||
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.props.onClose()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
|
||||
// , {
|
||||
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||
// }));
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={`Mute @${account.get('acct')}`}
|
||||
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||
onConfirm={() => {
|
||||
// dispatch(blockDomain(domain))
|
||||
// dispatch(blockDomain(domain))
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import moment from 'moment-mini'
|
||||
import PanelLayout from './panel_layout'
|
||||
import ColumnIndicator from '../column_indicator'
|
||||
import Divider from '../divider'
|
||||
import Icon from '../icon'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
import Text from '../text'
|
||||
|
||||
const messages = defineMessages({
|
||||
@ -18,16 +19,20 @@ class ListDetailsPanel extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
list: ImmutablePropTypes.map,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
handleOnEdit = () => {
|
||||
this.props.onEdit()
|
||||
}
|
||||
updateOnProps = [
|
||||
'list',
|
||||
]
|
||||
|
||||
render() {
|
||||
const { intl, list } = this.props
|
||||
const {
|
||||
intl,
|
||||
list,
|
||||
onEdit,
|
||||
} = this.props
|
||||
|
||||
const title = !!list ? list.get('title') : ''
|
||||
const createdAt = !!list ? list.get('created_at') : ''
|
||||
@ -36,11 +41,17 @@ class ListDetailsPanel extends ImmutablePureComponent {
|
||||
<PanelLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
headerButtonTitle={intl.formatMessage(messages.edit)}
|
||||
headerButtonAction={this.handleOnEdit}
|
||||
headerButtonAction={onEdit}
|
||||
>
|
||||
{
|
||||
(!title || !createdAt) &&
|
||||
<ColumnIndicator type='loading' />
|
||||
}
|
||||
{
|
||||
title && createdAt &&
|
||||
<div className={_s.default}>
|
||||
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<div className={_s.default}>
|
||||
<Text weight='medium'>
|
||||
{title}
|
||||
</Text>
|
||||
@ -57,13 +68,14 @@ class ListDetailsPanel extends ImmutablePureComponent {
|
||||
>
|
||||
{
|
||||
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
|
||||
date: <RelativeTimestamp timestamp={createdAt} />,
|
||||
date: moment(createdAt).format('lll'),
|
||||
}} />
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
</PanelLayout>
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { MODAL_DISPLAY_OPTIONS } from '../../constants'
|
||||
import { openModal } from '../../actions/modal'
|
||||
import { closePopover } from '../../actions/popover'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import List from '../list'
|
||||
|
||||
@ -13,6 +14,7 @@ const messages = defineMessages({
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenDisplayModal: () => {
|
||||
dispatch(closePopover())
|
||||
dispatch(openModal(MODAL_DISPLAY_OPTIONS))
|
||||
},
|
||||
})
|
||||
@ -54,7 +56,7 @@ class SidebarMorePopover extends PureComponent {
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage(messages.logout),
|
||||
href: '/auth/log_out',
|
||||
href: '/auth/sign_out',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
@ -2,6 +2,7 @@ import throttle from 'lodash.throttle'
|
||||
import { List as ImmutableList } from 'immutable'
|
||||
import IntersectionObserverArticle from './intersection_observer_article'
|
||||
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
|
||||
import Block from './block'
|
||||
import ColumnIndicator from './column_indicator'
|
||||
import LoadMore from './load_more'
|
||||
|
||||
@ -250,7 +251,11 @@ export default class ScrollableList extends PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
return <ColumnIndicator type='error' message={emptyMessage} />
|
||||
return (
|
||||
<Block>
|
||||
<ColumnIndicator type='error' message={emptyMessage} />
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ class Search extends PureComponent {
|
||||
onChange={this.handleOnChange}
|
||||
onFocus={this.handleOnFocus}
|
||||
onBlur={this.handleOnBlur}
|
||||
autoComplete='off'
|
||||
/>
|
||||
|
||||
<Button
|
||||
|
@ -16,6 +16,14 @@ export default class SettingSwitch extends ImmutablePureComponent {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
updateOnProps = [
|
||||
'prefix',
|
||||
'settings',
|
||||
'settingPath',
|
||||
'description',
|
||||
'label',
|
||||
]
|
||||
|
||||
onChange = ({ target }) => {
|
||||
this.props.onChange(this.props.settingPath, target.checked)
|
||||
}
|
||||
|
@ -38,17 +38,13 @@ const messages = defineMessages({
|
||||
donate: { id: 'tabs_bar.donate', defaultMessage: 'Make a Donation' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const getAccount = makeGetAccount()
|
||||
|
||||
return {
|
||||
account: getAccount(state, me),
|
||||
const mapStateToProps = (state) => ({
|
||||
account: makeGetAccount()(state, me),
|
||||
moreOpen: state.getIn(['popover', 'popoverType']) === 'SIDEBAR_MORE',
|
||||
notificationCount: state.getIn(['notifications', 'unread']),
|
||||
homeItemsQueueCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
|
||||
showCommunityTimeline: state.getIn(['settings', 'community', 'shows', 'inSidebar']),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onClose() {
|
||||
@ -226,23 +222,46 @@ class Sidebar extends ImmutablePureComponent {
|
||||
<div className={[_s.default, _s.width240PX].join(' ')}>
|
||||
<div className={[_s.default, _s.posFixed, _s.heightCalc53PX, _s.bottom0].join(' ')}>
|
||||
<div className={[_s.default, _s.height100PC, _s.alignItemsStart, _s.width240PX, _s.pr15, _s.py10, _s.overflowYScroll].join(' ')}>
|
||||
<div className={_s.default}>
|
||||
<div className={[_s.default, _s.width100PC].join(' ')}>
|
||||
{
|
||||
!!title &&
|
||||
<div className={[_s.default, _s.flexRow, _s.px5, _s.py10].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.px5, _s.pt10].join(' ')}>
|
||||
{
|
||||
showBackBtn &&
|
||||
<Button
|
||||
noClasses
|
||||
color='primary'
|
||||
backgroundColor='none'
|
||||
className={[_s.alignItemsCenter, _s.bgTransparent, _s.mr5, _s.cursorPointer, _s.outlineNone, _s.default, _s.justifyContentCenter].join(' ')}
|
||||
icon='back'
|
||||
iconSize='20px'
|
||||
icon='arrow-left'
|
||||
iconSize='24px'
|
||||
iconClassName={[_s.mr5, _s.fillPrimary].join(' ')}
|
||||
onClick={this.handleBackClick}
|
||||
/>
|
||||
}
|
||||
<Heading size='h1'>
|
||||
{title}
|
||||
</Heading>
|
||||
{
|
||||
!!actions &&
|
||||
<div className={[_s.default, _s.bgTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.mlAuto].join(' ')}>
|
||||
{
|
||||
actions.map((action, i) => (
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
color='primary'
|
||||
onClick={() => action.onClick()}
|
||||
key={`action-btn-${i}`}
|
||||
className={[_s.ml5, _s.px5].join(' ')}
|
||||
icon={action.icon}
|
||||
iconClassName={_s.fillPrimary}
|
||||
iconSize='14px'
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
{
|
||||
|
@ -89,6 +89,8 @@ class Status extends ImmutablePureComponent {
|
||||
cachedMediaWidth: PropTypes.number,
|
||||
contextType: PropTypes.string,
|
||||
commentsLimited: PropTypes.bool,
|
||||
onOpenLikes: PropTypes.func.isRequired,
|
||||
onOpenReposts: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
// Avoid checking props that are functions (and whose equality will always
|
||||
@ -472,6 +474,8 @@ class Status extends ImmutablePureComponent {
|
||||
onReply={this.props.onReply}
|
||||
onRepost={this.props.onRepost}
|
||||
onShare={this.props.onShare}
|
||||
onOpenLikes={this.props.onOpenLikes}
|
||||
onOpenReposts={this.props.onOpenReposts}
|
||||
/>
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,8 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
onReply: PropTypes.func.isRequired,
|
||||
onRepost: PropTypes.func.isRequired,
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
onOpenLikes: PropTypes.func.isRequired,
|
||||
onOpenReposts: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
updateOnProps = ['status']
|
||||
@ -58,15 +60,11 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
openLikesList = () => {
|
||||
// : todo :
|
||||
}
|
||||
|
||||
toggleCommentsVisible = () => {
|
||||
// : todo :
|
||||
this.props.onOpenLikes(this.props.status)
|
||||
}
|
||||
|
||||
openRepostsList = () => {
|
||||
// : todo :
|
||||
this.props.onOpenReposts(this.props.status)
|
||||
}
|
||||
|
||||
setRepostButton = (n) => {
|
||||
|
@ -35,6 +35,7 @@ export default class Switch extends PureComponent {
|
||||
circle: 1,
|
||||
border1PX: 1,
|
||||
mlAuto: 1,
|
||||
bgPrimary: 1,
|
||||
borderColorSecondary: 1,
|
||||
bgBrand: checked,
|
||||
})
|
||||
|
@ -56,6 +56,8 @@ export const MODAL_MEDIA = 'MEDIA'
|
||||
export const MODAL_MUTE = 'MUTE'
|
||||
export const MODAL_PRO_UPGRADE = 'PRO_UPGRADE'
|
||||
export const MODAL_REPORT = 'REPORT'
|
||||
export const MODAL_STATUS_LIKES = 'STATUS_LIKES'
|
||||
export const MODAL_STATUS_REPOSTS = 'STATUS_REPOSTS'
|
||||
export const MODAL_STATUS_REVISIONS = 'STATUS_REVISIONS'
|
||||
export const MODAL_UNAUTHORIZED = 'UNAUTHORIZED'
|
||||
export const MODAL_UNFOLLOW = 'UNFOLLOW'
|
||||
@ -69,13 +71,14 @@ export const FONT_SIZES_LARGE = '16px'
|
||||
export const FONT_SIZES_EXTRA_LARGE = '17px'
|
||||
|
||||
export const FONT_SIZES = {
|
||||
'extra-small': FONT_SIZES_EXTRA_SMALL,
|
||||
small: FONT_SIZES_SMALL,
|
||||
normal: FONT_SIZES_NORMAL,
|
||||
medium: FONT_SIZES_MEDIUM,
|
||||
large: FONT_SIZES_LARGE,
|
||||
'extra-large': FONT_SIZES_EXTRA_LARGE,
|
||||
'extra-small': '12px',
|
||||
small: '13px',
|
||||
normal: '14px',
|
||||
medium: '15px',
|
||||
large: '16px',
|
||||
'extra-large': '17px',
|
||||
}
|
||||
|
||||
export const THEMES = [
|
||||
'light',
|
||||
'muted',
|
||||
|
@ -5,39 +5,55 @@ import {
|
||||
DEFAULT_FONT_SIZE,
|
||||
} from '../constants'
|
||||
|
||||
export default class Display extends PureComponent {
|
||||
const mapStateToProps = (state) => ({
|
||||
fontSize: state.getIn(['settings', 'displayOptions', 'fontSize']),
|
||||
radiusSmallDisabled: state.getIn(['settings', 'displayOptions', 'radiusSmallDisabled']),
|
||||
radiusCircleDisabled: state.getIn(['settings', 'displayOptions', 'radiusCircleDisabled']),
|
||||
theme: state.getIn(['settings', 'displayOptions', 'theme']),
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class Display extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
theme: PropTypes.string.isRequired,
|
||||
rounded: PropTypes.bool.isRequired,
|
||||
fontSize: PropTypes.string.isRequired,
|
||||
radiusSmallDisabled: PropTypes.bool.isRequired,
|
||||
radiusCircleDisabled: PropTypes.bool.isRequired,
|
||||
theme: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
theme: this.props.theme,
|
||||
rounded: this.props.rounded,
|
||||
radiusSmallDisabled: this.props.radiusSmallDisabled,
|
||||
radiusCircleDisabled: this.props.radiusCircleDisabled,
|
||||
fontSize: this.props.fontSize,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
theme: 'BLACK',
|
||||
rounded: false,
|
||||
theme: 'light',
|
||||
radiusSmallDisabled: true,
|
||||
radiusCircleDisabled: true,
|
||||
fontSize: 'normal',
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateTheme(this.state.theme)
|
||||
this.updateRounded(this.state.rounded)
|
||||
this.updateRadiusSmallDisabled(this.state.radiusSmallDisabled)
|
||||
this.updateRadiusCircleDisabled(this.state.radiusCircleDisabled)
|
||||
this.updateFontSizes(this.state.fontSize)
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
console.log("nextProps:", nextProps)
|
||||
if (nextProps.theme !== prevState.theme ||
|
||||
nextProps.rounded !== prevState.rounded ||
|
||||
nextProps.radiusSmallDisabled !== prevState.radiusSmallDisabled ||
|
||||
nextProps.radiusCircleDisabled !== prevState.radiusCircleDisabled ||
|
||||
nextProps.fontSize !== prevState.fontSize) {
|
||||
return {
|
||||
theme: nextProps.theme,
|
||||
rounded: nextProps.rounded,
|
||||
radiusSmallDisabled: nextProps.radiusSmallDisabled,
|
||||
radiusCircleDisabled: nextProps.radiusCircleDisabled,
|
||||
fontSize: nextProps.fontSize,
|
||||
}
|
||||
}
|
||||
@ -50,8 +66,12 @@ export default class Display extends PureComponent {
|
||||
this.updateTheme(this.state.theme)
|
||||
}
|
||||
|
||||
if (prevState.rounded !== this.state.rounded) {
|
||||
this.updateRounded(this.state.rounded)
|
||||
if (prevState.radiusSmallDisabled !== this.state.radiusSmallDisabled) {
|
||||
this.updateRadiusSmallDisabled(this.state.radiusSmallDisabled)
|
||||
}
|
||||
|
||||
if (prevState.radiusCircleDisabled !== this.state.radiusCircleDisabled) {
|
||||
this.updateRadiusCircleDisabled(this.state.radiusCircleDisabled)
|
||||
}
|
||||
|
||||
if (prevState.fontSize !== this.state.fontSize) {
|
||||
@ -59,16 +79,24 @@ export default class Display extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
updateRounded(rounded) {
|
||||
if (rounded) {
|
||||
document.documentElement.removeAttribute('rounded')
|
||||
updateRadiusSmallDisabled(disabled) {
|
||||
if (disabled) {
|
||||
document.documentElement.setAttribute('no-radius', '');
|
||||
} else {
|
||||
document.documentElement.setAttribute('rounded', '')
|
||||
document.documentElement.removeAttribute('no-radius')
|
||||
}
|
||||
}
|
||||
|
||||
updateRadiusCircleDisabled(disabled) {
|
||||
if (disabled) {
|
||||
document.documentElement.setAttribute('no-circle', '');
|
||||
} else {
|
||||
document.documentElement.removeAttribute('no-circle')
|
||||
}
|
||||
}
|
||||
|
||||
updateFontSizes(fontSize) {
|
||||
let correctedFontSize = fontSize.toUpperCase()
|
||||
let correctedFontSize = fontSize.toLowerCase()
|
||||
if (!FONT_SIZES.hasOwnProperty(correctedFontSize)) {
|
||||
correctedFontSize = DEFAULT_FONT_SIZE
|
||||
}
|
||||
@ -78,7 +106,7 @@ export default class Display extends PureComponent {
|
||||
|
||||
updateTheme(theme) {
|
||||
let correctedTheme = theme.toLowerCase()
|
||||
if (!THEMES.hasOwnProperty(correctedTheme)) {
|
||||
if (THEMES.indexOf(correctedTheme) < 0) {
|
||||
correctedTheme = DEFAULT_THEME
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ const makeMapStateToProps = () => {
|
||||
const ids = [status.get('id')]
|
||||
|
||||
const r = state.getIn(['contexts', 'replies', ids[0]])
|
||||
console.log("r:", r)
|
||||
// console.log("r:", r)
|
||||
|
||||
while (ids.length > 0) {
|
||||
let id = ids.shift()
|
||||
@ -253,6 +253,15 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchComments(statusId) {
|
||||
dispatch(fetchComments(statusId))
|
||||
},
|
||||
|
||||
onOpenLikes(status) {
|
||||
dispatch(openModal('STATUS_LIKES', { status }))
|
||||
},
|
||||
|
||||
onOpenReposts(status) {
|
||||
dispatch(openModal('STATUS_REPOSTS', { status }))
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default connect(makeMapStateToProps, mapDispatchToProps)(Status);
|
||||
|
@ -17,7 +17,7 @@ const messages = defineMessages({
|
||||
home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
|
||||
notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' },
|
||||
public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' },
|
||||
community: { id: 'navigation_bar.community_timeline', defaultMessage: 'Community timeline' },
|
||||
community: { id: 'navigation_bar.community_timeline', defaultMessage: 'Community feed' },
|
||||
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||
compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new gab' },
|
||||
|
@ -12,15 +12,9 @@ const messages = defineMessages({
|
||||
reject: { id: 'follow_request.reject', defaultMessage: 'Reject' },
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
account: getAccount(state, props.id),
|
||||
});
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
const makeMapStateToProps = () => ({
|
||||
account: makeGetAccount()(state, props.id),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch, { id }) => ({
|
||||
onAuthorize() {
|
||||
|
@ -1 +0,0 @@
|
||||
export { default } from './list'
|
@ -1,66 +0,0 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { removeFromListAdder, addToListAdder } from '../../../../actions/lists';
|
||||
import Button from '../../../../components/button';
|
||||
import Icon from '../../../../components/icon';
|
||||
|
||||
const messages = defineMessages({
|
||||
remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
||||
add: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
||||
});
|
||||
|
||||
const MapStateToProps = (state, { listId, added }) => ({
|
||||
list: state.get('lists').get(listId),
|
||||
added: typeof added === 'undefined' ? state.getIn(['listAdder', 'lists', 'items']).includes(listId) : added,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch, { listId }) => ({
|
||||
onRemove: () => dispatch(removeFromListAdder(listId)),
|
||||
onAdd: () => dispatch(addToListAdder(listId)),
|
||||
});
|
||||
|
||||
// : todo :
|
||||
|
||||
export default
|
||||
@connect(MapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class List extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
list: ImmutablePropTypes.map.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onRemove: PropTypes.func.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
added: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
added: false,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { list, intl, onRemove, onAdd, added } = this.props;
|
||||
|
||||
return (
|
||||
<div className='list'>
|
||||
<div className='list__wrapper'>
|
||||
<div className='list__name'>
|
||||
<Icon id='list-ul' className='list__name-icon' fixedWidth />
|
||||
{list.get('title')}
|
||||
</div>
|
||||
|
||||
<div className='list__btn-block'>
|
||||
{
|
||||
added ?
|
||||
<Button icon='times' title={intl.formatMessage(messages.remove)} onClick={onRemove} />
|
||||
:
|
||||
<Button icon='plus' title={intl.formatMessage(messages.add)} onClick={onAdd} />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
.list {
|
||||
padding: 4px;
|
||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||
|
||||
&__wrapper {
|
||||
display: flex;
|
||||
|
||||
.account__relationship {
|
||||
padding: 8px 5px 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&__name {
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
font-size: 16px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&__name-icon {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
&__btn-block {
|
||||
height: auto;
|
||||
position: relative;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { default } from './list_adder'
|
@ -1,90 +0,0 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { getOrderedLists } from '../../selectors'
|
||||
import { setupListAdder, resetListAdder } from '../../actions/lists';
|
||||
import List from './components/list';
|
||||
import Account from '../../components/account';
|
||||
import Button from '../../components/button';
|
||||
// import NewListForm from '../lists_directory/components/new_list_form';
|
||||
|
||||
const mapStateToProps = (state, { accountId }) => ({
|
||||
listIds: getOrderedLists(state).map(list => list.get('id')),
|
||||
account: state.getIn(['accounts', accountId]),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onInitialize: accountId => dispatch(setupListAdder(accountId)),
|
||||
onReset: () => dispatch(resetListAdder()),
|
||||
});
|
||||
|
||||
const messages = defineMessages({
|
||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||
subheading: { id: 'lists.subheading', defaultMessage: 'Your lists' },
|
||||
add: { id: 'lists.new.create', defaultMessage: 'Add List' },
|
||||
headerTitle: { id: 'list_adder.header_title', defaultMessage: 'Add or Remove from Lists' },
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListAdder extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
accountId: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onInitialize: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired,
|
||||
listIds: ImmutablePropTypes.list.isRequired,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { onInitialize, accountId } = this.props;
|
||||
onInitialize(accountId);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.onReset();
|
||||
}
|
||||
|
||||
onClickClose = () => {
|
||||
this.props.onClose('LIST_ADDER');
|
||||
};
|
||||
|
||||
render() {
|
||||
const { listIds, intl, account } = this.props;
|
||||
|
||||
return (
|
||||
<div className='modal-root__modal compose-modal'>
|
||||
<div className='compose-modal__header'>
|
||||
<h3 className='compose-modal__header__title'>
|
||||
{intl.formatMessage(messages.headerTitle)}
|
||||
</h3>
|
||||
<Button className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
|
||||
</div>
|
||||
<div className='compose-modal__content'>
|
||||
<div className='list-adder'>
|
||||
<div className='list-adder__account'>
|
||||
<Account account={account} displayOnly/>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
{ /* <NewListForm /> */ }
|
||||
|
||||
<br />
|
||||
|
||||
<div className='list-adder__lists'>
|
||||
{
|
||||
listIds.map(ListId => <List key={ListId} listId={ListId} />)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
316
app/javascript/gabsocial/features/list_edit.js
Normal file
316
app/javascript/gabsocial/features/list_edit.js
Normal file
@ -0,0 +1,316 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import isObject from 'lodash.isobject'
|
||||
import {
|
||||
setupListEditor,
|
||||
resetListEditor,
|
||||
removeFromListEditor,
|
||||
addToListEditor,
|
||||
fetchListSuggestions,
|
||||
clearListSuggestions,
|
||||
changeListSuggestions,
|
||||
} from '../actions/lists'
|
||||
import { openModal } from '../actions/modal'
|
||||
import {
|
||||
MODAL_LIST_EDITOR,
|
||||
MODAL_LIST_DELETE,
|
||||
} from '../constants'
|
||||
import Account from '../components/account'
|
||||
import Button from '../components/button'
|
||||
import Divider from '../components/divider'
|
||||
import Input from '../components/input'
|
||||
import TabBar from '../components/tab_bar'
|
||||
import Text from '../components/text'
|
||||
|
||||
const messages = defineMessages({
|
||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||
save: { id: 'lists.new.save_title', defaultMessage: 'Save Title' },
|
||||
changeTitle: { id: 'lists.edit.submit', defaultMessage: 'Change title' },
|
||||
addToList: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
||||
removeFromList: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
||||
editList: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
||||
editListTitle: { id: 'lists.new.edit_title_placeholder', defaultMessage: 'Edit list title' },
|
||||
remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
||||
add: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
||||
search: { id: 'lists.search', defaultMessage: 'Search people...' },
|
||||
searchMembers: { id: 'lists.search_members', defaultMessage: 'Search members...' },
|
||||
searchTitle: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, { params, id }) => {
|
||||
const listId = isObject(params) ? params['id'] : id
|
||||
|
||||
return {
|
||||
listId,
|
||||
list: state.getIn(['lists', listId]),
|
||||
title: state.getIn(['listEditor', 'title']),
|
||||
disabled: !state.getIn(['listEditor', 'isChanged']),
|
||||
accountIds: state.getIn(['listEditor', 'accounts', 'items']),
|
||||
searchAccountIds: state.getIn(['listEditor', 'suggestions', 'items']),
|
||||
searchSuggestionsValue: state.getIn(['listEditor', 'suggestions', 'value']),
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
onDeleteList(list) {
|
||||
dispatch(openModal(MODAL_LIST_DELETE, { list }))
|
||||
},
|
||||
|
||||
onChangeTitle(value) {
|
||||
dispatch(changeListEditorTitle(value))
|
||||
},
|
||||
|
||||
onUpdateList() {
|
||||
dispatch(submitListEditor(false))
|
||||
},
|
||||
|
||||
onInitialize(listId) {
|
||||
dispatch(setupListEditor(listId))
|
||||
},
|
||||
|
||||
onReset() {
|
||||
dispatch(resetListEditor())
|
||||
},
|
||||
|
||||
onRemoveAccountFromList(accountId) {
|
||||
dispatch(removeFromListEditor(accountId))
|
||||
},
|
||||
|
||||
onAddAccountToList(accountId) {
|
||||
dispatch(addToListEditor(accountId))
|
||||
},
|
||||
|
||||
onSubmitSearchSuggestions(value) {
|
||||
dispatch(fetchListSuggestions(value))
|
||||
},
|
||||
|
||||
onClearSearchSuggestions() {
|
||||
dispatch(clearListSuggestions())
|
||||
},
|
||||
|
||||
onChangeSuggestions(value) {
|
||||
dispatch(changeListSuggestions(value))
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListEdit extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
list: ImmutablePropTypes.map,
|
||||
title: PropTypes.string,
|
||||
listId: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onInitialize: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired,
|
||||
searchSuggestionsValue: PropTypes.string.isRequired,
|
||||
accountIds: ImmutablePropTypes.list.isRequired,
|
||||
searchAccountIds: ImmutablePropTypes.list.isRequired,
|
||||
onRemoveAccountFromList: PropTypes.func.isRequired,
|
||||
onAddAccountToList: PropTypes.func.isRequired,
|
||||
onChangeSuggestions: PropTypes.func.isRequired,
|
||||
onClearSearchSuggestions: PropTypes.func.isRequired,
|
||||
onSubmitSearchSuggestions: PropTypes.func.isRequired,
|
||||
onDeleteList: PropTypes.func.isRequired,
|
||||
tab: PropTypes.string,
|
||||
}
|
||||
|
||||
state = {
|
||||
activeTab: this.props.tab || 'members'
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { onInitialize, listId } = this.props
|
||||
if (listId) {
|
||||
onInitialize(listId)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.listId !== prevProps.listId) {
|
||||
this.props.onInitialize(this.props.listId)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.onReset()
|
||||
}
|
||||
|
||||
handleChangeTab = (tab) => {
|
||||
this.setState({ activeTab: tab })
|
||||
}
|
||||
|
||||
onClickClose = () => {
|
||||
this.props.onClose(MODAL_LIST_EDITOR)
|
||||
}
|
||||
|
||||
handleOnDeleteList = () => {
|
||||
this.props.onDeleteList(this.props.list)
|
||||
}
|
||||
|
||||
handleAddOrRemoveFromList = (accountId) => {
|
||||
if (this.props.accountIds.includes(accountId)) {
|
||||
this.props.onRemoveAccountFromList(accountId)
|
||||
} else {
|
||||
this.props.onAddAccountToList(accountId)
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchSuggestionsChange = (value) => {
|
||||
this.props.onChangeSuggestions(value)
|
||||
}
|
||||
|
||||
handleSearchSuggestionsKeyUp = (e) => {
|
||||
if (e.keyCode === 13) {
|
||||
this.props.onSubmitSearchSuggestions(this.props.searchSuggestionsValue)
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchSuggestionsSubmit = () => {
|
||||
this.props.onSubmitSearchSuggestions(this.props.searchSuggestionsValue)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
title,
|
||||
accountIds,
|
||||
searchAccountIds,
|
||||
intl,
|
||||
searchSuggestionsValue,
|
||||
} = this.props
|
||||
const { activeTab } = this.state
|
||||
|
||||
// : todo : save new list title
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary].join(' ')}>
|
||||
<div className={[_s.default, _s.z4, _s.bgPrimary, _s.px15, _s.top0, _s.posSticky, _s.borderBottom1PX, _s.borderColorSecondary,].join(' ')}>
|
||||
<TabBar
|
||||
tabs={[
|
||||
{
|
||||
title: 'Members list',
|
||||
onClick: () => this.handleChangeTab('members'),
|
||||
active: activeTab === 'members',
|
||||
},
|
||||
{
|
||||
title: 'Add new',
|
||||
onClick: () => this.handleChangeTab('add-new'),
|
||||
active: activeTab === 'add-new',
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
onClick: () => this.handleChangeTab('settings'),
|
||||
active: activeTab === 'settings',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
activeTab === 'members' &&
|
||||
<div className={[_s.default, _s.mb10, _s.py10].join(' ')}>
|
||||
<div className={[_s.default, _s.pb10, _s.pt5].join(' ')}>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<Text weight='bold' size='small' color='secondary' className={[_s.default, _s.px15, _s.mt5, _s.mb15].join(' ')}>
|
||||
Total members ({accountIds.size})
|
||||
</Text>
|
||||
{
|
||||
accountIds &&
|
||||
accountIds.map((accountId) => (
|
||||
<Account
|
||||
compact
|
||||
key={`remove-from-list-${accountId}`}
|
||||
id={accountId}
|
||||
onActionClick={() => this.handleAddOrRemoveFromList(accountId)}
|
||||
actionIcon={'subtract'}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
activeTab === 'settings' &&
|
||||
<div className={[_s.default, _s.mb10, _s.pb10, _s.px15].join(' ')}>
|
||||
<div className={[_s.default, _s.py15].join(' ')}>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.editListTitle)}
|
||||
placeholder='My new list title...'
|
||||
value={title}
|
||||
// onChange={onChange}
|
||||
// onSubmit={onSubmit}
|
||||
// disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
<Divider />
|
||||
<div className={_s.mb10}>
|
||||
<Button
|
||||
onClick={this.handleOnDeleteList}
|
||||
backgroundColor='danger'
|
||||
>
|
||||
Delete List
|
||||
</Button>
|
||||
</div>
|
||||
<Text size='extraSmall' color='secondary'>
|
||||
Once you delete a list you cannot retrieve it.
|
||||
</Text>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
activeTab === 'add-new' &&
|
||||
<div className={[_s.default, _s.mb10, _s.py10].join(' ')}>
|
||||
<div className={[_s.default, _s.px15].join(' ')}>
|
||||
<Input
|
||||
placeholder={intl.formatMessage(messages.search)}
|
||||
value={searchSuggestionsValue}
|
||||
onChange={this.handleSearchSuggestionsChange}
|
||||
onKeyUp={this.handleSearchSuggestionsKeyUp}
|
||||
handleSubmit={this.handleSearchSuggestionsSubmit}
|
||||
title={intl.formatMessage(messages.searchTitle)}
|
||||
prependIcon='search'
|
||||
hideLabel
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.pt10].join(' ')}>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<Text weight='bold' size='small' color='secondary' className={[_s.default, _s.px15, _s.mt5, _s.mb15].join(' ')}>
|
||||
Search results ({searchAccountIds.size})
|
||||
</Text>
|
||||
{
|
||||
searchAccountIds &&
|
||||
searchAccountIds.map((accountId) => {
|
||||
if (accountIds.includes(accountId)) return null
|
||||
return (
|
||||
<Account
|
||||
key={`add-to-list-${accountId}`}
|
||||
id={accountId}
|
||||
compact
|
||||
onActionClick={() => this.handleAddOrRemoveFromList(accountId)}
|
||||
actionIcon='add'
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { removeFromListEditor, addToListEditor } from '../../../actions/lists';
|
||||
import { makeGetAccount } from '../../../selectors';
|
||||
import Avatar from '../../../components/avatar';
|
||||
import DisplayName from '../../../components/display_name';
|
||||
import Button from '../../../components/button';
|
||||
|
||||
const messages = defineMessages({
|
||||
remove: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
||||
add: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, { accountId, added }) => ({
|
||||
account: getAccount(state, accountId),
|
||||
added: typeof added === 'undefined' ? state.getIn(['listEditor', 'accounts', 'items']).includes(accountId) : added,
|
||||
});
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch, { accountId }) => ({
|
||||
onRemove: () => dispatch(removeFromListEditor(accountId)),
|
||||
onAdd: () => dispatch(addToListEditor(accountId)),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(makeMapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onRemove: PropTypes.func.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
added: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
added: false,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { account, intl, onRemove, onAdd, added } = this.props;
|
||||
|
||||
let button;
|
||||
|
||||
if (added) {
|
||||
button = <Button icon='times' title={intl.formatMessage(messages.remove)} onClick={onRemove} />;
|
||||
} else {
|
||||
button = <Button icon='plus' title={intl.formatMessage(messages.add)} onClick={onAdd} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account'>
|
||||
<div className='account__wrapper'>
|
||||
<div className='account__display-name'>
|
||||
<div className='account__avatar-wrapper'>
|
||||
<Avatar account={account} size={36} />
|
||||
</div>
|
||||
<DisplayName account={account} />
|
||||
</div>
|
||||
|
||||
<div className='account__relationship'>
|
||||
{button}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { changeListEditorTitle, submitListEditor } from '../../../../actions/lists';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'lists.edit.submit', defaultMessage: 'Change title' },
|
||||
save: { id: 'lists.new.save_title', defaultMessage: 'Save Title' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
value: state.getIn(['listEditor', 'title']),
|
||||
disabled: !state.getIn(['listEditor', 'isChanged']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onChange: value => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => dispatch(submitListEditor(false)),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListForm extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { value, disabled, intl, onSubmit, onChange } = this.props;
|
||||
|
||||
return null;
|
||||
|
||||
// return (
|
||||
// <ColumnInlineForm
|
||||
// value={value}
|
||||
// onChange={onChange}
|
||||
// onSubmit={onSubmit}
|
||||
// label={intl.formatMessage(messages.title)}
|
||||
// btnTitle={intl.formatMessage(messages.save)}
|
||||
// disabled={disabled}
|
||||
// />
|
||||
// );
|
||||
}
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { default } from './edit_list_form'
|
@ -1 +0,0 @@
|
||||
export { default } from './list_editor_search'
|
@ -1,68 +0,0 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../../actions/lists';
|
||||
import Search from '../../../../components/search';
|
||||
|
||||
const messages = defineMessages({
|
||||
search: { id: 'lists.search', defaultMessage: 'Search among people you follow' },
|
||||
searchTitle: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
value: state.getIn(['listEditor', 'suggestions', 'value']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSubmit: (value) => dispatch(fetchListSuggestions(value)),
|
||||
onClear: () => dispatch(clearListSuggestions()),
|
||||
onChange: (value) => dispatch(changeListSuggestions(value)),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListEditorSearch extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
onClear: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
handleChange = (value) => {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
|
||||
handleKeyUp = e => {
|
||||
if (e.keyCode === 13) {
|
||||
this.props.onSubmit(this.props.value);
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
this.props.onSubmit(this.props.value);
|
||||
}
|
||||
|
||||
handleClear = () => {
|
||||
this.props.onClear();
|
||||
}
|
||||
|
||||
render () {
|
||||
const { value, intl } = this.props;
|
||||
|
||||
return (
|
||||
<Search
|
||||
className='list-editor-search'
|
||||
placeholder={intl.formatMessage(messages.search)}
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
handleSubmit={this.handleSubmit}
|
||||
handleClear={this.handleClear}
|
||||
searchTitle={intl.formatMessage(messages.searchTitle)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { default } from './list_edit'
|
@ -1,127 +0,0 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import isObject from 'lodash.isobject'
|
||||
import { setupListEditor, resetListEditor } from '../../actions/lists'
|
||||
import Account from './components/account'
|
||||
import ListEditorSearch from './components/list_editor_search'
|
||||
import EditListForm from './components/edit_list_form/edit_list_form'
|
||||
import Button from '../../components/button'
|
||||
import Form from '../../components/form'
|
||||
import Input from '../../components/input'
|
||||
|
||||
const mapStateToProps = (state, { params }) => {
|
||||
|
||||
console.log("params:", params)
|
||||
|
||||
const listId = isObject(params) ? params['id'] : null
|
||||
|
||||
return {
|
||||
listId,
|
||||
title: state.getIn(['listEditor', 'title']),
|
||||
accountIds: state.getIn(['listEditor', 'accounts', 'items']),
|
||||
searchAccountIds: state.getIn(['listEditor', 'suggestions', 'items']),
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onInitialize: (listId) => dispatch(setupListEditor(listId)),
|
||||
onReset: () => dispatch(resetListEditor()),
|
||||
})
|
||||
|
||||
const messages = defineMessages({
|
||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||
changeTitle: { id: 'lists.edit.submit', defaultMessage: 'Change title' },
|
||||
addToList: { id: 'lists.account.add', defaultMessage: 'Add to list' },
|
||||
removeFromList: { id: 'lists.account.remove', defaultMessage: 'Remove from list' },
|
||||
editList: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
||||
editListTitle: { id: 'lists.new.edit_title_placeholder', defaultMessage: 'Edit list title' },
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListEdit extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
title: PropTypes.string,
|
||||
listId: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onInitialize: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list.isRequired,
|
||||
searchAccountIds: ImmutablePropTypes.list.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { onInitialize, listId } = this.props
|
||||
console.log("listId:", listId)
|
||||
if (listId) {
|
||||
onInitialize(listId)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.onReset()
|
||||
}
|
||||
|
||||
onClickClose = () => {
|
||||
this.props.onClose('LIST_ADDER')
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
title,
|
||||
accountIds,
|
||||
searchAccountIds,
|
||||
intl
|
||||
} = this.props
|
||||
|
||||
console.log("title:", title)
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.editListTitle)}
|
||||
placeholder='My new list title...'
|
||||
value={title}
|
||||
// onChange={onChange}
|
||||
// onSubmit={onSubmit}
|
||||
// disabled={disabled}
|
||||
/>
|
||||
|
||||
<div className='compose-modal__header'>
|
||||
<h3 className='compose-modal__header__title'>
|
||||
{intl.formatMessage(messages.editList)}
|
||||
</h3>
|
||||
<Button className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
|
||||
</div>
|
||||
<div className='compose-modal__content'>
|
||||
<div className='list-editor'>
|
||||
<EditListForm />
|
||||
<br />
|
||||
|
||||
{
|
||||
accountIds.size > 0 &&
|
||||
<div>
|
||||
<div className='list-editor__accounts'>
|
||||
{accountIds.map(accountId => <Account key={accountId} accountId={accountId} added />)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<br />
|
||||
<ListEditorSearch />
|
||||
<div className='list-editor__accounts'>
|
||||
{searchAccountIds.map(accountId => <Account key={accountId} accountId={accountId} />)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Form>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -71,7 +71,8 @@ class ListTimeline extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
handleEditClick = () => {
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id }))
|
||||
console.log("handleEditClick:", this.props.params.id)
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { id: this.props.params.id }))
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -86,12 +87,13 @@ class ListTimeline extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
const emptyMessage = (
|
||||
<div className={[_s.default, _s.py15, _s.px15].join(' ')}>
|
||||
<div className={[_s.default, _s.py15, _s.px15, _s.alignItemsCenter].join(' ')}>
|
||||
<FormattedMessage
|
||||
id='empty_column.list'
|
||||
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.'
|
||||
/>
|
||||
|
||||
<div className={_s.mt10}>
|
||||
<Button
|
||||
onClick={this.handleEditClick}
|
||||
className={[_s.mt10]}
|
||||
@ -101,6 +103,7 @@ class ListTimeline extends ImmutablePureComponent {
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,50 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { fetchStatus } from '../actions/statuses'
|
||||
import StatusContainer from '../containers/status_container'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const statusId = props.id || props.params.statusId
|
||||
|
||||
return {
|
||||
status: state.getIn(['statuses', statusId]),
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchStatus: (id) => dispatch(fetchStatus(id)),
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class Status extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
onFetchStatus: PropTypes.func.isRequired,
|
||||
params: PropTypes.object,
|
||||
status: ImmutablePropTypes.map,
|
||||
}
|
||||
|
||||
updateOnProps = [
|
||||
'params',
|
||||
'status',
|
||||
]
|
||||
|
||||
componentDidMount() {
|
||||
const statusId = this.props.id || this.props.params.statusId
|
||||
this.props.onFetchStatus(statusId)
|
||||
}
|
||||
|
||||
export default class Status extends PureComponent {
|
||||
render() {
|
||||
const { status } = this.props
|
||||
|
||||
// - if comment render as such
|
||||
|
||||
if (!status) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
}
|
||||
|
||||
return (
|
||||
<StatusContainer {...this.props} />
|
||||
)
|
||||
|
@ -1,72 +1,70 @@
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { fetchLikes } from '../actions/interactions'
|
||||
import { fetchStatus } from '../actions/statuses'
|
||||
import { makeGetStatus } from '../selectors'
|
||||
import Account from '../components/account'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import ScrollableList from '../components/scrollable_list'
|
||||
|
||||
const messages = defineMessages({
|
||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||
});
|
||||
const mapStateToProps = (state, props) => {
|
||||
const getStatus = makeGetStatus()
|
||||
const status = getStatus(state, {
|
||||
id: props.params.statusId,
|
||||
username: props.params.username,
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
|
||||
});
|
||||
return {
|
||||
status,
|
||||
accountIds: state.getIn(['user_lists', 'liked_by', props.params.statusId]),
|
||||
}
|
||||
}
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps)
|
||||
class StatusLikes extends ImmutablePureComponent {
|
||||
class StatusReposts extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
multiColumn: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
status: ImmutablePropTypes.map,
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId));
|
||||
}
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId))
|
||||
this.props.dispatch(fetchStatus(this.props.params.statusId))
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchLikes(nextProps.params.statusId));
|
||||
this.props.dispatch(fetchLikes(nextProps.params.statusId))
|
||||
this.props.dispatch(fetchStatus(nextProps.params.statusId))
|
||||
}
|
||||
}
|
||||
|
||||
handleRefresh = () => {
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId));
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, shouldUpdateScroll, accountIds, multiColumn } = this.props;
|
||||
const { accountIds, status } = this.props
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (!status) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.favourites' defaultMessage='No one has favourited this toot yet. When someone does, they will show up here.' />;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ScrollableList
|
||||
scrollKey='favourites'
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
scrollKey='likes'
|
||||
emptyMessage={<FormattedMessage id='status.likes.empty' defaultMessage='No one has liked this gab yet. When someone does, they will show up here.' />}
|
||||
>
|
||||
{accountIds.map(id =>
|
||||
<Account key={id} id={id} withNote={false} />,
|
||||
)}
|
||||
{
|
||||
accountIds.map(id =>
|
||||
<Account key={id} id={id} />
|
||||
)
|
||||
}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -145,7 +145,7 @@ class SwitchingArea extends PureComponent {
|
||||
<Redirect from='/' to='/home' exact />
|
||||
<WrappedRoute path='/home' exact page={HomePage} component={HomeTimeline} content={children} />
|
||||
|
||||
<WrappedRoute path='/timeline/all' exact page={CommunityPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Community Timeline' }} />
|
||||
<WrappedRoute path='/timeline/all' exact page={CommunityPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Community Feed' }} />
|
||||
|
||||
<WrappedRoute path='/groups' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'featured' }} />
|
||||
<WrappedRoute path='/groups/new' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'new' }} />
|
||||
|
@ -65,6 +65,8 @@ export function SidebarMorePopover() { return import(/* webpackChunkName: "compo
|
||||
export function StatusLikes() { return import(/* webpackChunkName: "features/status_likes" */'../../status_likes') }
|
||||
export function StatusOptionsPopover() { return import(/* webpackChunkName: "components/status_options_popover" */'../../../components/popover/status_options_popover') }
|
||||
export function StatusReposts() { return import(/* webpackChunkName: "features/status_reposts" */'../../status_reposts') }
|
||||
export function StatusLikesModal() { return import(/* webpackChunkName: "modals/status_likes_modal" */'../../../components/modal/status_likes_modal') }
|
||||
export function StatusRepostsModal() { return import(/* webpackChunkName: "modals/status_reposts_modal" */'../../../components/modal/status_reposts_modal') }
|
||||
export function StatusRevisionsModal() { return import(/* webpackChunkName: "modals/status_revisions_modal" */'../../../components/modal/status_revisions_modal') }
|
||||
export function StatusSharePopover() { return import(/* webpackChunkName: "components/status_share_popover" */'../../../components/popover/status_share_popover') }
|
||||
export function StatusVisibilityPopover() { return import(/* webpackChunkName: "components/status_visibility_popover" */'../../../components/popover/status_visibility_popover') }
|
||||
|
@ -1,32 +1,33 @@
|
||||
import Layout from './layout'
|
||||
|
||||
export default class DefaultLayout extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
actions: PropTypes.array,
|
||||
tabs: PropTypes.array,
|
||||
children: PropTypes.node.isRequired,
|
||||
layout: PropTypes.object,
|
||||
showBackBtn: PropTypes.bool,
|
||||
tabs: PropTypes.array,
|
||||
title: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
title,
|
||||
showBackBtn,
|
||||
layout,
|
||||
actions,
|
||||
children,
|
||||
layout,
|
||||
showBackBtn,
|
||||
tabs,
|
||||
title,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title={title}
|
||||
showBackBtn={showBackBtn}
|
||||
actions={actions}
|
||||
tabs={tabs}
|
||||
layout={layout}
|
||||
showBackBtn={showBackBtn}
|
||||
tabs={tabs}
|
||||
title={title}
|
||||
>
|
||||
{children}
|
||||
</Layout>
|
||||
|
@ -5,32 +5,34 @@ import Layout from './layout'
|
||||
import GroupHeader from '../components/group_header'
|
||||
|
||||
export default class GroupLayout extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
actions: PropTypes.array,
|
||||
children: PropTypes.node,
|
||||
group: ImmutablePropTypes.map,
|
||||
relationships: ImmutablePropTypes.map,
|
||||
layout: PropTypes.object,
|
||||
relationships: ImmutablePropTypes.map,
|
||||
showBackBtn: PropTypes.bool,
|
||||
title: PropTypes.string,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
group,
|
||||
children,
|
||||
layout,
|
||||
showBackBtn,
|
||||
actions,
|
||||
children,
|
||||
group,
|
||||
layout,
|
||||
relationships,
|
||||
showBackBtn,
|
||||
title,
|
||||
} = this.props
|
||||
|
||||
const title = !!group ? group.get('title') : undefined
|
||||
|
||||
return (
|
||||
<Layout
|
||||
noRightSidebar
|
||||
title={title}
|
||||
actions={actions}
|
||||
showBackBtn={showBackBtn}
|
||||
title={title}
|
||||
>
|
||||
<div className={[_s.default, _s.width100PC, _s.pl15].join(' ')}>
|
||||
|
||||
|
@ -1,52 +1,58 @@
|
||||
import Sticky from 'react-stickynode'
|
||||
import Search from '../components/search'
|
||||
import ColumnHeader from '../components/column_header'
|
||||
import Sidebar from '../components/sidebar'
|
||||
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
|
||||
import NavigationBar from '../components/navigation_bar'
|
||||
// : todo :
|
||||
// import Footer from '../components/footer'
|
||||
import FloatingActionButton from '../components/floating_action_button'
|
||||
import Responsive from '../features/ui/util/responsive_component'
|
||||
|
||||
export default class Layout extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
actions: PropTypes.array,
|
||||
tabs: PropTypes.array,
|
||||
children: PropTypes.node,
|
||||
layout: PropTypes.object,
|
||||
title: PropTypes.string,
|
||||
showBackBtn: PropTypes.bool,
|
||||
noSidebar: PropTypes.bool,
|
||||
noRightSidebar: PropTypes.bool,
|
||||
noComposeButton: PropTypes.bool,
|
||||
noRightSidebar: PropTypes.bool,
|
||||
noSidebar: PropTypes.bool,
|
||||
showBackBtn: PropTypes.bool,
|
||||
tabs: PropTypes.array,
|
||||
title: PropTypes.string,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
title,
|
||||
showBackBtn,
|
||||
layout,
|
||||
actions,
|
||||
tabs,
|
||||
noSidebar,
|
||||
noRightSidebar,
|
||||
children,
|
||||
layout,
|
||||
noComposeButton,
|
||||
noRightSidebar,
|
||||
noSidebar,
|
||||
showBackBtn,
|
||||
tabs,
|
||||
title,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.width100PC, _s.heightMin100VH, _s.bgTertiary].join(' ')}>
|
||||
|
||||
<NavigationBar
|
||||
title={title}
|
||||
tabs={tabs}
|
||||
actions={actions}
|
||||
tabs={tabs}
|
||||
title={title}
|
||||
/>
|
||||
|
||||
<div className={[_s.default, _s.flexRow, _s.width100PC].join(' ')}>
|
||||
{
|
||||
!noSidebar &&
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<Sidebar title={title} tabs={tabs} actions={actions} />
|
||||
<Sidebar
|
||||
actions={actions}
|
||||
showBackBtn={showBackBtn}
|
||||
tabs={tabs}
|
||||
title={title}
|
||||
/>
|
||||
</Responsive>
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,16 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import Sticky from 'react-stickynode'
|
||||
import ProfileHeader from '../components/profile_header'
|
||||
import NavigationBar from '../components/navigation_bar'
|
||||
import ProfileHeader from '../components/profile_header'
|
||||
|
||||
export default class ProfileLayout extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
children: PropTypes.node.isRequired,
|
||||
layout: PropTypes.object,
|
||||
title: PropTypes.string,
|
||||
showBackBtn: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -20,7 +19,6 @@ export default class ProfileLayout extends ImmutablePureComponent {
|
||||
children,
|
||||
layout,
|
||||
title,
|
||||
showBackBtn,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
|
@ -45,7 +45,7 @@
|
||||
"bundle_modal_error.message": "Something went wrong while loading this component.",
|
||||
"bundle_modal_error.retry": "Try again",
|
||||
"column.blocks": "Blocked users",
|
||||
"column.community": "Community timeline",
|
||||
"column.community": "Community feed",
|
||||
"column.direct": "Direct messages",
|
||||
"column.domain_blocks": "Blocked domains",
|
||||
"column.favorites": "Favorites",
|
||||
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Зареждане...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -228,7 +228,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new toot",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -1688,7 +1688,7 @@
|
||||
{
|
||||
"descriptors": [
|
||||
{
|
||||
"defaultMessage": "Search among people you follow",
|
||||
"defaultMessage": "Search people...",
|
||||
"id": "lists.search"
|
||||
}
|
||||
],
|
||||
|
@ -45,7 +45,7 @@
|
||||
"bundle_modal_error.message": "Something went wrong while loading this component.",
|
||||
"bundle_modal_error.retry": "Try again",
|
||||
"column.blocks": "Blocked users",
|
||||
"column.community": "Community timeline",
|
||||
"column.community": "Community feed",
|
||||
"column.direct": "Direct messages",
|
||||
"column.domain_blocks": "Blocked domains",
|
||||
"column.favorites": "Favorites",
|
||||
@ -221,7 +221,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -230,7 +230,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new gab",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "טוען...",
|
||||
"media_gallery.toggle_visible": "נראה\\בלתי נראה",
|
||||
|
@ -45,7 +45,7 @@
|
||||
"bundle_modal_error.message": "Something went wrong while loading this component.",
|
||||
"bundle_modal_error.retry": "Try again",
|
||||
"column.blocks": "Blocked users",
|
||||
"column.community": "Community timeline",
|
||||
"column.community": "Community feed",
|
||||
"column.direct": "Direct messages",
|
||||
"column.domain_blocks": "Blocked domains",
|
||||
"column.favorites": "Favorites",
|
||||
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -228,7 +228,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new toot",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Učitavam...",
|
||||
"media_gallery.toggle_visible": "Preklopi vidljivost",
|
||||
|
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Tunggu sebentar...",
|
||||
"media_gallery.toggle_visible": "Tampil/Sembunyikan",
|
||||
|
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Kargante...",
|
||||
"media_gallery.toggle_visible": "Chanjar videbleso",
|
||||
|
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -228,7 +228,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new toot",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -45,7 +45,7 @@
|
||||
"bundle_modal_error.message": "Something went wrong while loading this component.",
|
||||
"bundle_modal_error.retry": "Try again",
|
||||
"column.blocks": "Blocked users",
|
||||
"column.community": "Community timeline",
|
||||
"column.community": "Community feed",
|
||||
"column.direct": "Direct messages",
|
||||
"column.domain_blocks": "Blocked domains",
|
||||
"column.favorites": "Favorites",
|
||||
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -228,7 +228,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new toot",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -228,7 +228,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new toot",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -45,7 +45,7 @@
|
||||
"bundle_modal_error.message": "Something went wrong while loading this component.",
|
||||
"bundle_modal_error.retry": "Try again",
|
||||
"column.blocks": "Blocked users",
|
||||
"column.community": "Community timeline",
|
||||
"column.community": "Community feed",
|
||||
"column.direct": "Direct messages",
|
||||
"column.domain_blocks": "Blocked domains",
|
||||
"column.favorites": "Favorites",
|
||||
@ -219,7 +219,7 @@
|
||||
"lists.edit.submit": "Change title",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.search": "Search people...",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Hide media",
|
||||
@ -228,7 +228,7 @@
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"navigation_bar.apps": "Mobile apps",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Community timeline",
|
||||
"navigation_bar.community_timeline": "Community feed",
|
||||
"navigation_bar.compose": "Compose new toot",
|
||||
"navigation_bar.direct": "Direct messages",
|
||||
"navigation_bar.discover": "Discover",
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { Fragment } from 'react'
|
||||
import PageTitle from '../features/ui/util/page_title'
|
||||
import LinkFooter from '../components/link_footer'
|
||||
import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
||||
import TrendsPanel from '../components/panel/trends_panel'
|
||||
import DefaultLayout from '../layouts/default_layout'
|
||||
import LinkFooter from '../components/link_footer'
|
||||
import TrendsPanel from '../components/panel/trends_panel'
|
||||
import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
||||
|
||||
export default class BasicPage extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
@ -31,4 +32,5 @@ export default class BasicPage extends PureComponent {
|
||||
</DefaultLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,7 @@ import TimelineComposeBlock from '../components/timeline_compose_block'
|
||||
import Divider from '../components/divider'
|
||||
|
||||
const messages = defineMessages({
|
||||
community: { 'id': 'column.community', 'defaultMessage': 'Community timeline' },
|
||||
community: { 'id': 'column.community', 'defaultMessage': 'Community feed' },
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
@ -50,36 +50,12 @@ class GroupPage extends ImmutablePureComponent {
|
||||
relationships,
|
||||
} = this.props
|
||||
|
||||
// <div className="column-header__wrapper">
|
||||
// <h1 className="column-header">
|
||||
// <Link to={`/groups/${id}`} className={classNames('btn grouped active')}>
|
||||
// {intl.formatMessage(messages.tabLatest)}
|
||||
// </Link>
|
||||
|
||||
// <div className='column-header__buttons'>
|
||||
// <button
|
||||
// className={classNames('column-header__button', { 'active': !collapsed })}
|
||||
// title={intl.formatMessage(collapsed ? messages.show : messages.hide)}
|
||||
// aria-label={intl.formatMessage(collapsed ? messages.show : messages.hide)}
|
||||
// aria-pressed={collapsed ? 'false' : 'true'}
|
||||
// onClick={this.handleToggleClick}
|
||||
// ><Icon id='sliders' /></button>
|
||||
// </div>
|
||||
// </h1>
|
||||
// {!collapsed && <div className='column-header__collapsible'>
|
||||
// <div className='column-header__collapsible-inner'>
|
||||
// <div className='column-header__collapsible__extra'>
|
||||
// <ColumnSettingsContainer />
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>}
|
||||
// </div>
|
||||
|
||||
const groupTitle = !!group ? group.get('title') : ''
|
||||
|
||||
return (
|
||||
<GroupLayout
|
||||
showBackBtn
|
||||
title={intl.formatMessage(messages.group)}
|
||||
group={group}
|
||||
relationships={relationships}
|
||||
actions={[
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Fragment } from 'react'
|
||||
import { openModal } from '../actions/modal'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { MODAL_HOME_TIMELINE_SETTINGS } from '../constants'
|
||||
import IntersectionObserverArticle from '../components/intersection_observer_article'
|
||||
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
|
||||
import PageTitle from '../features/ui/util/page_title'
|
||||
@ -25,7 +26,7 @@ const mapStateToProps = (state) => ({
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenHomePageSettingsModal() {
|
||||
dispatch(openModal('HOME_TIMELINE_SETTINGS'))
|
||||
dispatch(openModal(MODAL_HOME_TIMELINE_SETTINGS))
|
||||
},
|
||||
})
|
||||
|
||||
@ -35,10 +36,10 @@ export default
|
||||
class HomePage extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
totalQueuedItemsCount: PropTypes.number.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onOpenHomePageSettingsModal: PropTypes.func.isRequired,
|
||||
totalQueuedItemsCount: PropTypes.number.isRequired,
|
||||
}
|
||||
|
||||
intersectionObserverWrapper = new IntersectionObserverWrapper()
|
||||
@ -59,7 +60,6 @@ class HomePage extends PureComponent {
|
||||
this.intersectionObserverWrapper.disconnect()
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
@ -110,13 +110,18 @@ class HomePage extends PureComponent {
|
||||
</Fragment>
|
||||
)}
|
||||
>
|
||||
|
||||
<PageTitle
|
||||
path={intl.formatMessage(messages.home)}
|
||||
badge={totalQueuedItemsCount}
|
||||
/>
|
||||
|
||||
<TimelineComposeBlock autoFocus={false} />
|
||||
|
||||
<Divider />
|
||||
|
||||
{children}
|
||||
|
||||
</DefaultLayout>
|
||||
)
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenListEditModal(list) {
|
||||
if (!list) return
|
||||
const listId = list.get('id')
|
||||
dispatch(openModal(MODAL_LIST_EDITOR, { listId }))
|
||||
dispatch(openModal(MODAL_LIST_EDITOR, { id: listId }))
|
||||
},
|
||||
// : todo :
|
||||
// onOpenListTimelineSettingsModal() {
|
||||
@ -65,7 +65,7 @@ class ListPage extends ImmutablePureComponent {
|
||||
return (
|
||||
<DefaultLayout
|
||||
showBackBtn
|
||||
title={title}
|
||||
title={intl.formatMessage(messages.list)}
|
||||
actions={[
|
||||
{
|
||||
icon: 'cog',
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
import { EMOJI_USE } from '../actions/emojis';
|
||||
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
import uuid from '../utils/uuid';
|
||||
import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings'
|
||||
import { STORE_HYDRATE } from '../actions/store'
|
||||
import { EMOJI_USE } from '../actions/emojis'
|
||||
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists'
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable'
|
||||
import uuid from '../utils/uuid'
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
saved: true,
|
||||
onboarded: false,
|
||||
skinTone: 1,
|
||||
|
||||
// displayOptions: ImmutableMap({
|
||||
// fontSize: 'normal',
|
||||
// radiusSmallEnabled: true,
|
||||
// radiusCircleEnabled: true,
|
||||
// theme: 'light',
|
||||
// }),
|
||||
displayOptions: ImmutableMap({
|
||||
fontSize: 'normal',
|
||||
radiusSmallDisabled: false,
|
||||
radiusCircleDisabled: false,
|
||||
theme: 'light',
|
||||
}),
|
||||
|
||||
home: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
@ -27,26 +27,6 @@ const initialState = ImmutableMap({
|
||||
}),
|
||||
}),
|
||||
|
||||
lists: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
photos: true,
|
||||
polls: true,
|
||||
reply: true,
|
||||
repost: true,
|
||||
videos: true,
|
||||
}),
|
||||
}),
|
||||
|
||||
groups: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
photos: true,
|
||||
polls: true,
|
||||
reply: true,
|
||||
repost: true,
|
||||
videos: true,
|
||||
}),
|
||||
}),
|
||||
|
||||
community: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
inSidebar: false,
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
} from '../actions/accounts'
|
||||
import {
|
||||
REPOSTS_FETCH_SUCCESS,
|
||||
LIKES_FETCH_SUCCESS,
|
||||
} from '../actions/interactions'
|
||||
import {
|
||||
BLOCKS_FETCH_REQUEST,
|
||||
@ -52,7 +53,7 @@ const initialState = ImmutableMap({
|
||||
followers: ImmutableMap(),
|
||||
following: ImmutableMap(),
|
||||
reblogged_by: ImmutableMap(),
|
||||
favorited_by: ImmutableMap(),
|
||||
liked_by: ImmutableMap(),
|
||||
follow_requests: ImmutableMap(),
|
||||
blocks: ImmutableMap(),
|
||||
mutes: ImmutableMap(),
|
||||
@ -103,6 +104,8 @@ export default function userLists(state = initialState, action) {
|
||||
return state.setIn(['following', action.id, 'isLoading'], false);
|
||||
case REPOSTS_FETCH_SUCCESS:
|
||||
return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
||||
case LIKES_FETCH_SUCCESS:
|
||||
return state.setIn(['liked_by', action.id], ImmutableList(action.accounts.map(item => item.id)));
|
||||
case FOLLOW_REQUESTS_FETCH_SUCCESS:
|
||||
return state.setIn(['follow_requests', 'items'], ImmutableList(action.accounts.map(item => item.id))).setIn(['follow_requests', 'next'], action.next).setIn(['follow_requests', 'isLoading'], false);
|
||||
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
|
||||
|
@ -12,6 +12,9 @@
|
||||
--color_red: #de2960;
|
||||
--color_red-dark: #c72c5b;
|
||||
|
||||
--radius-small: 8px;
|
||||
--radius-circle: 9999px;
|
||||
|
||||
--fs_xs: 0.8571428571rem;
|
||||
--fs_s: 0.9285714286rem;
|
||||
--fs_n: 1rem;
|
||||
@ -19,19 +22,8 @@
|
||||
--fs_l: 1.1428571429rem;
|
||||
--fs_xl: 1.3571428571rem;
|
||||
--fs_xxl: 1.7142857143rem;
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius-small: 0;
|
||||
--radius-circle: 0;
|
||||
}
|
||||
|
||||
:root[rounded] {
|
||||
--radius-small: 8px;
|
||||
--radius-circle: 9999px;
|
||||
}
|
||||
|
||||
:root[theme='light'] {
|
||||
/* Default light theme */
|
||||
--solid_color_primary: #fff;
|
||||
--solid_color_primary-opaque:rgba(255, 255, 255,.6);
|
||||
--solid_color_secondary: #e2e8ec;
|
||||
@ -46,34 +38,42 @@
|
||||
--border_color_secondary: #ececed;
|
||||
}
|
||||
|
||||
:root[no-circle] {
|
||||
--radius-circle: 0 !important;
|
||||
}
|
||||
|
||||
:root[no-radius] {
|
||||
--radius-small: 0 !important;
|
||||
}
|
||||
|
||||
:root[theme='muted'] {
|
||||
--solid_color_primary: #222;
|
||||
--solid_color_primary-opaque:rgba(34, 34, 34, .6);
|
||||
--solid_color_secondary: #4f5050;
|
||||
--solid_color_secondary-dark: #424343;
|
||||
--solid_color_tertiary: #333;
|
||||
--solid_color_block: #2d2d2d;
|
||||
--solid_color_primary: #222 !important;
|
||||
--solid_color_primary-opaque:rgba(34, 34, 34, .6) !important;
|
||||
--solid_color_secondary: #4f5050 !important;
|
||||
--solid_color_secondary-dark: #424343 !important;
|
||||
--solid_color_tertiary: #333 !important;
|
||||
--solid_color_block: #2d2d2d !important;
|
||||
|
||||
--text_color_primary: #fff;
|
||||
--text_color_secondary: #7b7b7b;
|
||||
--text_color_tertiary: #656565;
|
||||
--text_color_primary: #fff !important;
|
||||
--text_color_secondary: #7b7b7b !important;
|
||||
--text_color_tertiary: #656565 !important;
|
||||
|
||||
--border_color_secondary: #424141;
|
||||
--border_color_secondary: #424141 !important;
|
||||
}
|
||||
|
||||
:root[theme='black'] {
|
||||
--solid_color_primary: #13171b;
|
||||
--solid_color_primary-opaque:rgba(19, 23, 27, .6);
|
||||
--solid_color_secondary: #4f5050;
|
||||
--solid_color_secondary-dark: #424343;
|
||||
--solid_color_tertiary: #000;
|
||||
--solid_color_block: #202327;
|
||||
--solid_color_primary: #13171b !important;
|
||||
--solid_color_primary-opaque:rgba(19, 23, 27, .6) !important;
|
||||
--solid_color_secondary: #4f5050 !important;
|
||||
--solid_color_secondary-dark: #424343 !important;
|
||||
--solid_color_tertiary: #000 !important;
|
||||
--solid_color_block: #202327 !important;
|
||||
|
||||
--text_color_primary: #cccbcb;
|
||||
--text_color_secondary: #61686E;
|
||||
--text_color_tertiary: #656565;
|
||||
--text_color_primary: #cccbcb !important;
|
||||
--text_color_secondary: #61686E !important;
|
||||
--text_color_tertiary: #656565 !important;
|
||||
|
||||
--border_color_secondary: #212020;
|
||||
--border_color_secondary: #212020 !important;
|
||||
}
|
||||
|
||||
html,
|
||||
@ -199,7 +199,6 @@ body {
|
||||
|
||||
.inherit {
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
white-space: inherit;
|
||||
}
|
||||
|
||||
@ -246,6 +245,9 @@ body {
|
||||
.whiteSpaceNoWrap { white-space: nowrap; }
|
||||
|
||||
.outlineNone { outline: none; }
|
||||
.outlineOnFocus:focus {
|
||||
box-shadow: 0 0 0 5px rgba(21, 156, 228, 0.4);
|
||||
}
|
||||
|
||||
.resizeNone { resize: none; }
|
||||
|
||||
@ -264,6 +266,7 @@ body {
|
||||
|
||||
.borderRight1PX { border-right-width: 1px; }
|
||||
.borderBottom1PX { border-bottom-width: 1px; }
|
||||
.borderBottom6PX { border-bottom-width: 6px; }
|
||||
.borderLeft1PX { border-left-width: 1px; }
|
||||
.borderTop1PX { border-top-width: 1px; }
|
||||
|
||||
@ -393,6 +396,7 @@ body {
|
||||
|
||||
/* */
|
||||
|
||||
.posSticky { position: sticky; }
|
||||
.posFixed { position: fixed; }
|
||||
.posAbs { position: absolute; }
|
||||
|
||||
@ -699,7 +703,7 @@ body {
|
||||
}
|
||||
|
||||
.boxShadowProfileAvatar {
|
||||
box-shadow: 0 0 0 6px #F6F6F9;
|
||||
box-shadow: 0 0 0 6px var(--solid_color_primary);
|
||||
}
|
||||
|
||||
.listStyleNone {
|
||||
|
@ -26,7 +26,7 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
def brand_color
|
||||
'#282c37'
|
||||
'#21D07B'
|
||||
end
|
||||
|
||||
def description
|
||||
|
@ -6,7 +6,7 @@
|
||||
# id :bigint(8) not null, primary key
|
||||
# list_id :bigint(8) not null
|
||||
# account_id :bigint(8) not null
|
||||
# follow_id :bigint(8) not null
|
||||
# follow_id :bigint(8) default(1)
|
||||
#
|
||||
|
||||
class ListAccount < ApplicationRecord
|
||||
@ -21,6 +21,6 @@ class ListAccount < ApplicationRecord
|
||||
private
|
||||
|
||||
def set_follow
|
||||
self.follow = Follow.find_by!(account_id: list.account_id, target_account_id: account.id) unless list.account_id == account.id
|
||||
self.follow = Follow.find_by!(account_id: list.account_id, target_account_id: account.id) unless true
|
||||
end
|
||||
end
|
||||
|
@ -32,7 +32,7 @@ class ManifestSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
def theme_color
|
||||
'#282c37'
|
||||
'#21D07B'
|
||||
end
|
||||
|
||||
def background_color
|
||||
|
@ -15,7 +15,7 @@
|
||||
%link{ rel: 'mask-icon', href: '/mask-icon.svg', color: '#2B90D9' }/
|
||||
%link{ rel: 'manifest', href: '/manifest.json' }/
|
||||
%meta{ name: 'msapplication-config', content: '/browserconfig.xml' }/
|
||||
%meta{ name: 'theme-color', content: '#282c37' }/
|
||||
%meta{ name: 'theme-color', content: '#21D07B' }/
|
||||
%meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/
|
||||
|
||||
- if @tag
|
||||
|
@ -11,7 +11,6 @@
|
||||
%link{ rel: 'dns-prefetch', href: storage_host }/
|
||||
|
||||
= stylesheet_pack_tag 'common', media: 'all'
|
||||
= stylesheet_pack_tag Setting.default_settings['theme'], media: 'all'
|
||||
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
|
||||
= javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
|
||||
= javascript_pack_tag 'public', integrity: true, crossorigin: 'anonymous'
|
||||
|
@ -6,7 +6,6 @@
|
||||
%title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
|
||||
%meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
|
||||
= stylesheet_pack_tag 'common', media: 'all'
|
||||
= stylesheet_pack_tag Setting.default_settings['theme'], media: 'all'
|
||||
= javascript_pack_tag 'common', integrity: true, crossorigin: 'anonymous'
|
||||
= javascript_pack_tag 'error', integrity: true, crossorigin: 'anonymous'
|
||||
%body.error
|
||||
|
@ -400,7 +400,7 @@ ActiveRecord::Schema.define(version: 2020_04_30_154012) do
|
||||
create_table "list_accounts", force: :cascade do |t|
|
||||
t.bigint "list_id", null: false
|
||||
t.bigint "account_id", null: false
|
||||
t.bigint "follow_id", null: false
|
||||
t.bigint "follow_id", default: nil
|
||||
t.index ["account_id", "list_id"], name: "index_list_accounts_on_account_id_and_list_id", unique: true
|
||||
t.index ["follow_id"], name: "index_list_accounts_on_follow_id"
|
||||
t.index ["list_id", "account_id"], name: "index_list_accounts_on_list_id_and_account_id"
|
||||
|
@ -3,7 +3,7 @@
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#282c37</TileColor>
|
||||
<TileColor>#21D07B</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
|
Loading…
Reference in New Issue
Block a user