Merge branch 'mastodong' into 'develop'
Mastodon: conditionally display Markdown, emojiReact column settings, sidebar... See merge request soapbox-pub/soapbox-fe!690
This commit is contained in:
commit
3dacb5448a
19 changed files with 191 additions and 69 deletions
|
@ -55,8 +55,10 @@ export const changeAliasesSuggestions = value => ({
|
|||
|
||||
export const addToAliases = (intl, apId) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const alsoKnownAs = getState().getIn(['meta', 'pleroma', 'also_known_as']);
|
||||
const me = state.get('me');
|
||||
const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(addToAliasesRequest(apId));
|
||||
|
||||
|
@ -92,8 +94,10 @@ export const addToAliasesFail = (apId, error) => ({
|
|||
|
||||
export const removeFromAliases = (intl, apId) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const alsoKnownAs = getState().getIn(['meta', 'pleroma', 'also_known_as']);
|
||||
const me = state.get('me');
|
||||
const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(removeFromAliasesRequest(apId));
|
||||
|
||||
|
|
|
@ -18,14 +18,17 @@ const makeMapStateToProps = () => {
|
|||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, { accountId, added }) => {
|
||||
const me = state.get('me');
|
||||
const ownAccount = getAccount(state, me);
|
||||
|
||||
const account = getAccount(state, accountId);
|
||||
const apId = account.getIn(['pleroma', 'ap_id']);
|
||||
|
||||
return {
|
||||
account,
|
||||
apId,
|
||||
added: typeof added === 'undefined' ? state.getIn(['meta', 'pleroma', 'also_known_as']).includes(apId) : added,
|
||||
me: state.get('me'),
|
||||
added: typeof added === 'undefined' ? ownAccount.getIn(['pleroma', 'also_known_as']).includes(apId) : added,
|
||||
me,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import Icon from 'soapbox/components/icon';
|
|||
import Search from './components/search';
|
||||
import Account from './components/account';
|
||||
import { removeFromAliases } from '../../actions/aliases';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.aliases', defaultMessage: 'Account aliases' },
|
||||
|
@ -19,13 +20,24 @@ const messages = defineMessages({
|
|||
delete: { id: 'column.aliases.delete', defaultMessage: 'Delete' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
aliases: state.getIn(['meta', 'pleroma', 'also_known_as']),
|
||||
searchAccountIds: state.getIn(['aliases', 'suggestions', 'items']),
|
||||
loaded: state.getIn(['aliases', 'suggestions', 'loaded']),
|
||||
});
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
const mapStateToProps = state => {
|
||||
const me = state.get('me');
|
||||
const account = getAccount(state, me);
|
||||
|
||||
return {
|
||||
aliases: account.getIn(['pleroma', 'also_known_as']),
|
||||
searchAccountIds: state.getIn(['aliases', 'suggestions', 'items']),
|
||||
loaded: state.getIn(['aliases', 'suggestions', 'loaded']),
|
||||
};
|
||||
};
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export default @connect(makeMapStateToProps)
|
||||
@injectIntl
|
||||
class Aliases extends ImmutablePureComponent {
|
||||
|
||||
|
@ -78,4 +90,4 @@ class Aliases extends ImmutablePureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ export default class TextIconButton extends React.PureComponent {
|
|||
active: PropTypes.bool,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
ariaControls: PropTypes.string,
|
||||
unavailable: PropTypes.bool,
|
||||
};
|
||||
|
||||
handleClick = (e) => {
|
||||
|
@ -17,7 +18,11 @@ export default class TextIconButton extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { label, title, active, ariaControls } = this.props;
|
||||
const { label, title, active, ariaControls, unavailable } = this.props;
|
||||
|
||||
if (unavailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button title={title} aria-label={title} className={`text-icon-button ${active ? 'active' : ''}`} aria-expanded={active} onClick={this.handleClick} aria-controls={ariaControls}>
|
||||
|
|
|
@ -2,18 +2,25 @@ import { connect } from 'react-redux';
|
|||
import TextIconButton from '../components/text_icon_button';
|
||||
import { changeComposeContentType } from '../../../actions/compose';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const messages = defineMessages({
|
||||
marked: { id: 'compose_form.markdown.marked', defaultMessage: 'Post markdown enabled' },
|
||||
unmarked: { id: 'compose_form.markdown.unmarked', defaultMessage: 'Post markdown disabled' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, { intl }) => ({
|
||||
label: 'MD',
|
||||
title: intl.formatMessage(state.getIn(['compose', 'content_type']) === 'text/markdown' ? messages.marked : messages.unmarked),
|
||||
active: state.getIn(['compose', 'content_type']) === 'text/markdown',
|
||||
ariaControls: 'markdown-input',
|
||||
});
|
||||
const mapStateToProps = (state, { intl }) => {
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
return {
|
||||
label: 'MD',
|
||||
title: intl.formatMessage(state.getIn(['compose', 'content_type']) === 'text/markdown' ? messages.marked : messages.unmarked),
|
||||
active: state.getIn(['compose', 'content_type']) === 'text/markdown',
|
||||
ariaControls: 'markdown-input',
|
||||
unavailable: !features.richText,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { unescape } from 'lodash';
|
|||
import { isVerified } from 'soapbox/utils/accounts';
|
||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
import { makeGetAccount } from 'soapbox/selectors';
|
||||
|
||||
const hidesNetwork = account => {
|
||||
const pleroma = account.get('pleroma');
|
||||
|
@ -41,19 +42,27 @@ const messages = defineMessages({
|
|||
metaFieldContent: { id: 'edit_profile.fields.meta_fields.content_placeholder', defaultMessage: 'Content' },
|
||||
verified: { id: 'edit_profile.fields.verified_display_name', defaultMessage: 'Verified users may not update their display name' },
|
||||
success: { id: 'edit_profile.success', defaultMessage: 'Profile saved!' },
|
||||
bioPlaceholder: { id: 'edit_profile.fields.bio_placeholder', defaultMessage: 'Tell us about yourself.' },
|
||||
displayNamePlaceholder: { id: 'edit_profile.fields.display_name_placeholder', defaultMessage: 'Name' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const me = state.get('me');
|
||||
const soapbox = getSoapboxConfig(state);
|
||||
const meta = state.getIn(['meta', 'pleroma']);
|
||||
const account = state.getIn(['accounts', me]).set('pleroma', meta);
|
||||
return {
|
||||
account,
|
||||
maxFields: state.getIn(['instance', 'pleroma', 'metadata', 'fields_limits', 'max_fields'], 4),
|
||||
verifiedCanEditName: soapbox.get('verifiedCanEditName'),
|
||||
supportsEmailList: getFeatures(state.get('instance')).emailList,
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const me = state.get('me');
|
||||
const account = getAccount(state, me);
|
||||
const soapbox = getSoapboxConfig(state);
|
||||
|
||||
return {
|
||||
account,
|
||||
maxFields: state.getIn(['instance', 'pleroma', 'metadata', 'fields_limits', 'max_fields'], 4),
|
||||
verifiedCanEditName: soapbox.get('verifiedCanEditName'),
|
||||
supportsEmailList: getFeatures(state.get('instance')).emailList,
|
||||
};
|
||||
};
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
// Forces fields to be maxFields size, filling empty values
|
||||
|
@ -70,7 +79,7 @@ const unescapeParams = (map, params) => (
|
|||
), map)
|
||||
);
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
export default @connect(makeMapStateToProps)
|
||||
@injectIntl
|
||||
class EditProfile extends ImmutablePureComponent {
|
||||
|
||||
|
@ -88,18 +97,21 @@ class EditProfile extends ImmutablePureComponent {
|
|||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { account } = this.props;
|
||||
const { account, maxFields } = this.props;
|
||||
|
||||
const strangerNotifications = account.getIn(['pleroma', 'notification_settings', 'block_from_strangers']);
|
||||
const acceptsEmailList = account.getIn(['pleroma', 'accepts_email_list']);
|
||||
|
||||
const initialState = account.withMutations(map => {
|
||||
map.merge(map.get('source'));
|
||||
map.delete('source');
|
||||
map.set('fields', normalizeFields(map.get('fields'), Math.min(props.maxFields, 4)));
|
||||
map.set('fields', normalizeFields(map.get('fields'), Math.min(maxFields, 4)));
|
||||
map.set('stranger_notifications', strangerNotifications);
|
||||
map.set('accepts_email_list', acceptsEmailList);
|
||||
map.set('hide_network', hidesNetwork(account));
|
||||
unescapeParams(map, ['display_name', 'bio']);
|
||||
});
|
||||
|
||||
this.state = initialState.toObject();
|
||||
}
|
||||
|
||||
|
@ -108,7 +120,7 @@ class EditProfile extends ImmutablePureComponent {
|
|||
return account.merge(ImmutableMap({
|
||||
header: this.state.header,
|
||||
avatar: this.state.avatar,
|
||||
display_name: this.state.display_name,
|
||||
display_name: this.state.display_name || account.get('username'),
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -225,6 +237,7 @@ class EditProfile extends ImmutablePureComponent {
|
|||
<TextInput
|
||||
className={canEditName ? '' : 'disabled'}
|
||||
label={<FormattedMessage id='edit_profile.fields.display_name_label' defaultMessage='Display name' />}
|
||||
placeholder={intl.formatMessage(messages.displayNamePlaceholder)}
|
||||
name='display_name'
|
||||
value={this.state.display_name}
|
||||
onChange={this.handleTextChange}
|
||||
|
@ -233,6 +246,7 @@ class EditProfile extends ImmutablePureComponent {
|
|||
/>
|
||||
<SimpleTextarea
|
||||
label={<FormattedMessage id='edit_profile.fields.bio_label' defaultMessage='Bio' />}
|
||||
placeholder={intl.formatMessage(messages.bioPlaceholder)}
|
||||
name='note'
|
||||
autoComplete='off'
|
||||
value={this.state.note}
|
||||
|
|
|
@ -13,6 +13,7 @@ export default class ColumnSettings extends React.PureComponent {
|
|||
pushSettings: ImmutablePropTypes.map.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onClear: PropTypes.func.isRequired,
|
||||
supportsEmojiReacts: PropTypes.bool,
|
||||
};
|
||||
|
||||
onPushChange = (path, checked) => {
|
||||
|
@ -28,7 +29,7 @@ export default class ColumnSettings extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { settings, pushSettings, onChange, onClear } = this.props;
|
||||
const { settings, pushSettings, onChange, onClear, supportsEmojiReacts } = this.props;
|
||||
|
||||
const filterShowStr = <FormattedMessage id='notifications.column_settings.filter_bar.show' defaultMessage='Show' />;
|
||||
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
|
||||
|
@ -96,7 +97,7 @@ export default class ColumnSettings extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div role='group' aria-labelledby='notifications-emoji-react'>
|
||||
{supportsEmojiReacts && <div role='group' aria-labelledby='notifications-emoji-react'>
|
||||
<span id='notifications-favourite' className='column-settings__section'><FormattedMessage id='notifications.column_settings.emoji_react' defaultMessage='Emoji reacts:' /></span>
|
||||
|
||||
<div className='column-settings__row'>
|
||||
|
@ -105,7 +106,7 @@ export default class ColumnSettings extends React.PureComponent {
|
|||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'pleroma:emoji_reaction']} onChange={onChange} label={showStr} />
|
||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'pleroma:emoji_reaction']} onChange={onChange} label={soundStr} />
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
<div role='group' aria-labelledby='notifications-mention'>
|
||||
<span id='notifications-mention' className='column-settings__section'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span>
|
||||
|
|
|
@ -20,6 +20,7 @@ class FilterBar extends React.PureComponent {
|
|||
selectFilter: PropTypes.func.isRequired,
|
||||
selectedFilter: PropTypes.string.isRequired,
|
||||
advancedMode: PropTypes.bool.isRequired,
|
||||
supportsEmojiReacts: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
@ -28,7 +29,7 @@ class FilterBar extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { selectedFilter, advancedMode, intl } = this.props;
|
||||
const { selectedFilter, advancedMode, supportsEmojiReacts, intl } = this.props;
|
||||
const renderedElement = !advancedMode ? (
|
||||
<div className='notification__filter-bar'>
|
||||
<button
|
||||
|
@ -75,13 +76,13 @@ class FilterBar extends React.PureComponent {
|
|||
>
|
||||
<Icon id='thumbs-up' fixedWidth />
|
||||
</button>
|
||||
<button
|
||||
{supportsEmojiReacts && <button
|
||||
className={selectedFilter === 'pleroma:emoji_reaction' ? 'active' : ''}
|
||||
onClick={this.onClick('pleroma:emoji_reaction')}
|
||||
title={intl.formatMessage(tooltips.emoji_reacts)}
|
||||
>
|
||||
<Icon id='smile-o' fixedWidth />
|
||||
</button>
|
||||
</button>}
|
||||
<button
|
||||
className={selectedFilter === 'reblog' ? 'active' : ''}
|
||||
onClick={this.onClick('reblog')}
|
||||
|
|
|
@ -6,16 +6,23 @@ import { setFilter } from '../../../actions/notifications';
|
|||
import { clearNotifications } from '../../../actions/notifications';
|
||||
import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications';
|
||||
import { openModal } from '../../../actions/modal';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const messages = defineMessages({
|
||||
clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' },
|
||||
clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
settings: getSettings(state).get('notifications'),
|
||||
pushSettings: state.get('push_notifications'),
|
||||
});
|
||||
const mapStateToProps = state => {
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
return {
|
||||
settings: getSettings(state).get('notifications'),
|
||||
pushSettings: state.get('push_notifications'),
|
||||
supportsEmojiReacts: features.emojiReacts,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||
|
||||
|
|
|
@ -2,12 +2,17 @@ import { connect } from 'react-redux';
|
|||
import FilterBar from '../components/filter_bar';
|
||||
import { setFilter } from '../../../actions/notifications';
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
const makeMapStateToProps = state => {
|
||||
const settings = getSettings(state);
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
return {
|
||||
selectedFilter: settings.getIn(['notifications', 'quickFilter', 'active']),
|
||||
advancedMode: settings.getIn(['notifications', 'quickFilter', 'advanced']),
|
||||
supportsEmojiReacts: features.emojiReacts,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ import IconWithCounter from 'soapbox/components/icon_with_counter';
|
|||
import { NavLink } from 'react-router-dom';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
import { getBaseURL } from 'soapbox/utils/accounts';
|
||||
|
||||
const messages = defineMessages({
|
||||
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit Profile' },
|
||||
|
@ -18,9 +20,16 @@ const messages = defineMessages({
|
|||
|
||||
const mapStateToProps = state => {
|
||||
const me = state.get('me');
|
||||
const account = state.getIn(['accounts', me]);
|
||||
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
return {
|
||||
isLocked: state.getIn(['accounts', me, 'locked']),
|
||||
followRequestsCount: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableOrderedSet()).count(),
|
||||
baseURL: getBaseURL(account),
|
||||
features,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -32,10 +41,12 @@ class FeaturesPanel extends React.PureComponent {
|
|||
intl: PropTypes.object.isRequired,
|
||||
isLocked: PropTypes.bool,
|
||||
followRequestsCount: PropTypes.number,
|
||||
baseURL: PropTypes.string,
|
||||
features: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { intl, isLocked, followRequestsCount } = this.props;
|
||||
const { intl, isLocked, followRequestsCount, baseURL, features } = this.props;
|
||||
|
||||
return (
|
||||
<div className='wtf-panel promo-panel'>
|
||||
|
@ -61,15 +72,29 @@ class FeaturesPanel extends React.PureComponent {
|
|||
{intl.formatMessage(messages.lists)}
|
||||
</NavLink>
|
||||
|
||||
<NavLink className='promo-panel-item' to='/auth/edit'>
|
||||
<Icon id='lock' className='promo-panel-item__icon' fixedWidth />
|
||||
{intl.formatMessage(messages.security)}
|
||||
</NavLink>
|
||||
{features.securityAPI ? (
|
||||
<NavLink className='promo-panel-item' to='/auth/edit'>
|
||||
<Icon id='lock' className='promo-panel-item__icon' fixedWidth />
|
||||
{intl.formatMessage(messages.security)}
|
||||
</NavLink>
|
||||
) : (
|
||||
<a className='promo-panel-item' href={`${baseURL}/auth/edit`}>
|
||||
<Icon id='lock' className='promo-panel-item__icon' fixedWidth />
|
||||
{intl.formatMessage(messages.security)}
|
||||
</a>
|
||||
)}
|
||||
|
||||
<NavLink className='promo-panel-item' to='/settings/preferences'>
|
||||
<Icon id='cog' className='promo-panel-item__icon' fixedWidth />
|
||||
{intl.formatMessage(messages.preferences)}
|
||||
</NavLink>
|
||||
{features.settingsStore ? (
|
||||
<NavLink className='promo-panel-item' to='/settings/preferences'>
|
||||
<Icon id='cog' className='promo-panel-item__icon' fixedWidth />
|
||||
{intl.formatMessage(messages.preferences)}
|
||||
</NavLink>
|
||||
) : (
|
||||
<a className='promo-panel-item' href={`${baseURL}/settings/preferences`}>
|
||||
<Icon id='cog' className='promo-panel-item__icon' fixedWidth />
|
||||
{intl.formatMessage(messages.preferences)}
|
||||
</a>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,6 +18,7 @@ const mapStateToProps = state => {
|
|||
return {
|
||||
account: state.getIn(['accounts', me]),
|
||||
federating: features.federating,
|
||||
showAliases: features.accountAliasesAPI,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -31,7 +32,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const LinkFooter = ({ onOpenHotkeys, account, federating, onClickLogOut }) => (
|
||||
const LinkFooter = ({ onOpenHotkeys, account, federating, showAliases, onClickLogOut }) => (
|
||||
<div className='getting-started__footer'>
|
||||
<ul>
|
||||
{account && <>
|
||||
|
@ -43,7 +44,7 @@ const LinkFooter = ({ onOpenHotkeys, account, federating, onClickLogOut }) => (
|
|||
{isAdmin(account) && <li><a href='/pleroma/admin'><FormattedMessage id='navigation_bar.admin_settings' defaultMessage='AdminFE' /></a></li>}
|
||||
{isAdmin(account) && <li><Link to='/soapbox/config'><FormattedMessage id='navigation_bar.soapbox_config' defaultMessage='Soapbox config' /></Link></li>}
|
||||
<li><Link to='/settings/import'><FormattedMessage id='navigation_bar.import_data' defaultMessage='Import data' /></Link></li>
|
||||
{federating && <li><Link to='/settings/aliases'><FormattedMessage id='navigation_bar.account_aliases' defaultMessage='Account aliases' /></Link></li>}
|
||||
{(federating && showAliases) && <li><Link to='/settings/aliases'><FormattedMessage id='navigation_bar.account_aliases' defaultMessage='Account aliases' /></Link></li>}
|
||||
<li><a href='#' onClick={onOpenHotkeys}><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></a></li>
|
||||
</>}
|
||||
<li><Link to='/about'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></Link></li>
|
||||
|
@ -67,6 +68,7 @@ const LinkFooter = ({ onOpenHotkeys, account, federating, onClickLogOut }) => (
|
|||
LinkFooter.propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
federating: PropTypes.bool,
|
||||
showAliases: PropTypes.bool,
|
||||
onOpenHotkeys: PropTypes.func.isRequired,
|
||||
onClickLogOut: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@ const normalizeAccount = (state, account) => {
|
|||
'followers_count',
|
||||
'following_count',
|
||||
'statuses_count',
|
||||
'source',
|
||||
]);
|
||||
|
||||
return state.set(account.id, normalized);
|
||||
|
|
28
app/soapbox/reducers/accounts_meta.js
Normal file
28
app/soapbox/reducers/accounts_meta.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Accounts Meta: private user data only the owner should see.
|
||||
* @module soapbox/reducers/accounts_meta
|
||||
*/
|
||||
|
||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
const importAccount = (state, account) => {
|
||||
const accountId = account.get('id');
|
||||
|
||||
return state.set(accountId, ImmutableMap({
|
||||
pleroma: account.get('pleroma', ImmutableMap()).delete('settings_store'),
|
||||
source: account.get('source', ImmutableMap()),
|
||||
}));
|
||||
};
|
||||
|
||||
export default function accounts_meta(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case ME_FETCH_SUCCESS:
|
||||
case ME_PATCH_SUCCESS:
|
||||
return importAccount(state, fromJS(action.me));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ import admin_log from './admin_log';
|
|||
import security from './security';
|
||||
import scheduled_statuses from './scheduled_statuses';
|
||||
import aliases from './aliases';
|
||||
import accounts_meta from './accounts_meta';
|
||||
|
||||
const appReducer = combineReducers({
|
||||
dropdown_menu,
|
||||
|
@ -109,6 +110,7 @@ const appReducer = combineReducers({
|
|||
security,
|
||||
scheduled_statuses,
|
||||
aliases,
|
||||
accounts_meta,
|
||||
});
|
||||
|
||||
// Clear the state (mostly) when the user logs out
|
||||
|
|
|
@ -1,25 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from 'soapbox/actions/me';
|
||||
import { INSTANCE_FETCH_FAIL } from 'soapbox/actions/instance';
|
||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||
import { Map as ImmutableMap } from 'immutable';
|
||||
|
||||
const initialState = ImmutableMap();
|
||||
|
||||
const importAccount = (state, account) => {
|
||||
return state.withMutations(state => {
|
||||
if (account.has('pleroma')) {
|
||||
const pleroPrefs = account.get('pleroma').delete('settings_store');
|
||||
state.mergeIn(['pleroma'], pleroPrefs);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default function meta(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case ME_FETCH_SUCCESS:
|
||||
case ME_PATCH_SUCCESS:
|
||||
return importAccount(state, fromJS(action.me));
|
||||
case INSTANCE_FETCH_FAIL:
|
||||
return state.set('instance_fetch_failed', true);
|
||||
default:
|
||||
|
|
|
@ -14,6 +14,7 @@ const getAccountBase = (state, id) => state.getIn(['accounts', id], null
|
|||
const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
|
||||
const getAccountRelationship = (state, id) => state.getIn(['relationships', id], null);
|
||||
const getAccountMoved = (state, id) => state.getIn(['accounts', state.getIn(['accounts', id, 'moved'])]);
|
||||
const getAccountMeta = (state, id) => state.getIn(['accounts_meta', id], ImmutableMap());
|
||||
const getAccountAdminData = (state, id) => state.getIn(['admin', 'users', id]);
|
||||
const getAccountPatron = (state, id) => {
|
||||
const url = state.getIn(['accounts', id, 'url']);
|
||||
|
@ -26,14 +27,18 @@ export const makeGetAccount = () => {
|
|||
getAccountCounters,
|
||||
getAccountRelationship,
|
||||
getAccountMoved,
|
||||
getAccountMeta,
|
||||
getAccountAdminData,
|
||||
getAccountPatron,
|
||||
], (base, counters, relationship, moved, admin, patron) => {
|
||||
], (base, counters, relationship, moved, meta, admin, patron) => {
|
||||
if (base === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return base.merge(counters).withMutations(map => {
|
||||
return base.withMutations(map => {
|
||||
map.merge(counters);
|
||||
map.merge(meta);
|
||||
map.set('pleroma', meta.get('pleroma', ImmutableMap()).merge(base.get('pleroma', ImmutableMap()))); // Lol, thanks Pleroma
|
||||
map.set('relationship', relationship);
|
||||
map.set('moved', moved);
|
||||
map.set('patron', patron);
|
||||
|
|
|
@ -21,6 +21,15 @@ export const guessFqn = account => {
|
|||
return account.get('acct');
|
||||
};
|
||||
|
||||
export const getBaseURL = account => {
|
||||
try {
|
||||
const url = account.get('url');
|
||||
return new URL(url).origin;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
// user@domain even for local users
|
||||
export const acctFull = account => (
|
||||
account.get('fqn') || guessFqn(account)
|
||||
|
|
|
@ -20,6 +20,10 @@ export const getFeatures = createSelector([
|
|||
chats: v.software === 'Pleroma' && gte(v.version, '2.1.0'),
|
||||
scopes: v.software === 'Pleroma' ? 'read write follow push admin' : 'read write follow push',
|
||||
federating: federation.get('enabled', true), // Assume true unless explicitly false
|
||||
richText: v.software === 'Pleroma',
|
||||
securityAPI: v.software === 'Pleroma',
|
||||
settingsStore: v.software === 'Pleroma',
|
||||
accountAliasesAPI: v.software === 'Pleroma',
|
||||
};
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue