This commit is contained in:
mgabdev 2020-05-03 01:22:49 -04:00
parent 196a906cec
commit 055b5a430f
85 changed files with 1110 additions and 1051 deletions

@ -4,52 +4,80 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
include Authorization include Authorization
before_action -> { authorize_if_got_token! :read, :'read:accounts' } before_action -> { authorize_if_got_token! :read, :'read:accounts' }
before_action :set_status
respond_to :json before_action :verify_own_status
after_action :insert_pagination_headers
def index def index
render json: {}, status: :ok @accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end end
private private
def load_accounts 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 end
def default_accounts def default_accounts
# Account
.includes(:favourites, :account_stat)
.references(:favourites)
.where(favourites: { status_id: @status.id })
end end
def paginated_favourites 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 end
def next_path def next_path
# if records_continue?
api_v1_status_favourited_by_index_url pagination_params(max_id: pagination_max_id)
end
end end
def prev_path def prev_path
# unless @accounts.empty?
api_v1_status_favourited_by_index_url pagination_params(since_id: pagination_since_id)
end
end end
def pagination_max_id def pagination_max_id
# @accounts.last.favourites.last.id
end end
def pagination_since_id def pagination_since_id
# @accounts.first.favourites.first.id
end end
def records_continue? def records_continue?
# @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end end
def set_status def set_status
# @status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end end
def pagination_params(core_params) def pagination_params(core_params)
# params.slice(:limit).permit(:limit).merge(core_params)
end end
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 end
def current_theme def current_theme
'light' 'default'
# : todo : # : todo :
# current_user.setting_theme # current_user.setting_theme
end end

