mirror of https://github.com/Siphonay/mastodon
Added App Setttings Modal
This commit is contained in:
parent
6cbbdc805f
commit
595c6de32c
|
@ -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;
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import Link from 'react-router-dom/Link';
|
||||
|
||||
const ColumnLink = ({ icon, text, to, href, method, hideOnMobile }) => {
|
||||
const ColumnLink = ({ icon, text, to, onClick, href, method, hideOnMobile }) => {
|
||||
if (href) {
|
||||
return (
|
||||
<a href={href} className={`column-link ${hideOnMobile ? 'hidden-on-mobile' : ''}`} data-method={method}>
|
||||
|
@ -10,13 +10,20 @@ const ColumnLink = ({ icon, text, to, href, method, hideOnMobile }) => {
|
|||
{text}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
} else if (to) {
|
||||
return (
|
||||
<Link to={to} className={`column-link ${hideOnMobile ? 'hidden-on-mobile' : ''}`}>
|
||||
<i className={`fa fa-fw fa-${icon} column-link__icon`} />
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<a onClick={onClick} role='button' tabIndex='0' className={`column-link ${hideOnMobile ? 'hidden-on-mobile' : ''}`} data-method={method}>
|
||||
<i className={`fa fa-fw fa-${icon} column-link__icon`} />
|
||||
{text}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,6 +31,7 @@ ColumnLink.propTypes = {
|
|||
icon: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
to: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
href: PropTypes.string,
|
||||
method: PropTypes.string,
|
||||
hideOnMobile: PropTypes.bool,
|
||||
|
|
|
@ -6,6 +6,7 @@ import VideoModal from './video_modal';
|
|||
import BoostModal from './boost_modal';
|
||||
import ConfirmationModal from './confirmation_modal';
|
||||
import ReportModal from './report_modal';
|
||||
import SettingsModal from '../containers/settings_modal_container';
|
||||
import TransitionMotion from 'react-motion/lib/TransitionMotion';
|
||||
import spring from 'react-motion/lib/spring';
|
||||
|
||||
|
@ -16,6 +17,7 @@ const MODAL_COMPONENTS = {
|
|||
'BOOST': BoostModal,
|
||||
'CONFIRM': ConfirmationModal,
|
||||
'REPORT': ReportModal,
|
||||
'SETTINGS': SettingsModal,
|
||||
};
|
||||
|
||||
export default class ModalRoot extends React.PureComponent {
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
class SettingsItem extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
item: PropTypes.array.isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
dependsOn: PropTypes.array,
|
||||
dependsOnNot: PropTypes.array,
|
||||
children: PropTypes.element.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
handleChange = (e) => {
|
||||
const { item, onChange } = this.props;
|
||||
onChange(item, e);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { settings, item, id, children, dependsOn, dependsOnNot } = this.props;
|
||||
let enabled = true;
|
||||
|
||||
if (dependsOn) {
|
||||
for (let i = 0; i < dependsOn.length; i++) {
|
||||
enabled = enabled && settings.getIn(dependsOn[i]);
|
||||
}
|
||||
}
|
||||
if (dependsOnNot) {
|
||||
for (let i = 0; i < dependsOnNot.length; i++) {
|
||||
enabled = enabled && !settings.getIn(dependsOnNot[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<label htmlFor={id}>
|
||||
<input
|
||||
id={id}
|
||||
type='checkbox'
|
||||
checked={settings.getIn(item)}
|
||||
onChange={this.handleChange}
|
||||
disabled={!enabled}
|
||||
/>
|
||||
{children}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default class SettingsModal extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
toggleSetting: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
currentIndex: 0,
|
||||
};
|
||||
|
||||
General = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1><FormattedMessage id='settings.general' defaultMessage='General' /></h1>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['stretch']}
|
||||
id='mastodon-settings--stretch'
|
||||
onChange={this.props.toggleSetting}
|
||||
>
|
||||
<FormattedMessage id='settings.wide_view' defaultMessage='Wide view (Desktop mode only)' />
|
||||
</SettingsItem>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CollapsedStatuses = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1><FormattedMessage id='settings.collapsed_statuses' defaultMessage='Collapsed toots' /></h1>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'enabled']}
|
||||
id='mastodon-settings--collapsed-enabled'
|
||||
onChange={this.props.toggleSetting}
|
||||
>
|
||||
<FormattedMessage id='settings.enable_collapsed' defaultMessage='Enable collapsed toots' />
|
||||
</SettingsItem>
|
||||
<section>
|
||||
<h2><FormattedMessage id='settings.auto_collapse' defaultMessage='Automatic collapsing' /></h2>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'auto', 'all']}
|
||||
id='mastodon-settings--collapsed-auto-all'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
>
|
||||
<FormattedMessage id='settings.auto_collapse_all' defaultMessage='Everything' />
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'auto', 'notifications']}
|
||||
id='mastodon-settings--collapsed-auto-notifications'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
dependsOnNot={[['collapsed', 'auto', 'all']]}
|
||||
>
|
||||
<FormattedMessage id='settings.auto_collapse_notifications' defaultMessage='Notifications' />
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'auto', 'lengthy']}
|
||||
id='mastodon-settings--collapsed-auto-lengthy'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
dependsOnNot={[['collapsed', 'auto', 'all']]}
|
||||
>
|
||||
<FormattedMessage id='settings.auto_collapse_lengthy' defaultMessage='Lengthy toots' />
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'auto', 'replies']}
|
||||
id='mastodon-settings--collapsed-auto-replies'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
dependsOnNot={[['collapsed', 'auto', 'all']]}
|
||||
>
|
||||
<FormattedMessage id='settings.auto_collapse_replies' defaultMessage='Replies' />
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'auto', 'media']}
|
||||
id='mastodon-settings--collapsed-auto-media'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
dependsOnNot={[['collapsed', 'auto', 'all']]}
|
||||
>
|
||||
<FormattedMessage id='settings.auto_collapse_media' defaultMessage='Toots with media' />
|
||||
</SettingsItem>
|
||||
</section>
|
||||
<section>
|
||||
<h2><FormattedMessage id='settings.image_backgrounds' defaultMessage='Image backgrounds' /></h2>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'backgrounds', 'user_backgrounds']}
|
||||
id='mastodon-settings--collapsed-user-backgrouns'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
>
|
||||
<FormattedMessage id='settings.image_backgrounds_users' defaultMessage='Give collapsed toots an image background' />
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
settings={this.props.settings}
|
||||
item={['collapsed', 'backgrounds', 'preview_images']}
|
||||
id='mastodon-settings--collapsed-preview-images'
|
||||
onChange={this.props.toggleSetting}
|
||||
dependsOn={[['collapsed', 'enabled']]}
|
||||
>
|
||||
<FormattedMessage id='settings.image_backgrounds_media' defaultMessage='Preview collapsed toot media' />
|
||||
</SettingsItem>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
navigateTo = (e) =>
|
||||
this.setState({ currentIndex: +e.currentTarget.getAttribute('data-mastodon-navigation_index') });
|
||||
|
||||
render () {
|
||||
|
||||
const { General, CollapsedStatuses, navigateTo } = this;
|
||||
const { onClose } = this.props;
|
||||
const { currentIndex } = this.state;
|
||||
|
||||
return (
|
||||
<div className='modal-root__modal settings-modal'>
|
||||
|
||||
<nav className='settings-modal__navigation'>
|
||||
<a onClick={navigateTo} role='button' data-mastodon-navigation_index='0' tabIndex='0' className={`settings-modal__navigation-item${currentIndex === 0 ? ' active' : ''}`}>
|
||||
<FormattedMessage id='settings.general' defaultMessage='General' />
|
||||
</a>
|
||||
<a onClick={navigateTo} role='button' data-mastodon-navigation_index='1' tabIndex='0' className={`settings-modal__navigation-item${currentIndex === 1 ? ' active' : ''}`}>
|
||||
<FormattedMessage id='settings.collapsed_statuses' defaultMessage='Collapsed toots' />
|
||||
</a>
|
||||
<a href='/settings/preferences' className='settings-modal__navigation-item'>
|
||||
<i className='fa fa-fw fa-cogs' /> <FormattedMessage id='settings.preferences' defaultMessage='User preferences' />
|
||||
</a>
|
||||
<a onClick={onClose} role='button' tabIndex='0' className='settings-modal__navigation-close'>
|
||||
<FormattedMessage id='settings.close' defaultMessage='Close' />
|
||||
</a>
|
||||
|
||||
</nav>
|
||||
|
||||
<div className='settings-modal__content'>
|
||||
{
|
||||
[
|
||||
<General />,
|
||||
<CollapsedStatuses />,
|
||||
][currentIndex] || <General />
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { changeLocalSetting } from '../../../actions/local_settings';
|
||||
import { closeModal } from '../../../actions/modal';
|
||||
import SettingsModal from '../components/settings_modal';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
settings: state.get('local_settings'),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
toggleSetting (setting, e) {
|
||||
dispatch(changeLocalSetting(setting, e.target.checked));
|
||||
},
|
||||
onClose () {
|
||||
dispatch(closeModal());
|
||||
},
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SettingsModal);
|
|
@ -73,7 +73,8 @@ class WrappedRoute extends React.Component {
|
|||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
layout: state.getIn(['localSettings', 'layout']),
|
||||
layout: state.getIn(['local_settings', 'layout']),
|
||||
isWide: state.getIn(['local_settings', 'stretch']),
|
||||
});
|
||||
|
||||
@connect(mapStateToProps)
|
||||
|
@ -83,6 +84,7 @@ export default class UI extends React.PureComponent {
|
|||
dispatch: PropTypes.func.isRequired,
|
||||
children: PropTypes.node,
|
||||
layout: PropTypes.string,
|
||||
isWide: PropTypes.bool,
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -179,7 +181,7 @@ export default class UI extends React.PureComponent {
|
|||
|
||||
render () {
|
||||
const { width, draggingOver } = this.state;
|
||||
const { children, layout } = this.props;
|
||||
const { children, layout, isWide } = this.props;
|
||||
|
||||
const columnsClass = layout => {
|
||||
switch (layout) {
|
||||
|
@ -193,7 +195,7 @@ export default class UI extends React.PureComponent {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className={'ui ' + columnsClass(layout)} ref={this.setRef}>
|
||||
<div className={'ui ' + columnsClass(layout) + (isWide ? ' wide' : '')} ref={this.setRef}>
|
||||
<TabsBar />
|
||||
<ColumnsAreaContainer singleColumn={isMobile(width, layout)}>
|
||||
<WrappedSwitch>
|
||||
|
|
|
@ -188,10 +188,6 @@
|
|||
},
|
||||
{
|
||||
"descriptors": [
|
||||
{
|
||||
"defaultMessage": "{name} boosted",
|
||||
"id": "status.reblogged_by"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Collapse",
|
||||
"id": "status.collapse"
|
||||
|
@ -199,6 +195,10 @@
|
|||
{
|
||||
"defaultMessage": "Uncollapse",
|
||||
"id": "status.uncollapse"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "{name} boosted",
|
||||
"id": "status.reblogged_by"
|
||||
}
|
||||
],
|
||||
"path": "app/javascript/mastodon/components/status.json"
|
||||
|
@ -652,8 +652,8 @@
|
|||
"id": "navigation_bar.community_timeline"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Preferences",
|
||||
"id": "navigation_bar.preferences"
|
||||
"defaultMessage": "App settings",
|
||||
"id": "navigation_bar.app_settings"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Logout",
|
||||
|
@ -667,13 +667,13 @@
|
|||
"defaultMessage": "Mobile",
|
||||
"id": "layout.mobile"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Desktop",
|
||||
"id": "layout.desktop"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Auto",
|
||||
"id": "layout.auto"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Desktop",
|
||||
"id": "layout.desktop"
|
||||
}
|
||||
],
|
||||
"path": "app/javascript/mastodon/features/compose/index.json"
|
||||
|
@ -743,6 +743,10 @@
|
|||
"defaultMessage": "Preferences",
|
||||
"id": "navigation_bar.preferences"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "App settings",
|
||||
"id": "navigation_bar.app_settings"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Follow requests",
|
||||
"id": "navigation_bar.follow_requests"
|
||||
|
@ -1073,7 +1077,7 @@
|
|||
"id": "onboarding.page_one.welcome"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "{domain} is an 'instance' of Mastodon. Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
|
||||
"defaultMessage": "{domain} is an \"instance\" of Mastodon. Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
|
||||
"id": "onboarding.page_one.federation"
|
||||
},
|
||||
{
|
||||
|
@ -1121,7 +1125,7 @@
|
|||
"id": "onboarding.page_six.almost_done"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "{domain} runs on Glitchsoc, a friendly fork of {Mastodon}. Glitchsoc is fully compatible with any Mastodon instance or app. You can report bugs, request features, or contribute to the code on {github}.",
|
||||
"defaultMessage": "{domain} runs on Glitchsoc. Glitchsoc is a friendly {fork} of {Mastodon}. Glitchsoc is fully compatible with all Mastodon apps and instances. Glitchsoc is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
|
||||
"id": "onboarding.page_six.github"
|
||||
},
|
||||
{
|
||||
|
@ -1168,6 +1172,71 @@
|
|||
],
|
||||
"path": "app/javascript/mastodon/features/ui/components/report_modal.json"
|
||||
},
|
||||
{
|
||||
"descriptors": [
|
||||
{
|
||||
"defaultMessage": "General",
|
||||
"id": "settings.general"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Wide view (Desktop mode only)",
|
||||
"id": "settings.wide_view"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Collapsed toots",
|
||||
"id": "settings.collapsed_statuses"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Enable collapsed toots",
|
||||
"id": "settings.enable_collapsed"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Automatic collapsing",
|
||||
"id": "settings.auto_collapse"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Everything",
|
||||
"id": "settings.auto_collapse_all"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Notifications",
|
||||
"id": "settings.auto_collapse_notifications"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Lengthy toots",
|
||||
"id": "settings.auto_collapse_lengthy"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Replies",
|
||||
"id": "settings.auto_collapse_replies"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Toots with media",
|
||||
"id": "settings.auto_collapse_media"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Image backgrounds",
|
||||
"id": "settings.image_backgrounds"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Give collapsed toots an image background",
|
||||
"id": "settings.image_backgrounds_users"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Preview collapsed toot media",
|
||||
"id": "settings.image_backgrounds_media"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "User preferences",
|
||||
"id": "settings.global_settings"
|
||||
},
|
||||
{
|
||||
"defaultMessage": "Close",
|
||||
"id": "settings.close"
|
||||
}
|
||||
],
|
||||
"path": "app/javascript/mastodon/features/ui/components/settings_modal.json"
|
||||
},
|
||||
{
|
||||
"descriptors": [
|
||||
{
|
||||
|
@ -1211,4 +1280,4 @@
|
|||
],
|
||||
"path": "app/javascript/mastodon/features/ui/components/video_modal.json"
|
||||
}
|
||||
]
|
||||
]
|
|
@ -87,6 +87,7 @@
|
|||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
"missing_indicator.label": "Not found",
|
||||
"navigation_bar.app_settings": "App settings",
|
||||
"navigation_bar.blocks": "Blocked users",
|
||||
"navigation_bar.community_timeline": "Local timeline",
|
||||
"navigation_bar.edit_profile": "Edit profile",
|
||||
|
@ -146,6 +147,21 @@
|
|||
"report.target": "Reporting {target}",
|
||||
"search.placeholder": "Search",
|
||||
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
|
||||
"settings.auto_collapse": "Automatic collapsing",
|
||||
"settings.auto_collapse_all": "Everything",
|
||||
"settings.auto_collapse_lengthy": "Lengthy toots",
|
||||
"settings.auto_collapse_media": "Toots with media",
|
||||
"settings.auto_collapse_notifications": "Notifications",
|
||||
"settings.auto_collapse_replies": "Replies",
|
||||
"settings.close": "Close",
|
||||
"settings.collapsed_statuses": "Collapsed toots",
|
||||
"settings.enable_collapsed": "Enable collapsed toots",
|
||||
"settings.general": "General",
|
||||
"settings.global_settings": "User preferences",
|
||||
"settings.image_backgrounds": "Image backgrounds",
|
||||
"settings.image_backgrounds_media": "Preview collapsed toot media",
|
||||
"settings.image_backgrounds_users": "Give collapsed toots an image background",
|
||||
"settings.wide_view": "Wide view (Desktop mode only)",
|
||||
"status.cannot_reblog": "This post cannot be boosted",
|
||||
"status.collapse": "Collapse",
|
||||
"status.delete": "Delete",
|
||||
|
|
|
@ -14,7 +14,7 @@ import relationships from './relationships';
|
|||
import search from './search';
|
||||
import notifications from './notifications';
|
||||
import settings from './settings';
|
||||
import localSettings from './local_settings';
|
||||
import local_settings from './local_settings';
|
||||
import status_lists from './status_lists';
|
||||
import cards from './cards';
|
||||
import reports from './reports';
|
||||
|
@ -37,7 +37,7 @@ export default combineReducers({
|
|||
search,
|
||||
notifications,
|
||||
settings,
|
||||
localSettings,
|
||||
local_settings,
|
||||
cards,
|
||||
reports,
|
||||
contexts,
|
||||
|
|
|
@ -3,7 +3,22 @@ import { STORE_HYDRATE } from '../actions/store';
|
|||
import Immutable from 'immutable';
|
||||
|
||||
const initialState = Immutable.Map({
|
||||
layout: 'auto',
|
||||
layout : 'auto',
|
||||
stretch : true,
|
||||
collapsed : {
|
||||
enabled : true,
|
||||
auto : {
|
||||
all : false,
|
||||
notifications : true,
|
||||
lengthy : true,
|
||||
replies : false,
|
||||
media : false,
|
||||
},
|
||||
backgrounds : {
|
||||
user_backgrounds : false,
|
||||
preview_images : false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const hydrate = (state, localSettings) => state.mergeDeep(localSettings);
|
||||
|
@ -11,7 +26,7 @@ const hydrate = (state, localSettings) => state.mergeDeep(localSettings);
|
|||
export default function localSettings(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case STORE_HYDRATE:
|
||||
return hydrate(state, action.state.get('localSettings'));
|
||||
return hydrate(state, action.state.get('local_settings'));
|
||||
case LOCAL_SETTING_CHANGE:
|
||||
return state.setIn(action.key, action.value);
|
||||
default:
|
||||
|
|
|
@ -1351,6 +1351,10 @@
|
|||
overflow-x: auto;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
|
||||
.wide & {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@include limited-single-column('screen and (max-width: 360px)', $parent: null) {
|
||||
|
@ -1367,6 +1371,12 @@
|
|||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.wide & {
|
||||
flex: auto;
|
||||
min-width: 330px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
> .scrollable {
|
||||
background: $ui-base-color;
|
||||
}
|
||||
|
@ -1387,6 +1397,12 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
|
||||
.wide & {
|
||||
flex: 1 1 200px;
|
||||
min-width: 300px;
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.drawer__tab {
|
||||
|
@ -1399,11 +1415,12 @@
|
|||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.column,
|
||||
.drawer {
|
||||
flex: 1 1 100%;
|
||||
@supports(display: grid) { // hack to fix Chrome <57
|
||||
contain: strict;
|
||||
}
|
||||
|
@ -1419,20 +1436,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
@include single-column('screen and (max-width: 1024px)', $parent: null) {
|
||||
.column,
|
||||
.drawer {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
:root { // Overrides .wide stylings for mobile view
|
||||
@include single-column('screen and (max-width: 1024px)', $parent: null) {
|
||||
.column,
|
||||
.drawer {
|
||||
flex: auto;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.columns-area {
|
||||
flex-direction: column;
|
||||
}
|
||||
.columns-area {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.search__input,
|
||||
.autosuggest-textarea__textarea {
|
||||
font-size: 16px;
|
||||
.search__input,
|
||||
.autosuggest-textarea__textarea {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1443,7 +1465,6 @@
|
|||
|
||||
.column,
|
||||
.drawer {
|
||||
flex: 0 0 auto;
|
||||
padding: 10px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
|
@ -1771,6 +1792,8 @@
|
|||
font-size: 16px;
|
||||
padding: 15px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
background: lighten($ui-base-color, 11%);
|
||||
|
@ -3312,6 +3335,85 @@ button.icon-button.active i.fa-retweet {
|
|||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.settings-modal {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background: $ui-secondary-color;
|
||||
color: $ui-base-color;
|
||||
border-radius: 8px;
|
||||
height: 80vh;
|
||||
width: 80vw;
|
||||
max-width: 740px;
|
||||
max-height: 450px;
|
||||
overflow: hidden;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-modal__navigation {
|
||||
background: $primary-text-color;
|
||||
color: $ui-base-color;
|
||||
width: 200px;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
overflow-y: auto;
|
||||
|
||||
.settings-modal__navigation-item, .settings-modal__navigation-close {
|
||||
display: block;
|
||||
padding: 15px 20px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.settings-modal__navigation-item {
|
||||
background: $primary-text-color;
|
||||
color: inherit;
|
||||
border-bottom: 1px $ui-primary-color solid;
|
||||
transition: background .3s;
|
||||
|
||||
&:hover {
|
||||
background: $ui-secondary-color;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $ui-highlight-color;
|
||||
color: $primary-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-modal__navigation-close {
|
||||
background: $error-value-color;
|
||||
color: $primary-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.settings-modal__content {
|
||||
display: block;
|
||||
flex: auto;
|
||||
padding: 15px 20px 15px 20px;
|
||||
width: 360px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.onboard-sliders {
|
||||
display: inline-block;
|
||||
max-width: 30px;
|
||||
|
|
|
@ -1,19 +1,5 @@
|
|||
@import 'application';
|
||||
|
||||
@include multi-columns('screen and (min-width: 1300px)', $parent: null) {
|
||||
.column {
|
||||
flex-grow: 1 !important;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.drawer {
|
||||
flex-grow: 1 !important;
|
||||
flex-basis: 200px !important;
|
||||
min-width: 268px;
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.muted {
|
||||
.status__content p, .status__content a {
|
||||
color: lighten($ui-base-color, 35%);
|
||||
|
|
Loading…
Reference in New Issue