Permalink
Browse files

Added App Setttings Modal

  • Loading branch information...
marrus-sh committed Jun 29, 2017
1 parent 6cbbdc8 commit 595c6de32c052f2a5e21307a0e43a6bd5d4b5c88
@@ -14,7 +14,7 @@ export function changeLocalSetting(key, value) {
export function saveLocalSettings() {
return (_, getState) => {
const localSettings = getState().get('localSettings').toJS();
const localSettings = getState().get('local_settings').toJS();
localStorage.setItem('mastodon-settings', JSON.stringify(localSettings));
};
};
@@ -25,6 +25,7 @@ export default class StatusOrReblog extends ImmutablePureComponent {
static propTypes = {
status: ImmutablePropTypes.map,
account: ImmutablePropTypes.map,
settings: ImmutablePropTypes.map,
wrapped: PropTypes.bool,
onReply: PropTypes.func,
onFavourite: PropTypes.func,
@@ -47,6 +48,7 @@ export default class StatusOrReblog extends ImmutablePureComponent {
updateOnProps = [
'status',
'account',
'settings',
'wrapped',
'me',
'boostModal',
@@ -97,6 +99,7 @@ class Status extends ImmutablePureComponent {
static propTypes = {
status: ImmutablePropTypes.map,
account: ImmutablePropTypes.map,
settings: ImmutablePropTypes.map,
wrapped: PropTypes.bool,
onReply: PropTypes.func,
onFavourite: PropTypes.func,
@@ -126,6 +129,7 @@ class Status extends ImmutablePureComponent {
updateOnProps = [
'status',
'account',
'settings',
'wrapped',
'me',
'boostModal',
@@ -140,7 +144,8 @@ class Status extends ImmutablePureComponent {
]
componentWillReceiveProps (nextProps) {
if (nextProps.collapse !== this.props.collapse && nextProps.collapse !== undefined) this.setState({ isCollapsed: !!nextProps.collapse });
if (!nextProps.settings.getIn(['collapsed', 'enabled'])) this.collapse(false);
else if (nextProps.collapse !== this.props.collapse && nextProps.collapse !== undefined) this.collapse(this.props.collapse);
}
shouldComponentUpdate (nextProps, nextState) {
@@ -165,8 +170,13 @@ class Status extends ImmutablePureComponent {
componentDidMount () {
const node = this.node;
if (this.props.collapse !== undefined) this.setState({ isCollapsed: !!this.props.collapse });
else if (node.clientHeight > 400) this.setState({ isCollapsed: true });
const { collapse, settings, status } = this.props;
if (collapse !== undefined) this.collapse(collapse);
else if (settings.getIn(['collapsed', 'auto', 'all'])) this.collapse();
else if (settings.getIn(['collapsed', 'auto', 'lengthy']) && node.clientHeight > 400) this.collapse();
else if (settings.getIn(['collapsed', 'auto', 'replies']) && status.get('in_reply_to_id', null) !== null) this.collapse();
else if (settings.getIn(['collapsed', 'auto', 'media']) && status.get('media_attachments').size > 0) this.collapse();
if (!this.props.intersectionObserverWrapper) {
// TODO: enable IntersectionObserver optimization for notification statuses.
@@ -186,6 +196,11 @@ class Status extends ImmutablePureComponent {
this.componentMounted = false;
}
collapse = (collapsedOrNot) => {
if (collapsedOrNot === undefined) collapsedOrNot = true;
if (this.props.settings.getIn(['collapsed', 'enabled'])) this.setState({ isCollapsed: !!collapsedOrNot });
}
handleIntersection = (entry) => {
// Edge 15 doesn't support isIntersecting, but we can infer it
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12156111/
@@ -247,20 +262,23 @@ class Status extends ImmutablePureComponent {
};
handleCollapsedClick = () => {
this.setState({ isCollapsed: !this.state.isCollapsed, isExpanded: false });
this.collapse(!this.state.isCollapsed);
this.setState({ isExpanded: false });
}
render () {
let media = null;
let mediaType = null;
let thumb = null;
let statusAvatar;
// Exclude intersectionObserverWrapper from `other` variable
// because intersection is managed in here.
const { status, account, intersectionObserverWrapper, intl, ...other } = this.props;
const { status, account, settings, intersectionObserverWrapper, intl, ...other } = this.props;
const { isExpanded, isIntersecting, isHidden, isCollapsed } = this.state;
let background = settings.getIn(['collapsed', 'backgrounds', 'user_backgrounds']) ? status.getIn(['account', 'header']) : null;
if (status === null) {
return null;
}
@@ -280,12 +298,12 @@ class Status extends ImmutablePureComponent {
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
media = <VideoPlayer media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />;
mediaType = <i className='fa fa-fw fa-video-camera' aria-hidden='true' />;
if (!status.get('sensitive') && !(status.get('spoiler_text').length > 0)) thumb = status.getIn(['media_attachments', 0]).get('preview_url');
} else {
media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />;
mediaType = status.get('media_attachments').size > 1 ? <i className='fa fa-fw fa-th-large' aria-hidden='true' /> : <i className='fa fa-fw fa-picture-o' aria-hidden='true' />;
if (!status.get('sensitive') && !(status.get('spoiler_text').length > 0)) thumb = status.getIn(['media_attachments', 0]).get('preview_url');
}
if (!status.get('sensitive') && !(status.get('spoiler_text').length > 0) && settings.getIn(['collapsed', 'backgrounds', 'preview_images'])) background = status.getIn(['media_attachments', 0]).get('preview_url');
}
if (account === undefined || account === null) {
@@ -295,19 +313,19 @@ class Status extends ImmutablePureComponent {
}
return (
<div className={`status ${this.props.muted ? 'muted' : ''} status-${status.get('visibility')} ${isCollapsed ? 'status-collapsed' : ''}`} data-id={status.get('id')} ref={this.handleRef} style={{ backgroundImage: thumb && isCollapsed ? 'url(' + thumb + ')' : 'none' }}>
<div className={`status ${this.props.muted ? 'muted' : ''} status-${status.get('visibility')} ${isCollapsed ? 'status-collapsed' : ''}`} data-id={status.get('id')} ref={this.handleRef} style={{ backgroundImage: background && isCollapsed ? 'url(' + background + ')' : 'none' }}>
<div className='status__info'>
<div className='status__info__icons'>
{mediaType}
<IconButton
{settings.getIn(['collapsed', 'enabled']) ? <IconButton
className='status__collapse-button'
animate flip
active={isCollapsed}
title={isCollapsed ? intl.formatMessage(messages.uncollapse) : intl.formatMessage(messages.collapse)}
icon='angle-double-up'
onClick={this.handleCollapsedClick}
/>
/> : null}
</div>
<a onClick={this.handleAccountClick} data-id={status.getIn(['account', 'id'])} href={status.getIn(['account', 'url'])} className='status__display-name'>
@@ -25,9 +25,9 @@ addLocaleData(localeData);
const store = configureStore();
const initialState = JSON.parse(document.getElementById('initial-state').textContent);
try {
initialState.localSettings = JSON.parse(localStorage.getItem('mastodon-settings'));
initialState.local_settings = JSON.parse(localStorage.getItem('mastodon-settings'));
} catch (e) {
initialState.localSettings = {};
initialState.local_settings = {};
}
store.dispatch(hydrateStore(initialState));
@@ -34,6 +34,7 @@ const makeMapStateToProps = () => {
const mapStateToProps = (state, props) => ({
status: getStatus(state, props.id),
me: state.getIn(['meta', 'me']),
settings: state.get('local_settings'),
boostModal: state.getIn(['meta', 'boost_modal']),
deleteModal: state.getIn(['meta', 'delete_modal']),
autoPlayGif: state.getIn(['meta', 'auto_play_gif']),
@@ -4,6 +4,7 @@ import NavigationContainer from './containers/navigation_container';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { mountCompose, unmountCompose } from '../../actions/compose';
import { openModal } from '../../actions/modal';
import { changeLocalSetting } from '../../actions/local_settings';
import Link from 'react-router-dom/Link';
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
@@ -16,13 +17,13 @@ const messages = defineMessages({
start: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' },
community: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
settings: { id: 'navigation_bar.app_settings', defaultMessage: 'App settings' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
});
const mapStateToProps = state => ({
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
layout: state.getIn(['localSettings', 'layout']),
layout: state.getIn(['local_settings', 'layout']),
});
@connect(mapStateToProps)
@@ -51,6 +52,10 @@ export default class Compose extends React.PureComponent {
e.preventDefault();
}
openSettings = () => {
this.props.dispatch(openModal('SETTINGS', {}));
}
render () {
const { multiColumn, showSearch, intl, layout } = this.props;
@@ -62,7 +67,7 @@ export default class Compose extends React.PureComponent {
<Link to='/getting-started' className='drawer__tab' title={intl.formatMessage(messages.start)}><i role='img' aria-label={intl.formatMessage(messages.start)} className='fa fa-fw fa-asterisk' /></Link>
<Link to='/timelines/public/local' className='drawer__tab' title={intl.formatMessage(messages.community)}><i role='img' aria-label={intl.formatMessage(messages.community)} className='fa fa-fw fa-users' /></Link>
<Link to='/timelines/public' className='drawer__tab' title={intl.formatMessage(messages.public)}><i role='img' aria-label={intl.formatMessage(messages.public)} className='fa fa-fw fa-globe' /></Link>
<a href='/settings/preferences' className='drawer__tab' title={intl.formatMessage(messages.preferences)}><i role='img' aria-label={intl.formatMessage(messages.preferences)} className='fa fa-fw fa-cog' /></a>
<a onClick={this.openSettings} role='button' tabIndex='0' className='drawer__tab' title={intl.formatMessage(messages.settings)}><i role='img' aria-label={intl.formatMessage(messages.settings)} className='fa fa-fw fa-cogs' /></a>
<a href='/auth/sign_out' className='drawer__tab' data-method='delete' title={intl.formatMessage(messages.logout)}><i role='img' aria-label={intl.formatMessage(messages.logout)} className='fa fa-fw fa-sign-out' /></a>
</div>
);
@@ -4,6 +4,7 @@ import ColumnLink from '../ui/components/column_link';
import ColumnSubheading from '../ui/components/column_subheading';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { openModal } from '../../actions/modal';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -17,6 +18,7 @@ const messages = defineMessages({
settings_subheading: { id: 'column_subheading.settings', defaultMessage: 'Settings' },
community_timeline: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
settings: { id: 'navigation_bar.app_settings', defaultMessage: 'App settings' },
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' },
@@ -39,8 +41,13 @@ export default class GettingStarted extends ImmutablePureComponent {
me: ImmutablePropTypes.map.isRequired,
columns: ImmutablePropTypes.list,
multiColumn: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
};
openSettings = () => {
this.props.dispatch(openModal('SETTINGS', {}));
}
render () {
const { intl, me, columns, multiColumn } = this.props;
@@ -79,27 +86,30 @@ export default class GettingStarted extends ImmutablePureComponent {
return (
<Column icon='asterisk' heading={intl.formatMessage(messages.heading)} hideHeadingOnMobile>
<div className='getting-started__wrapper'>
<ColumnSubheading text={intl.formatMessage(messages.navigation_subheading)} />
{navItems}
<ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} />
<ColumnLink icon='book' text={intl.formatMessage(messages.info)} href='/about/more' />
<ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />
<ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
</div>
<div className='scrollable optionally-scrollable'>
<div className='getting-started__wrapper'>
<ColumnSubheading text={intl.formatMessage(messages.navigation_subheading)} />
{navItems}
<ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} />
<ColumnLink icon='book' text={intl.formatMessage(messages.info)} href='/about/more' />
<ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />
<ColumnLink icon='cogs' text={intl.formatMessage(messages.settings)} onClick={this.openSettings} />
<ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
</div>
<div className='getting-started__footer scrollable optionally-scrollable'>
<div className='static-content getting-started'>
<p>
<a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/FAQ.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.faq' defaultMessage='FAQ' /></a><a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/User-guide.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.userguide' defaultMessage='User Guide' /></a><a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.appsshort' defaultMessage='Apps' /></a>
</p>
<p>
<FormattedMessage
id='getting_started.open_source_notice'
defaultMessage='Glitchsoc is open source software, a friendly fork of {Mastodon}. You can contribute or report issues on GitHub at {github}.'
values={{ github: <a href='https://github.com/glitch-soc/mastodon' rel='noopener' target='_blank'>glitch-soc/mastodon</a>, Mastodon: <a href='https://github.com/tootsuite/mastodon' rel='noopener' target='_blank'>Mastodon</a> }}
/>
</p>
<div className='getting-started__footer'>
<div className='static-content getting-started'>
<p>
<a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/FAQ.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.faq' defaultMessage='FAQ' /></a><a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/User-guide.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.userguide' defaultMessage='User Guide' /></a><a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md' rel='noopener' target='_blank'><FormattedMessage id='getting_started.appsshort' defaultMessage='Apps' /></a>
</p>
<p>
<FormattedMessage
id='getting_started.open_source_notice'
defaultMessage='Glitchsoc is open source software, a friendly fork of {Mastodon}. You can contribute or report issues on GitHub at {github}.'
values={{ github: <a href='https://github.com/glitch-soc/mastodon' rel='noopener' target='_blank'>glitch-soc/mastodon</a>, Mastodon: <a href='https://github.com/tootsuite/mastodon' rel='noopener' target='_blank'>Mastodon</a> }}
/>
</p>
</div>
</div>
</div>
</Column>
@@ -12,6 +12,7 @@ export default class Notification extends ImmutablePureComponent {
static propTypes = {
notification: ImmutablePropTypes.map.isRequired,
settings: ImmutablePropTypes.map.isRequired,
};
renderFollow (account, link) {
@@ -34,7 +35,7 @@ export default class Notification extends ImmutablePureComponent {
return <StatusContainer id={notification.get('status')} withDismiss />;
}
renderFavourite (notification, link) {
renderFavourite (notification, settings, link) {
return (
<div className='notification notification-favourite'>
<div className='notification__message'>
@@ -44,12 +45,12 @@ export default class Notification extends ImmutablePureComponent {
<FormattedMessage id='notification.favourite' defaultMessage='{name} favourited your status' values={{ name: link }} />
</div>
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted collapse withDismiss />
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted collapse={settings.getIn(['collapsed', 'auto', 'notifications'])} withDismiss />
</div>
);
}
renderReblog (notification, link) {
renderReblog (notification, settings, link) {
return (
<div className='notification notification-reblog'>
<div className='notification__message'>
@@ -59,13 +60,13 @@ export default class Notification extends ImmutablePureComponent {
<FormattedMessage id='notification.reblog' defaultMessage='{name} boosted your status' values={{ name: link }} />
</div>
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted collapse withDismiss />
<StatusContainer id={notification.get('status')} account={notification.get('account')} muted collapse={settings.getIn(['collapsed', 'auto', 'notifications'])} withDismiss />
</div>
);
}
render () {
const { notification } = this.props;
const { notification, settings } = this.props;
const account = notification.get('account');
const displayName = account.get('display_name').length > 0 ? account.get('display_name') : account.get('username');
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
@@ -77,9 +78,9 @@ export default class Notification extends ImmutablePureComponent {
case 'mention':
return this.renderMention(notification);
case 'favourite':
return this.renderFavourite(notification, link);
return this.renderFavourite(notification, settings, link);
case 'reblog':
return this.renderReblog(notification, link);
return this.renderReblog(notification, settings, link);
}
return null;
@@ -7,6 +7,7 @@ const makeMapStateToProps = () => {
const mapStateToProps = (state, props) => ({
notification: getNotification(state, props.notification, props.accountId),
settings: state.get('local_settings'),
});
return mapStateToProps;
Oops, something went wrong.

0 comments on commit 595c6de

Please sign in to comment.