@ -258,8 +258,7 @@ export const fetchListSuggestions = (q) => (dispatch, getState) => {
const params = { const params = {
q, q,
resolve: false, resolve: false,
limit: 4, limit: 25,
following: true,
}; };
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => { 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 GIFS_CLEAR_RESULTS = 'GIFS_CLEAR_RESULTS'
export const GIF_SET_SELECTED = 'GIF_SET_SELECTED' export const GIF_SET_SELECTED = 'GIF_SET_SELECTED'
export const GIF_CHANGE_SEARCH_TEXT = 'GIF_CHANGE_SEARCH_TEXT' 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_REQUEST = 'GIF_RESULTS_FETCH_REQUEST'
export const GIF_RESULTS_FETCH_SUCCESS = 'GIF_RESULTS_FETCH_SUCCESS' export const GIF_RESULTS_FETCH_SUCCESS = 'GIF_RESULTS_FETCH_SUCCESS'

@ -135,6 +135,8 @@ class Account extends ImmutablePureComponent {
isOutline={true} isOutline={true}
color='brand' color='brand'
backgroundColor='none' backgroundColor='none'
icon={actionIcon}
iconSize='10px'
> >
{actionTitle} {actionTitle}
</Button> </Button>

@ -265,7 +265,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
className={textareaClasses} className={textareaClasses}
disabled={disabled} disabled={disabled}
placeholder={placeholder} placeholder={placeholder}
autoFocus={false} dautoFocus={false}
value={value} value={value}
onChange={this.onChange} onChange={this.onChange}
// onKeyDown={this.onKeyDown} // onKeyDown={this.onKeyDown}

@ -138,6 +138,7 @@ export default class Button extends PureComponent {
cursorPointer: 1, cursorPointer: 1,
textAlignCenter: 1, textAlignCenter: 1,
outlineNone: 1, outlineNone: 1,
// outlineOnFocus: !isText,
flexRow: !!children && !!icon, flexRow: !!children && !!icon,
cursorNotAllowed: isDisabled, cursorNotAllowed: isDisabled,
opacity05: 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 = { const options = {
rel, rel,
target, target,
@ -230,6 +234,7 @@ export default class Button extends PureComponent {
className: classes, className: classes,
href: href || undefined, href: href || undefined,
ref: this.setRef, ref: this.setRef,
'data-method': dataMethod,
...handlers, ...handlers,
} }

@ -1,7 +1,4 @@
import classnames from 'classnames/bind' import { CX } from '../constants'
// Bind CSS Modules global variable `_s` to classNames module
const cx = classnames.bind(_s)
/** /**
* Renders a divider component * Renders a divider component
@ -18,7 +15,7 @@ export default class Divider extends PureComponent {
render() { render() {
const { isSmall, isInvisible } = this.props const { isSmall, isInvisible } = this.props
const classes = cx({ const classes = CX({
default: 1, default: 1,
borderBottom1PX: !isInvisible, borderBottom1PX: !isInvisible,
borderColorSecondary: !isInvisible, borderColorSecondary: !isInvisible,

@ -31,13 +31,13 @@ export default class Heading extends PureComponent {
} }
render() { render() {
const { children, size, center } = this.props const { children, size, isCentered } = this.props
// Each size has it's own custom style // Each size has it's own custom style
const classes = cx({ const classes = cx({
default: 1, default: 1,
text: 1, text: 1,
textAlignCenter: center, textAlignCenter: isCentered,
colorPrimary: [SIZES.h1, SIZES.h2].indexOf(size) > -1, colorPrimary: [SIZES.h1, SIZES.h2].indexOf(size) > -1,
colorSecondary: [SIZES.h3, SIZES.h4, SIZES.h5].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), text: intl.formatMessage(messages.help),
requiresUser: true, requiresUser: true,
}, },
{ // : todo :
onClick: onOpenHotkeys, // {
text: intl.formatMessage(messages.hotkeys), // onClick: onOpenHotkeys,
requiresUser: true, // text: intl.formatMessage(messages.hotkeys),
}, // requiresUser: true,
// },
{ {
to: '/auth/edit', to: '/auth/edit',
text: intl.formatMessage(messages.security), text: intl.formatMessage(messages.security),

@ -56,6 +56,8 @@ export default class ListItem extends PureComponent {
flexRow: 1, flexRow: 1,
alignItemsCenter: 1, alignItemsCenter: 1,
width100PC: 1, width100PC: 1,
outlineNone: 1,
bgTransparent: 1,
bgSubtle_onHover: 1, bgSubtle_onHover: 1,
borderColorSecondary: !isLast, borderColorSecondary: !isLast,
borderBottom1PX: !isLast, borderBottom1PX: !isLast,

@ -8,7 +8,7 @@ import SettingSwitch from '../setting_switch'
import Text from '../text' import Text from '../text'
const messages = defineMessages({ 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' }, saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' }, onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
showInSidebar: { id: 'show_in_sidebar', defaultMessage: 'Show in Sidebar' }, showInSidebar: { id: 'show_in_sidebar', defaultMessage: 'Show in Sidebar' },
@ -18,17 +18,15 @@ const mapStateToProps = (state) => ({
settings: state.getIn(['settings', 'community']), settings: state.getIn(['settings', 'community']),
}) })
const mapDispatchToProps = (dispatch, { onClose }) => { const mapDispatchToProps = (dispatch, { onClose }) => ({
return { onChange(key, checked) {
onChange(key, checked) { dispatch(changeSetting(['community', ...key], checked))
dispatch(changeSetting(['community', ...key], checked)) },
}, onSave() {
onSave() { dispatch(saveSettings())
dispatch(saveSettings()) onClose()
onClose() },
}, })
}
}
export default export default
@connect(mapStateToProps, mapDispatchToProps) @connect(mapStateToProps, mapDispatchToProps)
@ -39,6 +37,7 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired, settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired, onSave: PropTypes.func.isRequired,
} }
@ -47,10 +46,16 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
} }
render() { render() {
const { intl, settings, onChange, onClose } = this.props const {
intl,
settings,
onChange,
onClose,
} = this.props
return ( return (
<ModalLayout <ModalLayout
onClose={onClose}
width={320} width={320}
title={intl.formatMessage(messages.title)} title={intl.formatMessage(messages.title)}
> >

@ -14,8 +14,6 @@ class ConfirmationModal extends PureComponent {
confirm: PropTypes.any.isRequired, confirm: PropTypes.any.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onConfirm: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired,
secondary: PropTypes.string,
onSecondary: PropTypes.func,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
onCancel: PropTypes.func, onCancel: PropTypes.func,
} }
@ -29,11 +27,6 @@ class ConfirmationModal extends PureComponent {
this.props.onConfirm() this.props.onConfirm()
} }
handleSecondary = () => {
this.props.onClose()
this.props.onSecondary()
}
handleCancel = () => { handleCancel = () => {
const { onClose, onCancel } = this.props const { onClose, onCancel } = this.props
onClose() onClose()
@ -49,7 +42,6 @@ class ConfirmationModal extends PureComponent {
title, title,
message, message,
confirm, confirm,
secondary
} = this.props } = this.props
return ( return (
@ -74,19 +66,11 @@ class ConfirmationModal extends PureComponent {
onClick={this.handleCancel} onClick={this.handleCancel}
className={[_s.mr10, _s.flexGrow1].join(' ')} 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' /> <FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
</Text> </Text>
</Button> </Button>
{ /**
: todo :
*/
secondary !== undefined && (
<Button text={secondary} onClick={this.handleSecondary} />
)
}
<Button <Button
backgroundColor='brand' backgroundColor='brand'
color='white' color='white'
@ -94,7 +78,7 @@ class ConfirmationModal extends PureComponent {
ref={this.setRef} ref={this.setRef}
className={_s.flexGrow1} className={_s.flexGrow1}
> >
<Text size='medium' weight='bold' color='inherit'> <Text size='medium' weight='bold' align='center' color='inherit'>
{confirm} {confirm}
</Text> </Text>
</Button> </Button>

@ -1,6 +1,12 @@
import { injectIntl, defineMessages } from 'react-intl' import { injectIntl, defineMessages } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes' 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 ModalLayout from './modal_layout'
import Button from '../button' import Button from '../button'
import Text from '../text' import Text from '../text'
@ -12,12 +18,15 @@ const messages = defineMessages({
}) })
const mapStateToProps = (state) => ({ 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) => ({ const mapDispatchToProps = (dispatch) => ({
onChange(path, value) { onChange(key, value) {
dispatch(setFilter(path, value)) dispatch(changeSetting(['displayOptions', key], value))
dispatch(saveSettings())
}, },
}) })
@ -27,34 +36,47 @@ export default
class DisplayOptionsModal extends ImmutablePureComponent { class DisplayOptionsModal extends ImmutablePureComponent {
static propTypes = { static propTypes = {
isSubmitting: PropTypes.bool.isRequired, fontSize: PropTypes.string,
account: PropTypes.object.isRequired,
onConfirm: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
displayOptionsSettings: ImmutablePropTypes.map,
theme: PropTypes.string,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
settings: ImmutablePropTypes.map.isRequired, onClose: PropTypes.func.isRequired,
} }
handleClick = () => { updateOnProps = [
this.props.onClose() 'fontSize',
this.props.onConfirm(this.props.account, this.props.notifications) 'displayOptionsSettings',
'theme',
]
handleOnFontSizeChange = (e) => {
const fontSizeNames = Object.keys(FONT_SIZES)
const index = fontSizeNames[e.target.value]
this.props.onChange('fontSize', index)
}
handleOnThemeSelected = (e) => {
this.props.onChange('theme', e.target.value)
}
handleOnRadiusKeyDisabled = (key, checked) => {
this.props.onChange(key, checked)
} }
// document.documentElement.style.setProperty("--color-surface", "black");
render() { render() {
const { const {
account, fontSize,
displayOptionsSettings,
intl, intl,
settings, theme,
onChange,
onClose, onClose,
} = this.props } = this.props
// theme - light, muted, dark const fontSizeNames = Object.keys(FONT_SIZES)
// text size - extra small, small, normal, medium, large, extra large const currentFontSizeIndex = fontSizeNames.indexOf(fontSize)
// rounded borders
return ( return (
<ModalLayout <ModalLayout
@ -64,86 +86,165 @@ class DisplayOptionsModal extends ImmutablePureComponent {
> >
<div className={[_s.default, _s.mb15].join(' ')}> <div className={[_s.default, _s.mb15].join(' ')}>
<Text> <Text align='center' color='secondary' size='medium'>
{intl.formatMessage(messages.message)} {intl.formatMessage(messages.message)}
</Text> </Text>
</div> </div>
<div className={[_s.default, _s.mb10].join(' ')}> <div className={[_s.default, _s.mb15].join(' ')}>
<Text weight='bold' color='secondary'> <Text weight='bold' size='small' color='secondary'>
Font Size Font Size
</Text> </Text>
<div className={[_s.default, _s.radiusSmall, _s.mt10, _s.py15, _s.px15, _s.bgTertiary].join(' ')}> <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> </div>
<div className={[_s.default, _s.mb10].join(' ')}> <div className={[_s.default, _s.mb15].join(' ')}>
<Text weight='bold' color='secondary'> <Text weight='bold' size='small' color='secondary'>
Rounded Rounded
</Text> </Text>
<div className={[_s.default, _s.radiusSmall, _s.mt10, _s.py15, _s.px15, _s.bgTertiary].join(' ')}> <div className={[_s.default, _s.radiusSmall, _s.mt10, _s.py15, _s.px15, _s.bgTertiary].join(' ')}>
<SettingSwitch <SettingSwitch
prefix='notification' prefix='displayOptions'
settings={settings} settings={displayOptionsSettings}
settingPath={'onlyVerified'} settingPath={'radiusSmallDisabled'}
onChange={onChange} onChange={this.handleOnRadiusKeyDisabled}
label={'Small Radius'} label={'Small Radius Disabled'}
/> />
<SettingSwitch <SettingSwitch
prefix='notification' prefix='displayOptions'
settings={settings} settings={displayOptionsSettings}
settingPath={'onlyVerified'} settingPath={'radiusCircleDisabled'}
onChange={onChange} onChange={this.handleOnRadiusKeyDisabled}
label={'Circle Radius'} label={'Circles Disabled'}
/> />
</div> </div>
</div> </div>
<div className={[_s.default, _s.mb10].join(' ')}> <div className={[_s.default, _s.mb10].join(' ')}>
<Text weight='bold' color='secondary'> <Text weight='bold' size='small' color='secondary'>
Theme Theme
</Text> </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(' ')}> <ThemeBlock
<div className={[_s.default, _s.bgPrimary, _s.radiusSmall]}> title='Light'
<Text> value='light'
Light checked={theme === 'light'}
</Text> onChange={this.handleOnThemeSelected}
</div> style={{
</div> borderColor: '#ececed',
backgroundColor: '#fff',
color: '#2d3436',
}}
/>
<div className={[_s.default, _s.py10, _s.px10, _s.flexGrow1].join(' ')}> <ThemeBlock
<div className={[_s.default, _s.bgPrimary, _s.radiusSmall]}> title='Muted'
<Text> value='muted'
Muted checked={theme === 'muted'}
</Text> onChange={this.handleOnThemeSelected}
</div> style={{
</div> borderColor: '#424141',
backgroundColor: '#222',
color: '#fff',
}}
/>
<div className={[_s.default, _s.py10, _s.px10, _s.flexGrow1].join(' ')}> <ThemeBlock
<div className={[_s.default, _s.bgPrimary, _s.radiusSmall]}> title='Black'
<Text> value='black'
Black checked={theme === 'black'}
</Text> onChange={this.handleOnThemeSelected}
</div> style={{
</div> borderColor: '#212020',
backgroundColor: '#13171b',
color: '#cccbcb',
}}
/>
</div> </div>
</div> </div>
<div className={[_s.mlAuto, _s.mrAuto].join(' ')}> <div className={[_s.mlAuto, _s.my10, _s.mrAuto].join(' ')}>
<Button> <Button onClick={onClose}>
<Text size='medium' color='inherit'> <Text size='medium' color='inherit' className={_s.px10}>
Done Done
</Text> </Text>
</Button> </Button>
</div> </div>
</ModalLayout> </ModalLayout>
) )
} }
} }
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 { injectIntl, defineMessages } from 'react-intl'
import { deleteList } from '../../actions/lists' import { deleteList } from '../../actions/lists'
import ConfirmationModal from './confirmation_modal' import ConfirmationModal from './confirmation_modal'
@ -9,24 +11,24 @@ const messages = defineMessages({
}) })
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onConfirm(listId) { onConfirm: (listId) => dispatch(deleteList(listId)),
dispatch(deleteList(listId))
},
}) })
export default export default
@injectIntl @injectIntl
@connect(null, mapDispatchToProps) @connect(null, mapDispatchToProps)
class ListDeleteModal extends PureComponent { class ListDeleteModal extends ImmutablePureComponent {
static propTypes = { static propTypes = {
list: PropTypes.object.isRequired, list: ImmutablePropTypes.map.isRequired,
onConfirm: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
onConfirm: PropTypes.func.isRequired,
} }
handleClick = () => { handleClick = () => {
this.props.onConfirm(this.props.list.get('id')) this.props.onConfirm(this.props.list.get('id'))
// : todo :
// redirect back to /lists
} }
render() { render() {

@ -14,19 +14,20 @@ class ListEditorModal extends ImmutablePureComponent {
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
listId: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
} }
render() { render() {
const { intl, onClose, listId } = this.props const { intl, onClose, id } = this.props
return ( return (
<ModalLayout <ModalLayout
title={intl.formatMessage(messages.title)} title={intl.formatMessage(messages.title)}
width={500} width={500}
onClose={onClose} onClose={onClose}
noPadding
> >
<ListEdit listId={listId} /> <ListEdit id={id} />
</ModalLayout> </ModalLayout>
) )
} }

@ -21,17 +21,15 @@ const mapStateToProps = (state) => ({
settings: state.getIn(['settings', 'list']), settings: state.getIn(['settings', 'list']),
}) })
const mapDispatchToProps = (dispatch, { onClose }) => { const mapDispatchToProps = (dispatch, { onClose }) => ({
return { onChange(key, checked) {
onChange(key, checked) { dispatch(changeSetting(['list', ...key], checked))
dispatch(changeSetting(['list', ...key], checked)) },
}, onSave() {
onSave() { dispatch(saveSettings())
dispatch(saveSettings()) onClose()
onClose() },
}, })
}
}
export default export default
@connect(mapStateToProps, mapDispatchToProps) @connect(mapStateToProps, mapDispatchToProps)

@ -29,6 +29,8 @@ import {
MODAL_MUTE, MODAL_MUTE,
MODAL_PRO_UPGRADE, MODAL_PRO_UPGRADE,
MODAL_REPORT, MODAL_REPORT,
MODAL_STATUS_LIKES,
MODAL_STATUS_REPOSTS,
MODAL_STATUS_REVISIONS, MODAL_STATUS_REVISIONS,
MODAL_UNAUTHORIZED, MODAL_UNAUTHORIZED,
MODAL_UNFOLLOW, MODAL_UNFOLLOW,
@ -60,6 +62,8 @@ import {
MuteModal, MuteModal,
ProUpgradeModal, ProUpgradeModal,
ReportModal, ReportModal,
StatusLikesModal,
StatusRepostsModal,
StatusRevisionsModal, StatusRevisionsModal,
UnauthorizedModal, UnauthorizedModal,
UnfollowModal, UnfollowModal,
@ -92,6 +96,8 @@ MODAL_COMPONENTS[MODAL_MEDIA] = MediaModal
MODAL_COMPONENTS[MODAL_MUTE] = MuteModal MODAL_COMPONENTS[MODAL_MUTE] = MuteModal
MODAL_COMPONENTS[MODAL_PRO_UPGRADE] = ProUpgradeModal MODAL_COMPONENTS[MODAL_PRO_UPGRADE] = ProUpgradeModal
MODAL_COMPONENTS[MODAL_REPORT] = ReportModal 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_STATUS_REVISIONS] = StatusRevisionsModal
MODAL_COMPONENTS[MODAL_UNAUTHORIZED] = UnauthorizedModal MODAL_COMPONENTS[MODAL_UNAUTHORIZED] = UnauthorizedModal
MODAL_COMPONENTS[MODAL_UNFOLLOW] = UnfollowModal 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 { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import moment from 'moment-mini'
import PanelLayout from './panel_layout' import PanelLayout from './panel_layout'
import ColumnIndicator from '../column_indicator'
import Divider from '../divider' import Divider from '../divider'
import Icon from '../icon' import Icon from '../icon'
import RelativeTimestamp from '../relative_timestamp'
import Text from '../text' import Text from '../text'
const messages = defineMessages({ const messages = defineMessages({
@ -18,16 +19,20 @@ class ListDetailsPanel extends ImmutablePureComponent {
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
onEdit: PropTypes.func.isRequired,
list: ImmutablePropTypes.map, list: ImmutablePropTypes.map,
onEdit: PropTypes.func.isRequired,
} }
handleOnEdit = () => { updateOnProps = [
this.props.onEdit() 'list',
} ]
render() { render() {
const { intl, list } = this.props const {
intl,
list,
onEdit,
} = this.props
const title = !!list ? list.get('title') : '' const title = !!list ? list.get('title') : ''
const createdAt = !!list ? list.get('created_at') : '' const createdAt = !!list ? list.get('created_at') : ''
@ -36,34 +41,41 @@ class ListDetailsPanel extends ImmutablePureComponent {
<PanelLayout <PanelLayout
title={intl.formatMessage(messages.title)} title={intl.formatMessage(messages.title)}
headerButtonTitle={intl.formatMessage(messages.edit)} headerButtonTitle={intl.formatMessage(messages.edit)}
headerButtonAction={this.handleOnEdit} headerButtonAction={onEdit}
> >
<div className={_s.default}> {
(!title || !createdAt) &&
<ColumnIndicator type='loading' />
}
{
title && createdAt &&
<div className={_s.default}>
<div className={_s.default}>
<Text weight='medium'>
{title}
</Text>
</div>
<Divider isSmall />
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Icon id='calendar' size='12px' className={_s.fillSecondary} />
<Text
size='small'
color='secondary'
className={_s.ml5}
>
{
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
date: moment(createdAt).format('lll'),
}} />
}
</Text>
</div>
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Text weight='medium'>
{title}
</Text>
</div> </div>
}
<Divider isSmall />
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Icon id='calendar' size='12px' className={_s.fillSecondary} />
<Text
size='small'
color='secondary'
className={_s.ml5}
>
{
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
date: <RelativeTimestamp timestamp={createdAt} />,
}} />
}
</Text>
</div>
</div>
</PanelLayout> </PanelLayout>
) )
} }

@ -1,6 +1,7 @@
import { defineMessages, injectIntl } from 'react-intl' import { defineMessages, injectIntl } from 'react-intl'
import { MODAL_DISPLAY_OPTIONS } from '../../constants' import { MODAL_DISPLAY_OPTIONS } from '../../constants'
import { openModal } from '../../actions/modal' import { openModal } from '../../actions/modal'
import { closePopover } from '../../actions/popover'
import PopoverLayout from './popover_layout' import PopoverLayout from './popover_layout'
import List from '../list' import List from '../list'
@ -13,6 +14,7 @@ const messages = defineMessages({
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onOpenDisplayModal: () => { onOpenDisplayModal: () => {
dispatch(closePopover())
dispatch(openModal(MODAL_DISPLAY_OPTIONS)) dispatch(openModal(MODAL_DISPLAY_OPTIONS))
}, },
}) })
@ -54,7 +56,7 @@ class SidebarMorePopover extends PureComponent {
}, },
{ {
title: intl.formatMessage(messages.logout), 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 { List as ImmutableList } from 'immutable'
import IntersectionObserverArticle from './intersection_observer_article' import IntersectionObserverArticle from './intersection_observer_article'
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper' import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
import Block from './block'
import ColumnIndicator from './column_indicator' import ColumnIndicator from './column_indicator'
import LoadMore from './load_more' 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} onChange={this.handleOnChange}
onFocus={this.handleOnFocus} onFocus={this.handleOnFocus}
onBlur={this.handleOnBlur} onBlur={this.handleOnBlur}
autoComplete='off'
/> />
<Button <Button

@ -16,6 +16,14 @@ export default class SettingSwitch extends ImmutablePureComponent {
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
} }
updateOnProps = [
'prefix',
'settings',
'settingPath',
'description',
'label',
]
onChange = ({ target }) => { onChange = ({ target }) => {
this.props.onChange(this.props.settingPath, target.checked) this.props.onChange(this.props.settingPath, target.checked)
} }

@ -38,17 +38,13 @@ const messages = defineMessages({
donate: { id: 'tabs_bar.donate', defaultMessage: 'Make a Donation' }, donate: { id: 'tabs_bar.donate', defaultMessage: 'Make a Donation' },
}) })
const mapStateToProps = (state) => { const mapStateToProps = (state) => ({
const getAccount = makeGetAccount() account: makeGetAccount()(state, me),
moreOpen: state.getIn(['popover', 'popoverType']) === 'SIDEBAR_MORE',
return { notificationCount: state.getIn(['notifications', 'unread']),
account: getAccount(state, me), homeItemsQueueCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
moreOpen: state.getIn(['popover', 'popoverType']) === 'SIDEBAR_MORE', showCommunityTimeline: state.getIn(['settings', 'community', 'shows', 'inSidebar']),
notificationCount: state.getIn(['notifications', 'unread']), })
homeItemsQueueCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
showCommunityTimeline: state.getIn(['settings', 'community', 'shows', 'inSidebar']),
}
}
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onClose() { onClose() {
@ -91,7 +87,7 @@ class Sidebar extends ImmutablePureComponent {
this.props.onOpenComposeModal() this.props.onOpenComposeModal()
} }
handleOpenSidebarMorePopover =() => { handleOpenSidebarMorePopover = () => {
this.props.openSidebarMorePopover({ this.props.openSidebarMorePopover({
targetRef: this.moreBtnRef, targetRef: this.moreBtnRef,
position: 'top', position: 'top',
@ -226,23 +222,46 @@ class Sidebar extends ImmutablePureComponent {
<div className={[_s.default, _s.width240PX].join(' ')}> <div className={[_s.default, _s.width240PX].join(' ')}>
<div className={[_s.default, _s.posFixed, _s.heightCalc53PX, _s.bottom0].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, _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 && !!title &&
<div className={[_s.default, _s.flexRow, _s.px5, _s.py10].join(' ')}> <div className={[_s.default, _s.flexRow, _s.px5, _s.pt10].join(' ')}>
<Button {
noClasses showBackBtn &&
color='primary' <Button
backgroundColor='none' noClasses
className={[_s.alignItemsCenter, _s.bgTransparent, _s.mr5, _s.cursorPointer, _s.outlineNone, _s.default, _s.justifyContentCenter].join(' ')} color='primary'
icon='back' backgroundColor='none'
iconSize='20px' className={[_s.alignItemsCenter, _s.bgTransparent, _s.mr5, _s.cursorPointer, _s.outlineNone, _s.default, _s.justifyContentCenter].join(' ')}
iconClassName={[_s.mr5, _s.fillPrimary].join(' ')} icon='arrow-left'
onClick={this.handleBackClick} iconSize='24px'
/> iconClassName={[_s.mr5, _s.fillPrimary].join(' ')}
onClick={this.handleBackClick}
/>
}
<Heading size='h1'> <Heading size='h1'>
{title} {title}
</Heading> </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> </div>
} }
{ {

@ -89,6 +89,8 @@ class Status extends ImmutablePureComponent {
cachedMediaWidth: PropTypes.number, cachedMediaWidth: PropTypes.number,
contextType: PropTypes.string, contextType: PropTypes.string,
commentsLimited: PropTypes.bool, commentsLimited: PropTypes.bool,
onOpenLikes: PropTypes.func.isRequired,
onOpenReposts: PropTypes.func.isRequired,
} }
// Avoid checking props that are functions (and whose equality will always // Avoid checking props that are functions (and whose equality will always
@ -472,6 +474,8 @@ class Status extends ImmutablePureComponent {
onReply={this.props.onReply} onReply={this.props.onReply}
onRepost={this.props.onRepost} onRepost={this.props.onRepost}
onShare={this.props.onShare} onShare={this.props.onShare}
onOpenLikes={this.props.onOpenLikes}
onOpenReposts={this.props.onOpenReposts}
/> />
} }

@ -37,6 +37,8 @@ class StatusActionBar extends ImmutablePureComponent {
onReply: PropTypes.func.isRequired, onReply: PropTypes.func.isRequired,
onRepost: PropTypes.func.isRequired, onRepost: PropTypes.func.isRequired,
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
onOpenLikes: PropTypes.func.isRequired,
onOpenReposts: PropTypes.func.isRequired,
} }
updateOnProps = ['status'] updateOnProps = ['status']
@ -58,15 +60,11 @@ class StatusActionBar extends ImmutablePureComponent {
} }
openLikesList = () => { openLikesList = () => {
// : todo : this.props.onOpenLikes(this.props.status)
}
toggleCommentsVisible = () => {
// : todo :
} }
openRepostsList = () => { openRepostsList = () => {
// : todo : this.props.onOpenReposts(this.props.status)
} }
setRepostButton = (n) => { setRepostButton = (n) => {

@ -35,6 +35,7 @@ export default class Switch extends PureComponent {
circle: 1, circle: 1,
border1PX: 1, border1PX: 1,
mlAuto: 1, mlAuto: 1,
bgPrimary: 1,
borderColorSecondary: 1, borderColorSecondary: 1,
bgBrand: checked, bgBrand: checked,
}) })

@ -56,6 +56,8 @@ export const MODAL_MEDIA = 'MEDIA'
export const MODAL_MUTE = 'MUTE' export const MODAL_MUTE = 'MUTE'
export const MODAL_PRO_UPGRADE = 'PRO_UPGRADE' export const MODAL_PRO_UPGRADE = 'PRO_UPGRADE'
export const MODAL_REPORT = 'REPORT' 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_STATUS_REVISIONS = 'STATUS_REVISIONS'
export const MODAL_UNAUTHORIZED = 'UNAUTHORIZED' export const MODAL_UNAUTHORIZED = 'UNAUTHORIZED'
export const MODAL_UNFOLLOW = 'UNFOLLOW' 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_LARGE = '17px'
export const FONT_SIZES = { export const FONT_SIZES = {
'extra-small': FONT_SIZES_EXTRA_SMALL, 'extra-small': '12px',
small: FONT_SIZES_SMALL, small: '13px',
normal: FONT_SIZES_NORMAL, normal: '14px',
medium: FONT_SIZES_MEDIUM, medium: '15px',
large: FONT_SIZES_LARGE, large: '16px',
'extra-large': FONT_SIZES_EXTRA_LARGE, 'extra-large': '17px',
} }
export const THEMES = [ export const THEMES = [
'light', 'light',
'muted', 'muted',

@ -5,39 +5,55 @@ import {
DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE,
} from '../constants' } 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 = { static propTypes = {
theme: PropTypes.string.isRequired,
rounded: PropTypes.bool.isRequired,
fontSize: PropTypes.string.isRequired, fontSize: PropTypes.string.isRequired,
radiusSmallDisabled: PropTypes.bool.isRequired,
radiusCircleDisabled: PropTypes.bool.isRequired,
theme: PropTypes.string.isRequired,
} }
state = { state = {
theme: this.props.theme, theme: this.props.theme,
rounded: this.props.rounded, radiusSmallDisabled: this.props.radiusSmallDisabled,
radiusCircleDisabled: this.props.radiusCircleDisabled,
fontSize: this.props.fontSize, fontSize: this.props.fontSize,
} }
static defaultProps = { static defaultProps = {
theme: 'BLACK', theme: 'light',
rounded: false, radiusSmallDisabled: true,
radiusCircleDisabled: true,
fontSize: 'normal', fontSize: 'normal',
} }
componentDidMount() { componentDidMount() {
this.updateTheme(this.state.theme) 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) this.updateFontSizes(this.state.fontSize)
} }
static getDerivedStateFromProps(nextProps, prevState) { static getDerivedStateFromProps(nextProps, prevState) {
console.log("nextProps:", nextProps)
if (nextProps.theme !== prevState.theme || if (nextProps.theme !== prevState.theme ||
nextProps.rounded !== prevState.rounded || nextProps.radiusSmallDisabled !== prevState.radiusSmallDisabled ||
nextProps.radiusCircleDisabled !== prevState.radiusCircleDisabled ||
nextProps.fontSize !== prevState.fontSize) { nextProps.fontSize !== prevState.fontSize) {
return { return {
theme: nextProps.theme, theme: nextProps.theme,
rounded: nextProps.rounded, radiusSmallDisabled: nextProps.radiusSmallDisabled,
radiusCircleDisabled: nextProps.radiusCircleDisabled,
fontSize: nextProps.fontSize, fontSize: nextProps.fontSize,
} }
} }
@ -50,8 +66,12 @@ export default class Display extends PureComponent {
this.updateTheme(this.state.theme) this.updateTheme(this.state.theme)
} }
if (prevState.rounded !== this.state.rounded) { if (prevState.radiusSmallDisabled !== this.state.radiusSmallDisabled) {
this.updateRounded(this.state.rounded) this.updateRadiusSmallDisabled(this.state.radiusSmallDisabled)
}
if (prevState.radiusCircleDisabled !== this.state.radiusCircleDisabled) {
this.updateRadiusCircleDisabled(this.state.radiusCircleDisabled)
} }
if (prevState.fontSize !== this.state.fontSize) { if (prevState.fontSize !== this.state.fontSize) {
@ -59,16 +79,24 @@ export default class Display extends PureComponent {
} }
} }
updateRounded(rounded) { updateRadiusSmallDisabled(disabled) {
if (rounded) { if (disabled) {
document.documentElement.removeAttribute('rounded') document.documentElement.setAttribute('no-radius', '');
} else { } 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) { updateFontSizes(fontSize) {
let correctedFontSize = fontSize.toUpperCase() let correctedFontSize = fontSize.toLowerCase()
if (!FONT_SIZES.hasOwnProperty(correctedFontSize)) { if (!FONT_SIZES.hasOwnProperty(correctedFontSize)) {
correctedFontSize = DEFAULT_FONT_SIZE correctedFontSize = DEFAULT_FONT_SIZE
} }
@ -78,7 +106,7 @@ export default class Display extends PureComponent {
updateTheme(theme) { updateTheme(theme) {
let correctedTheme = theme.toLowerCase() let correctedTheme = theme.toLowerCase()
if (!THEMES.hasOwnProperty(correctedTheme)) { if (THEMES.indexOf(correctedTheme) < 0) {
correctedTheme = DEFAULT_THEME correctedTheme = DEFAULT_THEME
} }

@ -56,7 +56,7 @@ const makeMapStateToProps = () => {
const ids = [status.get('id')] const ids = [status.get('id')]
const r = state.getIn(['contexts', 'replies', ids[0]]) const r = state.getIn(['contexts', 'replies', ids[0]])
console.log("r:", r) // console.log("r:", r)
while (ids.length > 0) { while (ids.length > 0) {
let id = ids.shift() let id = ids.shift()
@ -253,6 +253,15 @@ const mapDispatchToProps = (dispatch) => ({
onFetchComments(statusId) { onFetchComments(statusId) {
dispatch(fetchComments(statusId)) dispatch(fetchComments(statusId))
}, },
onOpenLikes(status) {
dispatch(openModal('STATUS_LIKES', { status }))
},
onOpenReposts(status) {
dispatch(openModal('STATUS_REPOSTS', { status }))
},
}); });
export default connect(makeMapStateToProps, mapDispatchToProps)(Status); export default connect(makeMapStateToProps, mapDispatchToProps)(Status);

@ -17,7 +17,7 @@ const messages = defineMessages({
home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' }, home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' }, notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' },
public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' }, 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' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }, logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new gab' }, compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new gab' },

@ -12,15 +12,9 @@ const messages = defineMessages({
reject: { id: 'follow_request.reject', defaultMessage: 'Reject' }, reject: { id: 'follow_request.reject', defaultMessage: 'Reject' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => ({
const getAccount = makeGetAccount(); account: makeGetAccount()(state, props.id),
})
const mapStateToProps = (state, props) => ({
account: getAccount(state, props.id),
});
return mapStateToProps;
};
const mapDispatchToProps = (dispatch, { id }) => ({ const mapDispatchToProps = (dispatch, { id }) => ({
onAuthorize() { 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>
);
}
}

@ -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 = () => { 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() { render() {
@ -86,20 +87,22 @@ class ListTimeline extends ImmutablePureComponent {
} }
const emptyMessage = ( const emptyMessage = (
<div className={[_s.default, _s.py15, _s.px15].join(' ')}> <div className={[_s.default, _s.py15, _s.px15, _s.alignItemsCenter].join(' ')}>
<FormattedMessage <FormattedMessage
id='empty_column.list' id='empty_column.list'
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.'
/> />
<Button <div className={_s.mt10}>
onClick={this.handleEditClick} <Button
className={[_s.mt10]} onClick={this.handleEditClick}
> className={[_s.mt10]}
<Text color='inherit' align='center'> >
<FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' /> <Text color='inherit' align='center'>
</Text> <FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' />
</Button> </Text>
</Button>
</div>
</div> </div>
) )

@ -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 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() { render() {
const { status } = this.props
// - if comment render as such
if (!status) {
return <ColumnIndicator type='loading' />
}
return ( return (
<StatusContainer {...this.props} /> <StatusContainer {...this.props} />
) )

@ -1,72 +1,70 @@
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import ColumnIndicator from '../components/column_indicator' import { FormattedMessage } from 'react-intl'
import { fetchLikes } from '../actions/interactions' import { fetchLikes } from '../actions/interactions'
import { fetchStatus } from '../actions/statuses'
import { makeGetStatus } from '../selectors'
import Account from '../components/account' import Account from '../components/account'
import ColumnIndicator from '../components/column_indicator'
import ScrollableList from '../components/scrollable_list' import ScrollableList from '../components/scrollable_list'
const messages = defineMessages({ const mapStateToProps = (state, props) => {
refresh: { id: 'refresh', defaultMessage: 'Refresh' }, const getStatus = makeGetStatus()
}); const status = getStatus(state, {
id: props.params.statusId,
username: props.params.username,
})
const mapStateToProps = (state, props) => ({ return {
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]), status,
}); accountIds: state.getIn(['user_lists', 'liked_by', props.params.statusId]),
}
}
export default export default
@injectIntl
@connect(mapStateToProps) @connect(mapStateToProps)
class StatusLikes extends ImmutablePureComponent { class StatusReposts extends ImmutablePureComponent {
static propTypes = { static propTypes = {
params: PropTypes.object.isRequired, params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
shouldUpdateScroll: PropTypes.func,
accountIds: ImmutablePropTypes.list, accountIds: ImmutablePropTypes.list,
multiColumn: PropTypes.bool, status: ImmutablePropTypes.map,
intl: PropTypes.object.isRequired, }
};
componentWillMount () { 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) { componentWillReceiveProps(nextProps) {
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) { 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 () { render () {
const { intl, shouldUpdateScroll, accountIds, multiColumn } = this.props; const { accountIds, status } = this.props
if (!accountIds) { if (!accountIds) {
return <ColumnIndicator type='loading' /> 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 ( return (
<div> <ScrollableList
<ScrollableList scrollKey='likes'
scrollKey='favourites' emptyMessage={<FormattedMessage id='status.likes.empty' defaultMessage='No one has liked this gab yet. When someone does, they will show up here.' />}
shouldUpdateScroll={shouldUpdateScroll} >
emptyMessage={emptyMessage} {
bindToDocument={!multiColumn} accountIds.map(id =>
> <Account key={id} id={id} />
{accountIds.map(id => )
<Account key={id} id={id} withNote={false} />, }
)} </ScrollableList>
</ScrollableList> )
</div>
);
} }
} }

@ -145,7 +145,7 @@ class SwitchingArea extends PureComponent {
<Redirect from='/' to='/home' exact /> <Redirect from='/' to='/home' exact />
<WrappedRoute path='/home' exact page={HomePage} component={HomeTimeline} content={children} /> <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' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'featured' }} />
<WrappedRoute path='/groups/new' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'new' }} /> <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 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 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 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 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 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') } export function StatusVisibilityPopover() { return import(/* webpackChunkName: "components/status_visibility_popover" */'../../../components/popover/status_visibility_popover') }

@ -1,32 +1,33 @@
import Layout from './layout' import Layout from './layout'
export default class DefaultLayout extends PureComponent { export default class DefaultLayout extends PureComponent {
static propTypes = { static propTypes = {
actions: PropTypes.array, actions: PropTypes.array,
tabs: PropTypes.array, children: PropTypes.node.isRequired,
layout: PropTypes.object, layout: PropTypes.object,
showBackBtn: PropTypes.bool, showBackBtn: PropTypes.bool,
tabs: PropTypes.array,
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
} }
render() { render() {
const { const {
children,
title,
showBackBtn,
layout,
actions, actions,
children,
layout,
showBackBtn,
tabs, tabs,
} = this.props title,
} = this.props
return ( return (
<Layout <Layout
title={title}
showBackBtn={showBackBtn}
actions={actions} actions={actions}
tabs={tabs}
layout={layout} layout={layout}
showBackBtn={showBackBtn}
tabs={tabs}
title={title}
> >
{children} {children}
</Layout> </Layout>

@ -5,32 +5,34 @@ import Layout from './layout'
import GroupHeader from '../components/group_header' import GroupHeader from '../components/group_header'
export default class GroupLayout extends ImmutablePureComponent { export default class GroupLayout extends ImmutablePureComponent {
static propTypes = { static propTypes = {
actions: PropTypes.array, actions: PropTypes.array,
children: PropTypes.node,
group: ImmutablePropTypes.map, group: ImmutablePropTypes.map,
relationships: ImmutablePropTypes.map,
layout: PropTypes.object, layout: PropTypes.object,
relationships: ImmutablePropTypes.map,
showBackBtn: PropTypes.bool, showBackBtn: PropTypes.bool,
title: PropTypes.string,
} }
render() { render() {
const { const {
group,
children,
layout,
showBackBtn,
actions, actions,
children,
group,
layout,
relationships, relationships,
showBackBtn,
title,
} = this.props } = this.props
const title = !!group ? group.get('title') : undefined
return ( return (
<Layout <Layout
noRightSidebar noRightSidebar
title={title}
actions={actions} actions={actions}
showBackBtn={showBackBtn} showBackBtn={showBackBtn}
title={title}
> >
<div className={[_s.default, _s.width100PC, _s.pl15].join(' ')}> <div className={[_s.default, _s.width100PC, _s.pl15].join(' ')}>

@ -1,52 +1,58 @@
import Sticky from 'react-stickynode' import Sticky from 'react-stickynode'
import Search from '../components/search'
import ColumnHeader from '../components/column_header'
import Sidebar from '../components/sidebar' import Sidebar from '../components/sidebar'
import { BREAKPOINT_EXTRA_SMALL } from '../constants' import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import NavigationBar from '../components/navigation_bar' import NavigationBar from '../components/navigation_bar'
// : todo :
// import Footer from '../components/footer' // import Footer from '../components/footer'
import FloatingActionButton from '../components/floating_action_button' import FloatingActionButton from '../components/floating_action_button'
import Responsive from '../features/ui/util/responsive_component' import Responsive from '../features/ui/util/responsive_component'
export default class Layout extends PureComponent { export default class Layout extends PureComponent {
static propTypes = { static propTypes = {
actions: PropTypes.array, actions: PropTypes.array,
tabs: PropTypes.array, children: PropTypes.node,
layout: PropTypes.object, layout: PropTypes.object,
title: PropTypes.string,
showBackBtn: PropTypes.bool,
noSidebar: PropTypes.bool,
noRightSidebar: PropTypes.bool,
noComposeButton: PropTypes.bool, noComposeButton: PropTypes.bool,
noRightSidebar: PropTypes.bool,
noSidebar: PropTypes.bool,
showBackBtn: PropTypes.bool,
tabs: PropTypes.array,
title: PropTypes.string,
} }
render() { render() {
const { const {
children,
title,
showBackBtn,
layout,
actions, actions,
tabs, children,
noSidebar, layout,
noRightSidebar,
noComposeButton, noComposeButton,
noRightSidebar,
noSidebar,
showBackBtn,
tabs,
title,
} = this.props } = this.props
return ( return (
<div className={[_s.default, _s.width100PC, _s.heightMin100VH, _s.bgTertiary].join(' ')}> <div className={[_s.default, _s.width100PC, _s.heightMin100VH, _s.bgTertiary].join(' ')}>
<NavigationBar <NavigationBar
title={title}
tabs={tabs}
actions={actions} actions={actions}
tabs={tabs}
title={title}
/> />
<div className={[_s.default, _s.flexRow, _s.width100PC].join(' ')}> <div className={[_s.default, _s.flexRow, _s.width100PC].join(' ')}>
{ {
!noSidebar && !noSidebar &&
<Responsive min={BREAKPOINT_EXTRA_SMALL}> <Responsive min={BREAKPOINT_EXTRA_SMALL}>
<Sidebar title={title} tabs={tabs} actions={actions} /> <Sidebar
actions={actions}
showBackBtn={showBackBtn}
tabs={tabs}
title={title}
/>
</Responsive> </Responsive>
} }

@ -1,17 +1,16 @@
import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePureComponent from 'react-immutable-pure-component'
import Sticky from 'react-stickynode' import Sticky from 'react-stickynode'
import ProfileHeader from '../components/profile_header'
import NavigationBar from '../components/navigation_bar' import NavigationBar from '../components/navigation_bar'
import ProfileHeader from '../components/profile_header'
export default class ProfileLayout extends ImmutablePureComponent { export default class ProfileLayout extends ImmutablePureComponent {
static propTypes = { static propTypes = {
children: PropTypes.node.isRequired,
account: ImmutablePropTypes.map, account: ImmutablePropTypes.map,
children: PropTypes.node.isRequired,
layout: PropTypes.object, layout: PropTypes.object,
title: PropTypes.string, title: PropTypes.string,
showBackBtn: PropTypes.bool,
} }
render() { render() {
@ -20,7 +19,6 @@ export default class ProfileLayout extends ImmutablePureComponent {
children, children,
layout, layout,
title, title,
showBackBtn,
} = this.props } = this.props
return ( return (

@ -45,7 +45,7 @@
"bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again", "bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users", "column.blocks": "Blocked users",
"column.community": "Community timeline", "column.community": "Community feed",
"column.direct": "Direct messages", "column.direct": "Direct messages",
"column.domain_blocks": "Blocked domains", "column.domain_blocks": "Blocked domains",
"column.favorites": "Favorites", "column.favorites": "Favorites",
@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Зареждане...", "loading_indicator.label": "Зареждане...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -228,7 +228,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -1688,7 +1688,7 @@
{ {
"descriptors": [ "descriptors": [
{ {
"defaultMessage": "Search among people you follow", "defaultMessage": "Search people...",
"id": "lists.search" "id": "lists.search"
} }
], ],

@ -45,7 +45,7 @@
"bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again", "bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users", "column.blocks": "Blocked users",
"column.community": "Community timeline", "column.community": "Community feed",
"column.direct": "Direct messages", "column.direct": "Direct messages",
"column.domain_blocks": "Blocked domains", "column.domain_blocks": "Blocked domains",
"column.favorites": "Favorites", "column.favorites": "Favorites",
@ -221,7 +221,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -230,7 +230,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new gab",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "טוען...", "loading_indicator.label": "טוען...",
"media_gallery.toggle_visible": "נראה\\בלתי נראה", "media_gallery.toggle_visible": "נראה\\בלתי נראה",

@ -45,7 +45,7 @@
"bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again", "bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users", "column.blocks": "Blocked users",
"column.community": "Community timeline", "column.community": "Community feed",
"column.direct": "Direct messages", "column.direct": "Direct messages",
"column.domain_blocks": "Blocked domains", "column.domain_blocks": "Blocked domains",
"column.favorites": "Favorites", "column.favorites": "Favorites",
@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -228,7 +228,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Učitavam...", "loading_indicator.label": "Učitavam...",
"media_gallery.toggle_visible": "Preklopi vidljivost", "media_gallery.toggle_visible": "Preklopi vidljivost",

@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Tunggu sebentar...", "loading_indicator.label": "Tunggu sebentar...",
"media_gallery.toggle_visible": "Tampil/Sembunyikan", "media_gallery.toggle_visible": "Tampil/Sembunyikan",

@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Kargante...", "loading_indicator.label": "Kargante...",
"media_gallery.toggle_visible": "Chanjar videbleso", "media_gallery.toggle_visible": "Chanjar videbleso",

@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -228,7 +228,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -45,7 +45,7 @@
"bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again", "bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users", "column.blocks": "Blocked users",
"column.community": "Community timeline", "column.community": "Community feed",
"column.direct": "Direct messages", "column.direct": "Direct messages",
"column.domain_blocks": "Blocked domains", "column.domain_blocks": "Blocked domains",
"column.favorites": "Favorites", "column.favorites": "Favorites",
@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -228,7 +228,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -228,7 +228,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -45,7 +45,7 @@
"bundle_modal_error.message": "Something went wrong while loading this component.", "bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again", "bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users", "column.blocks": "Blocked users",
"column.community": "Community timeline", "column.community": "Community feed",
"column.direct": "Direct messages", "column.direct": "Direct messages",
"column.domain_blocks": "Blocked domains", "column.domain_blocks": "Blocked domains",
"column.favorites": "Favorites", "column.favorites": "Favorites",
@ -219,7 +219,7 @@
"lists.edit.submit": "Change title", "lists.edit.submit": "Change title",
"lists.new.create": "Add list", "lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title", "lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow", "lists.search": "Search people...",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Hide media", "media_gallery.toggle_visible": "Hide media",
@ -228,7 +228,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?", "mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps", "navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users", "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.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages", "navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover", "navigation_bar.discover": "Discover",

@ -1,11 +1,12 @@
import { Fragment } from 'react' import { Fragment } from 'react'
import PageTitle from '../features/ui/util/page_title' 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 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 { export default class BasicPage extends PureComponent {
static propTypes = { static propTypes = {
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
@ -31,4 +32,5 @@ export default class BasicPage extends PureComponent {
</DefaultLayout> </DefaultLayout>
) )
} }
} }

@ -12,7 +12,7 @@ import TimelineComposeBlock from '../components/timeline_compose_block'
import Divider from '../components/divider' import Divider from '../components/divider'
const messages = defineMessages({ const messages = defineMessages({
community: { 'id': 'column.community', 'defaultMessage': 'Community timeline' }, community: { 'id': 'column.community', 'defaultMessage': 'Community feed' },
}) })
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({

@ -50,36 +50,12 @@ class GroupPage extends ImmutablePureComponent {
relationships, relationships,
} = this.props } = 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') : '' const groupTitle = !!group ? group.get('title') : ''
return ( return (
<GroupLayout <GroupLayout
showBackBtn showBackBtn
title={intl.formatMessage(messages.group)}
group={group} group={group}
relationships={relationships} relationships={relationships}
actions={[ actions={[

@ -1,6 +1,7 @@
import { Fragment } from 'react' import { Fragment } from 'react'
import { openModal } from '../actions/modal' import { openModal } from '../actions/modal'
import { defineMessages, injectIntl } from 'react-intl' import { defineMessages, injectIntl } from 'react-intl'
import { MODAL_HOME_TIMELINE_SETTINGS } from '../constants'
import IntersectionObserverArticle from '../components/intersection_observer_article' import IntersectionObserverArticle from '../components/intersection_observer_article'
import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper' import IntersectionObserverWrapper from '../features/ui/util/intersection_observer_wrapper'
import PageTitle from '../features/ui/util/page_title' import PageTitle from '../features/ui/util/page_title'
@ -25,7 +26,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
onOpenHomePageSettingsModal() { onOpenHomePageSettingsModal() {
dispatch(openModal('HOME_TIMELINE_SETTINGS')) dispatch(openModal(MODAL_HOME_TIMELINE_SETTINGS))
}, },
}) })
@ -35,10 +36,10 @@ export default
class HomePage extends PureComponent { class HomePage extends PureComponent {
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired,
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
totalQueuedItemsCount: PropTypes.number.isRequired, intl: PropTypes.object.isRequired,
onOpenHomePageSettingsModal: PropTypes.func.isRequired, onOpenHomePageSettingsModal: PropTypes.func.isRequired,
totalQueuedItemsCount: PropTypes.number.isRequired,
} }
intersectionObserverWrapper = new IntersectionObserverWrapper() intersectionObserverWrapper = new IntersectionObserverWrapper()
@ -59,7 +60,6 @@ class HomePage extends PureComponent {
this.intersectionObserverWrapper.disconnect() this.intersectionObserverWrapper.disconnect()
} }
render() { render() {
const { const {
intl, intl,
@ -110,13 +110,18 @@ class HomePage extends PureComponent {
</Fragment> </Fragment>
)} )}
> >
<PageTitle <PageTitle
path={intl.formatMessage(messages.home)} path={intl.formatMessage(messages.home)}
badge={totalQueuedItemsCount} badge={totalQueuedItemsCount}
/> />
<TimelineComposeBlock autoFocus={false} /> <TimelineComposeBlock autoFocus={false} />
<Divider /> <Divider />
{children} {children}
</DefaultLayout> </DefaultLayout>
) )
} }

@ -26,7 +26,7 @@ const mapDispatchToProps = (dispatch) => ({
onOpenListEditModal(list) { onOpenListEditModal(list) {
if (!list) return if (!list) return
const listId = list.get('id') const listId = list.get('id')
dispatch(openModal(MODAL_LIST_EDITOR, { listId })) dispatch(openModal(MODAL_LIST_EDITOR, { id: listId }))
}, },
// : todo : // : todo :
// onOpenListTimelineSettingsModal() { // onOpenListTimelineSettingsModal() {
@ -65,7 +65,7 @@ class ListPage extends ImmutablePureComponent {
return ( return (
<DefaultLayout <DefaultLayout
showBackBtn showBackBtn
title={title} title={intl.formatMessage(messages.list)}
actions={[ actions={[
{ {
icon: 'cog', icon: 'cog',

@ -1,21 +1,21 @@
import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings'; import { SETTING_CHANGE, SETTING_SAVE } from '../actions/settings'
import { STORE_HYDRATE } from '../actions/store'; import { STORE_HYDRATE } from '../actions/store'
import { EMOJI_USE } from '../actions/emojis'; import { EMOJI_USE } from '../actions/emojis'
import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists'; import { LIST_DELETE_SUCCESS, LIST_FETCH_FAIL } from '../actions/lists'
import { Map as ImmutableMap, fromJS } from 'immutable'; import { Map as ImmutableMap, fromJS } from 'immutable'
import uuid from '../utils/uuid'; import uuid from '../utils/uuid'
const initialState = ImmutableMap({ const initialState = ImmutableMap({
saved: true, saved: true,
onboarded: false, onboarded: false,
skinTone: 1, skinTone: 1,
// displayOptions: ImmutableMap({ displayOptions: ImmutableMap({
// fontSize: 'normal', fontSize: 'normal',
// radiusSmallEnabled: true, radiusSmallDisabled: false,
// radiusCircleEnabled: true, radiusCircleDisabled: false,
// theme: 'light', theme: 'light',
// }), }),
home: ImmutableMap({ home: ImmutableMap({
shows: 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({ community: ImmutableMap({
shows: ImmutableMap({ shows: ImmutableMap({
inSidebar: false, inSidebar: false,

@ -23,6 +23,7 @@ import {
} from '../actions/accounts' } from '../actions/accounts'
import { import {
REPOSTS_FETCH_SUCCESS, REPOSTS_FETCH_SUCCESS,
LIKES_FETCH_SUCCESS,
} from '../actions/interactions' } from '../actions/interactions'
import { import {
BLOCKS_FETCH_REQUEST, BLOCKS_FETCH_REQUEST,
@ -52,7 +53,7 @@ const initialState = ImmutableMap({
followers: ImmutableMap(), followers: ImmutableMap(),
following: ImmutableMap(), following: ImmutableMap(),
reblogged_by: ImmutableMap(), reblogged_by: ImmutableMap(),
favorited_by: ImmutableMap(), liked_by: ImmutableMap(),
follow_requests: ImmutableMap(), follow_requests: ImmutableMap(),
blocks: ImmutableMap(), blocks: ImmutableMap(),
mutes: ImmutableMap(), mutes: ImmutableMap(),
@ -103,6 +104,8 @@ export default function userLists(state = initialState, action) {
return state.setIn(['following', action.id, 'isLoading'], false); return state.setIn(['following', action.id, 'isLoading'], false);
case REPOSTS_FETCH_SUCCESS: case REPOSTS_FETCH_SUCCESS:
return state.setIn(['reblogged_by', action.id], ImmutableList(action.accounts.map(item => item.id))); 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: 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); 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: case FOLLOW_REQUESTS_EXPAND_SUCCESS:

@ -12,6 +12,9 @@
--color_red: #de2960; --color_red: #de2960;
--color_red-dark: #c72c5b; --color_red-dark: #c72c5b;
--radius-small: 8px;
--radius-circle: 9999px;
--fs_xs: 0.8571428571rem; --fs_xs: 0.8571428571rem;
--fs_s: 0.9285714286rem; --fs_s: 0.9285714286rem;
--fs_n: 1rem; --fs_n: 1rem;
@ -19,19 +22,8 @@
--fs_l: 1.1428571429rem; --fs_l: 1.1428571429rem;
--fs_xl: 1.3571428571rem; --fs_xl: 1.3571428571rem;
--fs_xxl: 1.7142857143rem; --fs_xxl: 1.7142857143rem;
}
:root { /* Default light theme */
--radius-small: 0;
--radius-circle: 0;
}
:root[rounded] {
--radius-small: 8px;
--radius-circle: 9999px;
}
:root[theme='light'] {
--solid_color_primary: #fff; --solid_color_primary: #fff;
--solid_color_primary-opaque:rgba(255, 255, 255,.6); --solid_color_primary-opaque:rgba(255, 255, 255,.6);
--solid_color_secondary: #e2e8ec; --solid_color_secondary: #e2e8ec;
@ -46,34 +38,42 @@
--border_color_secondary: #ececed; --border_color_secondary: #ececed;
} }
:root[no-circle] {
--radius-circle: 0 !important;
}
:root[no-radius] {
--radius-small: 0 !important;
}
:root[theme='muted'] { :root[theme='muted'] {
--solid_color_primary: #222; --solid_color_primary: #222 !important;
--solid_color_primary-opaque:rgba(34, 34, 34, .6); --solid_color_primary-opaque:rgba(34, 34, 34, .6) !important;
--solid_color_secondary: #4f5050; --solid_color_secondary: #4f5050 !important;
--solid_color_secondary-dark: #424343; --solid_color_secondary-dark: #424343 !important;
--solid_color_tertiary: #333; --solid_color_tertiary: #333 !important;
--solid_color_block: #2d2d2d; --solid_color_block: #2d2d2d !important;
--text_color_primary: #fff; --text_color_primary: #fff !important;
--text_color_secondary: #7b7b7b; --text_color_secondary: #7b7b7b !important;
--text_color_tertiary: #656565; --text_color_tertiary: #656565 !important;
--border_color_secondary: #424141; --border_color_secondary: #424141 !important;
} }
:root[theme='black'] { :root[theme='black'] {
--solid_color_primary: #13171b; --solid_color_primary: #13171b !important;
--solid_color_primary-opaque:rgba(19, 23, 27, .6); --solid_color_primary-opaque:rgba(19, 23, 27, .6) !important;
--solid_color_secondary: #4f5050; --solid_color_secondary: #4f5050 !important;
--solid_color_secondary-dark: #424343; --solid_color_secondary-dark: #424343 !important;
--solid_color_tertiary: #000; --solid_color_tertiary: #000 !important;
--solid_color_block: #202327; --solid_color_block: #202327 !important;
--text_color_primary: #cccbcb; --text_color_primary: #cccbcb !important;
--text_color_secondary: #61686E; --text_color_secondary: #61686E !important;
--text_color_tertiary: #656565; --text_color_tertiary: #656565 !important;
--border_color_secondary: #212020; --border_color_secondary: #212020 !important;
} }
html, html,
@ -199,7 +199,6 @@ body {
.inherit { .inherit {
color: inherit; color: inherit;
font: inherit;
white-space: inherit; white-space: inherit;
} }
@ -246,6 +245,9 @@ body {
.whiteSpaceNoWrap { white-space: nowrap; } .whiteSpaceNoWrap { white-space: nowrap; }
.outlineNone { outline: none; } .outlineNone { outline: none; }
.outlineOnFocus:focus {
box-shadow: 0 0 0 5px rgba(21, 156, 228, 0.4);
}
.resizeNone { resize: none; } .resizeNone { resize: none; }
@ -264,6 +266,7 @@ body {
.borderRight1PX { border-right-width: 1px; } .borderRight1PX { border-right-width: 1px; }
.borderBottom1PX { border-bottom-width: 1px; } .borderBottom1PX { border-bottom-width: 1px; }
.borderBottom6PX { border-bottom-width: 6px; }
.borderLeft1PX { border-left-width: 1px; } .borderLeft1PX { border-left-width: 1px; }
.borderTop1PX { border-top-width: 1px; } .borderTop1PX { border-top-width: 1px; }
@ -393,6 +396,7 @@ body {
/* */ /* */
.posSticky { position: sticky; }
.posFixed { position: fixed; } .posFixed { position: fixed; }
.posAbs { position: absolute; } .posAbs { position: absolute; }
@ -699,7 +703,7 @@ body {
} }
.boxShadowProfileAvatar { .boxShadowProfileAvatar {
box-shadow: 0 0 0 6px #F6F6F9; box-shadow: 0 0 0 6px var(--solid_color_primary);
} }
.listStyleNone { .listStyleNone {

@ -26,7 +26,7 @@ class ProofProvider::Keybase::ConfigSerializer < ActiveModel::Serializer
end end
def brand_color def brand_color
'#282c37' '#21D07B'
end end
def description def description

@ -6,7 +6,7 @@
# id :bigint(8) not null, primary key # id :bigint(8) not null, primary key
# list_id :bigint(8) not null # list_id :bigint(8) not null
# account_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 class ListAccount < ApplicationRecord
@ -21,6 +21,6 @@ class ListAccount < ApplicationRecord
private private
def set_follow 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
end end

@ -32,7 +32,7 @@ class ManifestSerializer < ActiveModel::Serializer
end end
def theme_color def theme_color
'#282c37' '#21D07B'
end end
def background_color def background_color

@ -15,7 +15,7 @@
%link{ rel: 'mask-icon', href: '/mask-icon.svg', color: '#2B90D9' }/ %link{ rel: 'mask-icon', href: '/mask-icon.svg', color: '#2B90D9' }/
%link{ rel: 'manifest', href: '/manifest.json' }/ %link{ rel: 'manifest', href: '/manifest.json' }/
%meta{ name: 'msapplication-config', content: '/browserconfig.xml' }/ %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' }/ %meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/
- if @tag - if @tag

@ -11,7 +11,6 @@
%link{ rel: 'dns-prefetch', href: storage_host }/ %link{ rel: 'dns-prefetch', href: storage_host }/
= stylesheet_pack_tag 'common', media: 'all' = 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 'common', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous' = javascript_pack_tag "locale_#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'public', 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']], ' - ') %title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
%meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/ %meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
= stylesheet_pack_tag 'common', media: 'all' = 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 'common', integrity: true, crossorigin: 'anonymous'
= javascript_pack_tag 'error', integrity: true, crossorigin: 'anonymous' = javascript_pack_tag 'error', integrity: true, crossorigin: 'anonymous'
%body.error %body.error

@ -400,7 +400,7 @@ ActiveRecord::Schema.define(version: 2020_04_30_154012) do
create_table "list_accounts", force: :cascade do |t| create_table "list_accounts", force: :cascade do |t|
t.bigint "list_id", null: false t.bigint "list_id", null: false
t.bigint "account_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 ["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 ["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" t.index ["list_id", "account_id"], name: "index_list_accounts_on_list_id_and_account_id"

@ -3,7 +3,7 @@
<msapplication> <msapplication>
<tile> <tile>
<square150x150logo src="/mstile-150x150.png"/> <square150x150logo src="/mstile-150x150.png"/>
<TileColor>#282c37</TileColor> <TileColor>#21D07B</TileColor>
</tile> </tile>
</msapplication> </msapplication>
</browserconfig> </browserconfig>