diff options
Diffstat (limited to 'app/javascript/flavours')
36 files changed, 308 insertions, 130 deletions
diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index 605a2862b..613318102 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -6,7 +6,7 @@ import IconButton from './icon_button'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { isIOS } from 'flavours/glitch/util/is_mobile'; import classNames from 'classnames'; -import { autoPlayGif, displaySensitiveMedia } from 'flavours/glitch/util/initial_state'; +import { autoPlayGif, displayMedia } from 'flavours/glitch/util/initial_state'; const messages = defineMessages({ hidden: { @@ -226,7 +226,7 @@ export default class MediaGallery extends React.PureComponent { }; state = { - visible: this.props.revealed === undefined ? (!this.props.sensitive || displaySensitiveMedia) : this.props.revealed, + visible: this.props.revealed === undefined ? (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all') : this.props.revealed, }; componentWillReceiveProps (nextProps) { diff --git a/app/javascript/flavours/glitch/components/permalink.js b/app/javascript/flavours/glitch/components/permalink.js index d6556b584..1ea6a2915 100644 --- a/app/javascript/flavours/glitch/components/permalink.js +++ b/app/javascript/flavours/glitch/components/permalink.js @@ -12,12 +12,20 @@ export default class Permalink extends React.PureComponent { href: PropTypes.string.isRequired, to: PropTypes.string.isRequired, children: PropTypes.node, + onInterceptClick: PropTypes.func, }; handleClick = (e) => { - if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - this.context.router.history.push(this.props.to); + if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { + if (this.props.onInterceptClick && this.props.onInterceptClick()) { + e.preventDefault(); + return; + } + + if (this.context.router) { + e.preventDefault(); + this.context.router.history.push(this.props.to); + } } } @@ -27,6 +35,7 @@ export default class Permalink extends React.PureComponent { className, href, to, + onInterceptClick, ...other } = this.props; diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index a677cbf5b..3ee710dc9 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -150,6 +150,7 @@ export default class ScrollableList extends PureComponent { } defaultShouldUpdateScroll = (prevRouterProps, { location }) => { + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; return !(location.state && location.state.mastodonModalOpen); } diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index 5ac92ea39..663bfbebc 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -31,6 +31,8 @@ const messages = defineMessages({ redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' }, redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, + replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, + replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, }); const makeMapStateToProps = () => { @@ -67,7 +69,18 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onReply (status, router) { - dispatch(replyCompose(status, router)); + dispatch((_, getState) => { + let state = getState(); + if (state.getIn(['compose', 'text']).trim().length !== 0) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(replyCompose(status, router)), + })); + } else { + dispatch(replyCompose(status, router)); + } + }); }, onModalReblog (status) { diff --git a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js index c2cf48d7b..89778e123 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js +++ b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js @@ -2,6 +2,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Permalink from 'flavours/glitch/components/permalink'; +import { displayMedia } from 'flavours/glitch/util/initial_state'; export default class MediaItem extends ImmutablePureComponent { @@ -9,8 +10,22 @@ export default class MediaItem extends ImmutablePureComponent { media: ImmutablePropTypes.map.isRequired, }; + state = { + visible: displayMedia !== 'hide_all' && !this.props.media.getIn(['status', 'sensitive']) || displayMedia === 'show_all', + }; + + handleClick = () => { + if (!this.state.visible) { + this.setState({ visible: true }); + return true; + } + + return false; + } + render () { const { media } = this.props; + const { visible } = this.state; const status = media.get('status'); const focusX = media.getIn(['meta', 'focus', 'x']); const focusY = media.getIn(['meta', 'focus', 'y']); @@ -18,21 +33,36 @@ export default class MediaItem extends ImmutablePureComponent { const y = ((focusY / -2) + .5) * 100; const style = {}; - let content; + let label, icon, title; if (media.get('type') === 'gifv') { - content = <span className='media-gallery__gifv__label'>GIF</span>; + label = <span className='media-gallery__gifv__label'>GIF</span>; } - if (!status.get('sensitive')) { + if (visible) { style.backgroundImage = `url(${media.get('preview_url')})`; style.backgroundPosition = `${x}% ${y}%`; + title = media.get('description'); + } else { + icon = ( + <span className='account-gallery__item__icons'> + <i className='fa fa-eye-slash' /> + </span> + ); + title = status.get('spoiler_text') || media.get('description'); } return ( <div className='account-gallery__item'> - <Permalink to={`/statuses/${status.get('id')}`} href={status.get('url')} style={style}> - {content} + <Permalink + to={`/statuses/${status.get('id')}`} + href={status.get('url')} + style={style} + title={title} + onInterceptClick={this.handleClick} + > + {icon} + {label} </Permalink> </div> ); diff --git a/app/javascript/flavours/glitch/features/account_gallery/index.js b/app/javascript/flavours/glitch/features/account_gallery/index.js index de8318964..53b906d16 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/index.js +++ b/app/javascript/flavours/glitch/features/account_gallery/index.js @@ -90,7 +90,8 @@ export default class AccountGallery extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; + return !(location.state && location.state.mastodonModalOpen); } render () { diff --git a/app/javascript/flavours/glitch/features/blocks/index.js b/app/javascript/flavours/glitch/features/blocks/index.js index 4c8b16504..386a0ce63 100644 --- a/app/javascript/flavours/glitch/features/blocks/index.js +++ b/app/javascript/flavours/glitch/features/blocks/index.js @@ -43,7 +43,8 @@ export default class Blocks extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; + return !(location.state && location.state.mastodonModalOpen); } render () { diff --git a/app/javascript/flavours/glitch/features/favourites/index.js b/app/javascript/flavours/glitch/features/favourites/index.js index cf8b31eb3..65cd4a19b 100644 --- a/app/javascript/flavours/glitch/features/favourites/index.js +++ b/app/javascript/flavours/glitch/features/favourites/index.js @@ -34,6 +34,7 @@ export default class Favourites extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; return !(location.state && location.state.mastodonModalOpen); } diff --git a/app/javascript/flavours/glitch/features/follow_requests/index.js b/app/javascript/flavours/glitch/features/follow_requests/index.js index 1e4633984..bce6338ea 100644 --- a/app/javascript/flavours/glitch/features/follow_requests/index.js +++ b/app/javascript/flavours/glitch/features/follow_requests/index.js @@ -43,6 +43,7 @@ export default class FollowRequests extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; return !(location.state && location.state.mastodonModalOpen); } diff --git a/app/javascript/flavours/glitch/features/followers/index.js b/app/javascript/flavours/glitch/features/followers/index.js index cdde1775c..a977142ed 100644 --- a/app/javascript/flavours/glitch/features/followers/index.js +++ b/app/javascript/flavours/glitch/features/followers/index.js @@ -57,6 +57,7 @@ export default class Followers extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; return !(location.state && location.state.mastodonModalOpen); } diff --git a/app/javascript/flavours/glitch/features/following/index.js b/app/javascript/flavours/glitch/features/following/index.js index e7a72d036..70aeefaad 100644 --- a/app/javascript/flavours/glitch/features/following/index.js +++ b/app/javascript/flavours/glitch/features/following/index.js @@ -57,7 +57,8 @@ export default class Following extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; + return !(location.state && location.state.mastodonModalOpen); } render () { diff --git a/app/javascript/flavours/glitch/features/getting_started/index.js b/app/javascript/flavours/glitch/features/getting_started/index.js index 09dcbe716..c1897cc33 100644 --- a/app/javascript/flavours/glitch/features/getting_started/index.js +++ b/app/javascript/flavours/glitch/features/getting_started/index.js @@ -165,13 +165,10 @@ export default class GettingStarted extends ImmutablePureComponent { <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 href='https://docs.joinmastodon.org' target='_blank'> + <FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /> </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'> + <a href='https://joinmastodon.org/apps' target='_blank' rel='noopener'> <FormattedMessage id='getting_started.appsshort' defaultMessage='Apps' /> </a> </p> diff --git a/app/javascript/flavours/glitch/features/local_settings/navigation/index.js b/app/javascript/flavours/glitch/features/local_settings/navigation/index.js index a992b1ffc..cf02101cf 100644 --- a/app/javascript/flavours/glitch/features/local_settings/navigation/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/navigation/index.js @@ -38,37 +38,42 @@ export default class LocalSettingsNavigation extends React.PureComponent { active={index === 0} index={0} onNavigate={onNavigate} + icon='cogs' title={intl.formatMessage(messages.general)} /> <LocalSettingsNavigationItem active={index === 1} index={1} onNavigate={onNavigate} + icon='pencil' title={intl.formatMessage(messages.compose)} /> <LocalSettingsNavigationItem active={index === 2} index={2} onNavigate={onNavigate} + textIcon='CW' title={intl.formatMessage(messages.content_warnings)} /> <LocalSettingsNavigationItem active={index === 3} index={3} onNavigate={onNavigate} + icon='angle-double-up' title={intl.formatMessage(messages.collapsed)} /> <LocalSettingsNavigationItem active={index === 4} index={4} onNavigate={onNavigate} + icon='image' title={intl.formatMessage(messages.media)} /> <LocalSettingsNavigationItem active={index === 5} href='/settings/preferences' index={5} - icon='cog' + icon='sliders' title={intl.formatMessage(messages.preferences)} /> <LocalSettingsNavigationItem @@ -76,6 +81,7 @@ export default class LocalSettingsNavigation extends React.PureComponent { className='close' index={6} onNavigate={onClose} + icon='times' title={intl.formatMessage(messages.close)} /> </nav> diff --git a/app/javascript/flavours/glitch/features/local_settings/navigation/item/index.js b/app/javascript/flavours/glitch/features/local_settings/navigation/item/index.js index b67d479e7..68a998b6c 100644 --- a/app/javascript/flavours/glitch/features/local_settings/navigation/item/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/navigation/item/index.js @@ -12,6 +12,7 @@ export default class LocalSettingsPage extends React.PureComponent { className: PropTypes.string, href: PropTypes.string, icon: PropTypes.string, + textIcon: PropTypes.string, index: PropTypes.number.isRequired, onNavigate: PropTypes.func, title: PropTypes.string, @@ -32,6 +33,7 @@ export default class LocalSettingsPage extends React.PureComponent { className, href, icon, + textIcon, onNavigate, title, } = this.props; @@ -40,14 +42,14 @@ export default class LocalSettingsPage extends React.PureComponent { active, }, className); - const iconElem = icon ? <i className={`fa fa-fw fa-${icon}`} /> : null; + const iconElem = icon ? <i className={`fa fa-fw fa-${icon}`} /> : (textIcon ? <span className='text-icon-button'>{textIcon}</span> : null); if (href) return ( <a href={href} className={finalClassName} > - {iconElem} {title} + {iconElem} <span>{title}</span> </a> ); else if (onNavigate) return ( @@ -57,7 +59,7 @@ export default class LocalSettingsPage extends React.PureComponent { tabIndex='0' className={finalClassName} > - {iconElem} {title} + {iconElem} <span>{title}</span> </a> ); else return null; diff --git a/app/javascript/flavours/glitch/features/local_settings/page/index.js b/app/javascript/flavours/glitch/features/local_settings/page/index.js index ece80c4da..4f1b8525f 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js @@ -50,7 +50,8 @@ export default class LocalSettingsPage extends React.PureComponent { id='mastodon-settings--notifications-tab_badge' onChange={onChange} > - <FormattedMessage id='settings.notifications.tab_badge' defaultMessage="Display a badge for unread notifications if the notifications column isn't open" /> + <FormattedMessage id='settings.notifications.tab_badge' defaultMessage="Unread notifications badge" /> + <span className='hint'><FormattedMessage id='settings.notifications.tab_badge.hint' defaultMessage="Display a badge for unread notifications in the column icons when the notifications column isn't open" /></span> </LocalSettingsPageItem> <LocalSettingsPageItem settings={settings} @@ -58,7 +59,8 @@ export default class LocalSettingsPage extends React.PureComponent { id='mastodon-settings--notifications-favicon_badge' onChange={onChange} > - <FormattedMessage id='settings.notifications.favicon_badge' defaultMessage='Display unread notifications count in the favicon' /> + <FormattedMessage id='settings.notifications.favicon_badge' defaultMessage='Unread notifications favicon badge' /> + <span className='hint'><FormattedMessage id='settings.notifications.favicon_badge.hint' defaultMessage="Add a badge for unread notifications to the favicon" /></span> </LocalSettingsPageItem> </section> <section> @@ -83,6 +85,7 @@ export default class LocalSettingsPage extends React.PureComponent { onChange={onChange} > <FormattedMessage id='settings.wide_view' defaultMessage='Wide view (Desktop mode only)' /> + <span className='hint'><FormattedMessage id='settings.wide_view_hint' defaultMessage='Stretches columns to better fill the available space.' /></span> </LocalSettingsPageItem> <LocalSettingsPageItem settings={settings} @@ -112,7 +115,8 @@ export default class LocalSettingsPage extends React.PureComponent { id='mastodon-settings--preselect_on_reply' onChange={onChange} > - <FormattedMessage id='settings.preselect_on_reply' defaultMessage='Pre-select usernames past the first when replying to a toot with multiple participants' /> + <FormattedMessage id='settings.preselect_on_reply' defaultMessage='Pre-select usernames on reply' /> + <span className='hint'><FormattedMessage id='settings.preselect_on_reply_hint' defaultMessage='When replying to a conversation with multiple participants, pre-select usernames past the first' /></span> </LocalSettingsPageItem> <LocalSettingsPageItem settings={settings} @@ -186,6 +190,15 @@ export default class LocalSettingsPage extends React.PureComponent { > <FormattedMessage id='settings.enable_collapsed' defaultMessage='Enable collapsed toots' /> </LocalSettingsPageItem> + <LocalSettingsPageItem + settings={settings} + item={['collapsed', 'show_action_bar']} + id='mastodon-settings--collapsed-show-action-bar' + onChange={onChange} + dependsOn={[['collapsed', 'enabled']]} + > + <FormattedMessage id='settings.show_action_bar' defaultMessage='Show action buttons in collapsed toots' /> + </LocalSettingsPageItem> <section> <h2><FormattedMessage id='settings.auto_collapse' defaultMessage='Automatic collapsing' /></h2> <LocalSettingsPageItem @@ -269,18 +282,6 @@ export default class LocalSettingsPage extends React.PureComponent { <FormattedMessage id='settings.image_backgrounds_media' defaultMessage='Preview collapsed toot media' /> </LocalSettingsPageItem> </section> - <section> - <h2></h2> - <LocalSettingsPageItem - settings={settings} - item={['collapsed', 'show_action_bar']} - id='mastodon-settings--collapsed-show-action-bar' - onChange={onChange} - dependsOn={[['collapsed', 'enabled']]} - > - <FormattedMessage id='settings.show_action_bar' defaultMessage='Show action buttons in collapsed toots' /> - </LocalSettingsPageItem> - </section> </div> ), ({ onChange, settings }) => ( @@ -293,6 +294,7 @@ export default class LocalSettingsPage extends React.PureComponent { onChange={onChange} > <FormattedMessage id='settings.media_letterbox' defaultMessage='Letterbox media' /> + <span className='hint'><FormattedMessage id='settings.media_letterbox_hint' defaultMessage='Scale down and letterbox media to fill the image containers instead of stretching and cropping them' /></span> </LocalSettingsPageItem> <LocalSettingsPageItem settings={settings} diff --git a/app/javascript/flavours/glitch/features/local_settings/page/item/index.js b/app/javascript/flavours/glitch/features/local_settings/page/item/index.js index fe237f11e..66b937365 100644 --- a/app/javascript/flavours/glitch/features/local_settings/page/item/index.js +++ b/app/javascript/flavours/glitch/features/local_settings/page/item/index.js @@ -17,6 +17,7 @@ export default class LocalSettingsPageItem extends React.PureComponent { options: PropTypes.arrayOf(PropTypes.shape({ value: PropTypes.string.isRequired, message: PropTypes.string.isRequired, + hint: PropTypes.string, })), settings: ImmutablePropTypes.map.isRequired, placeholder: PropTypes.string, @@ -48,57 +49,63 @@ export default class LocalSettingsPageItem extends React.PureComponent { if (options && options.length > 0) { const currentValue = settings.getIn(item); - const optionElems = options && options.length > 0 && options.map((opt) => ( - <option - key={opt.value} - value={opt.value} - > - {opt.message} - </option> - )); - return ( - <label className='glitch local-settings__page__item' htmlFor={id}> - <p>{children}</p> - <p> - <select - id={id} - disabled={!enabled} + const optionElems = options && options.length > 0 && options.map((opt) => { + let optionId = `${id}--${opt.value}`; + return ( + <label htmlFor={optionId}> + <input type='radio' + name={id} + id={optionId} + value={opt.value} onBlur={handleChange} onChange={handleChange} - value={currentValue} - > - {optionElems} - </select> - </p> - </label> + checked={ currentValue === opt.value } + disabled={!enabled} + /> + {opt.message} + {opt.hint && <span class='hint'>{opt.hint}</span>} + </label> + ); + }); + return ( + <div class='glitch local-settings__page__item radio_buttons'> + <fieldset> + <legend>{children}</legend> + {optionElems} + </fieldset> + </div> ); } else if (placeholder) { return ( - <label className='glitch local-settings__page__item' htmlFor={id}> - <p>{children}</p> - <p> - <input - id={id} - type='text' - value={settings.getIn(item)} - placeholder={placeholder} - onChange={handleChange} - disabled={!enabled} - /> - </p> - </label> + <div className='glitch local-settings__page__item string'> + <label htmlFor={id}> + <p>{children}</p> + <p> + <input + id={id} + type='text' + value={settings.getIn(item)} + placeholder={placeholder} + onChange={handleChange} + disabled={!enabled} + /> + </p> + </label> + </div> ); } else return ( - <label className='glitch local-settings__page__item' htmlFor={id}> - <input - id={id} - type='checkbox' - checked={settings.getIn(item)} - onChange={handleChange} - disabled={!enabled} - /> - {children} - </label> + <div className='glitch local-settings__page__item boolean'> + <label htmlFor={id}> + <input + id={id} + type='checkbox' + checked={settings.getIn(item)} + onChange={handleChange} + disabled={!enabled} + /> + {children} + </label> + </div> ); } diff --git a/app/javascript/flavours/glitch/features/mutes/index.js b/app/javascript/flavours/glitch/features/mutes/index.js index d94c1d8ad..bbcbea701 100644 --- a/app/javascript/flavours/glitch/features/mutes/index.js +++ b/app/javascript/flavours/glitch/features/mutes/index.js @@ -43,6 +43,7 @@ export default class Mutes extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; return !(location.state && location.state.mastodonModalOpen); } diff --git a/app/javascript/flavours/glitch/features/reblogs/index.js b/app/javascript/flavours/glitch/features/reblogs/index.js index c0a65d1de..75f8390a1 100644 --- a/app/javascript/flavours/glitch/features/reblogs/index.js +++ b/app/javascript/flavours/glitch/features/reblogs/index.js @@ -34,6 +34,7 @@ export default class Reblogs extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; return !(location.state && location.state.mastodonModalOpen); } diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 5759a575c..4382748d5 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -50,6 +50,8 @@ const messages = defineMessages({ revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' }, hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' }, detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' }, + replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, + replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, }); const makeMapStateToProps = () => { @@ -60,6 +62,7 @@ const makeMapStateToProps = () => { settings: state.get('local_settings'), ancestorsIds: state.getIn(['contexts', 'ancestors', props.params.statusId]), descendantsIds: state.getIn(['contexts', 'descendants', props.params.statusId]), + askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0, }); return mapStateToProps; @@ -81,6 +84,7 @@ export default class Status extends ImmutablePureComponent { ancestorsIds: ImmutablePropTypes.list, descendantsIds: ImmutablePropTypes.list, intl: PropTypes.object.isRequired, + askReplyConfirmation: PropTypes.bool, }; state = { @@ -140,7 +144,16 @@ export default class Status extends ImmutablePureComponent { } handleReplyClick = (status) => { - this.props.dispatch(replyCompose(status, this.context.router.history)); + let { askReplyConfirmation, dispatch, intl } = this.props; + if (askReplyConfirmation) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(replyCompose(status, this.context.router.history)), + })); + } else { + dispatch(replyCompose(status, this.context.router.history)); + } } handleModalReblog = (status) => { @@ -351,7 +364,8 @@ export default class Status extends ImmutablePureComponent { } shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state && location.state.mastodonModalOpen) + if ((((prevRouterProps || {}).location || {}).state || {}).mastodonModalOpen) return false; + return !(location.state && location.state.mastodonModalOpen); } render () { diff --git a/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js b/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js index 4c910daec..16355a446 100644 --- a/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js @@ -133,7 +133,7 @@ const PageSix = ({ admin, domain }) => { <h1><FormattedMessage id='onboarding.page_six.almost_done' defaultMessage='Almost done...' /></h1> {adminSection} <p><FormattedMessage id='onboarding.page_six.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}.' values={{ domain, fork: <a href='https://en.wikipedia.org/wiki/Fork_(software_development)' target='_blank' rel='noopener'>fork</a>, Mastodon: <a href='https://github.com/tootsuite/mastodon' target='_blank' rel='noopener'>Mastodon</a>, github: <a href='https://github.com/glitch-soc/mastodon' target='_blank' rel='noopener'>GitHub</a> }} /></p> - <p><FormattedMessage id='onboarding.page_six.apps_available' defaultMessage='There are {apps} available for iOS, Android and other platforms.' values={{ domain, apps: <a href='https://github.com/tootsuite/documentation/blob/master/Using-Mastodon/Apps.md' target='_blank' rel='noopener'><FormattedMessage id='onboarding.page_six.various_app' defaultMessage='mobile apps' /></a> }} /></p> + <p><FormattedMessage id='onboarding.page_six.apps_available' defaultMessage='There are {apps} available for iOS, Android and other platforms.' values={{ domain, apps: <a href='https://joinmastodon.org/apps' target='_blank' rel='noopener'><FormattedMessage id='onboarding.page_six.various_app' defaultMessage='mobile apps' /></a> }} /></p> <p><em><FormattedMessage id='onboarding.page_six.appetoot' defaultMessage='Bon Appetoot!' /></em></p> </div> ); diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index ecbac1f8f..510bb9540 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -456,7 +456,7 @@ export default class UI extends React.Component { }; return ( - <HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef}> + <HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused> <div className={className} ref={this.setRef} style={{ pointerEvents: dropdownMenuIsOpen ? 'none' : null }}> {navbarUnder ? null : (<TabsBar />)} diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 5cbe01f26..227f298e4 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -5,7 +5,7 @@ import { fromJS } from 'immutable'; import { throttle } from 'lodash'; import classNames from 'classnames'; import { isFullscreen, requestFullscreen, exitFullscreen } from 'flavours/glitch/util/fullscreen'; -import { displaySensitiveMedia } from 'flavours/glitch/util/initial_state'; +import { displayMedia } from 'flavours/glitch/util/initial_state'; const messages = defineMessages({ play: { id: 'video.play', defaultMessage: 'Play' }, @@ -114,7 +114,7 @@ export default class Video extends React.PureComponent { fullscreen: false, hovered: false, muted: false, - revealed: this.props.revealed === undefined ? (!this.props.sensitive || displaySensitiveMedia) : this.props.revealed, + revealed: this.props.revealed === undefined ? (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all') : this.props.revealed, }; setPlayerRef = c => { diff --git a/app/javascript/flavours/glitch/styles/about.scss b/app/javascript/flavours/glitch/styles/about.scss index ba46c65c5..f676a8c77 100644 --- a/app/javascript/flavours/glitch/styles/about.scss +++ b/app/javascript/flavours/glitch/styles/about.scss @@ -16,7 +16,7 @@ $small-breakpoint: 960px; } .rich-formatting { - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 16px; font-weight: 400; font-size: 16px; @@ -31,7 +31,7 @@ $small-breakpoint: 960px; p, li { - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 16px; font-weight: 400; font-size: 16px; @@ -62,7 +62,7 @@ $small-breakpoint: 960px; } h1 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 26px; line-height: 30px; font-weight: 500; @@ -70,7 +70,7 @@ $small-breakpoint: 960px; color: $secondary-text-color; small { - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; display: block; font-size: 18px; font-weight: 400; @@ -79,7 +79,7 @@ $small-breakpoint: 960px; } h2 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 22px; line-height: 26px; font-weight: 500; @@ -88,7 +88,7 @@ $small-breakpoint: 960px; } h3 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 18px; line-height: 24px; font-weight: 500; @@ -97,7 +97,7 @@ $small-breakpoint: 960px; } h4 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 16px; line-height: 24px; font-weight: 500; @@ -106,7 +106,7 @@ $small-breakpoint: 960px; } h5 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 14px; line-height: 24px; font-weight: 500; @@ -115,7 +115,7 @@ $small-breakpoint: 960px; } h6 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 12px; line-height: 24px; font-weight: 500; @@ -180,7 +180,7 @@ $small-breakpoint: 960px; &__section { flex: 1 0 0; - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 16px; line-height: 28px; color: $primary-text-color; @@ -221,7 +221,7 @@ $small-breakpoint: 960px; bottom: -40px; .panel-header { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 14px; line-height: 24px; font-weight: 500; @@ -452,7 +452,7 @@ $small-breakpoint: 960px; p, li { - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 16px; font-weight: 400; font-size: 16px; @@ -501,7 +501,7 @@ $small-breakpoint: 960px; } h1 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 26px; line-height: 30px; font-weight: 500; @@ -509,7 +509,7 @@ $small-breakpoint: 960px; color: $secondary-text-color; small { - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; display: block; font-size: 18px; font-weight: 400; @@ -518,7 +518,7 @@ $small-breakpoint: 960px; } h2 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 22px; line-height: 26px; font-weight: 500; @@ -527,7 +527,7 @@ $small-breakpoint: 960px; } h3 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 18px; line-height: 24px; font-weight: 500; @@ -536,7 +536,7 @@ $small-breakpoint: 960px; } h4 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 16px; line-height: 24px; font-weight: 500; @@ -545,7 +545,7 @@ $small-breakpoint: 960px; } h5 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 14px; line-height: 24px; font-weight: 500; @@ -554,7 +554,7 @@ $small-breakpoint: 960px; } h6 { - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-size: 12px; line-height: 24px; font-weight: 500; @@ -621,7 +621,7 @@ $small-breakpoint: 960px; .hero .heading { padding-bottom: 20px; - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 16px; font-weight: 400; font-size: 16px; @@ -672,7 +672,7 @@ $small-breakpoint: 960px; text-decoration: none; padding: 12px 16px; line-height: 32px; - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-weight: 500; font-size: 14px; @@ -745,7 +745,7 @@ $small-breakpoint: 960px; .about-short { background: darken($ui-base-color, 4%); padding: 50px 0 30px; - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 16px; font-weight: 400; font-size: 16px; @@ -1015,7 +1015,7 @@ $small-breakpoint: 960px; display: flex; -webkit-overflow-scrolling: touch; -ms-overflow-style: -ms-autohiding-scrollbar; - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; font-size: 13px; line-height: 18px; font-weight: 400; diff --git a/app/javascript/flavours/glitch/styles/admin.scss b/app/javascript/flavours/glitch/styles/admin.scss index b8cc33039..e16920dd4 100644 --- a/app/javascript/flavours/glitch/styles/admin.scss +++ b/app/javascript/flavours/glitch/styles/admin.scss @@ -443,7 +443,7 @@ $no-columns-breakpoint: 600px; border-radius: 0 0 4px 4px; padding: 10px; color: $darker-text-color; - font-family: 'mastodon-font-monospace', monospace; + font-family: $font-monospace, monospace; font-size: 12px; word-wrap: break-word; min-height: 20px; diff --git a/app/javascript/flavours/glitch/styles/basics.scss b/app/javascript/flavours/glitch/styles/basics.scss index 9c2499ac4..550b7fdfc 100644 --- a/app/javascript/flavours/glitch/styles/basics.scss +++ b/app/javascript/flavours/glitch/styles/basics.scss @@ -6,7 +6,7 @@ } body { - font-family: 'mastodon-font-sans-serif', sans-serif; + font-family: $font-sans-serif, sans-serif; background: darken($ui-base-color, 8%); font-size: 13px; line-height: 18px; @@ -29,8 +29,8 @@ body { // Fira Sans => Firefox OS // Droid Sans => Older Androids (<4.0) // Helvetica Neue => Older macOS <10.11 - // mastodon-font-sans-serif => web-font (Roboto) fallback and newer Androids (>=4.0) - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", mastodon-font-sans-serif, sans-serif; + // $font-sans-serif => web-font (Roboto) fallback and newer Androids (>=4.0) + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", $font-sans-serif, sans-serif; } &.app-body { diff --git a/app/javascript/flavours/glitch/styles/components/accounts.scss b/app/javascript/flavours/glitch/styles/components/accounts.scss index 3eddd7fb4..d87cd9c43 100644 --- a/app/javascript/flavours/glitch/styles/components/accounts.scss +++ b/app/javascript/flavours/glitch/styles/components/accounts.scss @@ -415,7 +415,7 @@ background-size: cover; background-position: center; position: absolute; - color: inherit; + color: $ui-primary-color; text-decoration: none; border-radius: 4px; @@ -423,6 +423,7 @@ &:active, &:focus { outline: 0; + color: $ui-secondary-color; &::before { content: ""; @@ -434,6 +435,14 @@ } } } + + &__icons { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 24px; + } } .account__section-headline { diff --git a/app/javascript/flavours/glitch/styles/components/local_settings.scss b/app/javascript/flavours/glitch/styles/components/local_settings.scss index 9cd4e1fbe..0b7a74575 100644 --- a/app/javascript/flavours/glitch/styles/components/local_settings.scss +++ b/app/javascript/flavours/glitch/styles/components/local_settings.scss @@ -11,8 +11,26 @@ max-height: 450px; overflow: hidden; - label { + label, legend { display: block; + font-size: 14px; + } + + .boolean label, .radio_buttons label { + position: relative; + padding-left: 28px; + padding-top: 3px; + + input { + position: absolute; + left: 0; + top: 0; + } + } + + span.hint { + display: block; + color: $lighter-text-color; } h1 { @@ -42,6 +60,11 @@ outline: none; transition: background .3s; + .text-icon-button { + color: inherit; + transition: unset; + } + &:hover { background: $ui-secondary-color; } @@ -59,7 +82,7 @@ .glitch.local-settings__navigation { background: lighten($ui-secondary-color, 8%); - width: 200px; + width: 212px; font-size: 15px; line-height: 20px; overflow-y: auto; @@ -74,7 +97,26 @@ } .glitch.local-settings__page__item { - select { - margin-bottom: 5px; + margin-bottom: 2px; +} + +.glitch.local-settings__page__item.string, +.glitch.local-settings__page__item.radio_buttons { + margin-top: 10px; + margin-bottom: 10px; +} + +@media screen and (max-width: 630px) { + .glitch.local-settings__navigation { + width: 40px; + flex-shrink: 0; + } + + .glitch.local-settings__navigation__item { + padding: 10px; + + span:last-of-type { + display: none; + } } } diff --git a/app/javascript/flavours/glitch/styles/containers.scss b/app/javascript/flavours/glitch/styles/containers.scss index d1b9934d7..398458e47 100644 --- a/app/javascript/flavours/glitch/styles/containers.scss +++ b/app/javascript/flavours/glitch/styles/containers.scss @@ -37,7 +37,7 @@ outline: 0; padding: 12px 16px; line-height: 32px; - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; font-weight: 500; font-size: 14px; } @@ -633,7 +633,7 @@ font-size: 18px; margin-bottom: 5px; color: $primary-text-color; - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; } } diff --git a/app/javascript/flavours/glitch/styles/dashboard.scss b/app/javascript/flavours/glitch/styles/dashboard.scss index 949ca733f..86cf6c61b 100644 --- a/app/javascript/flavours/glitch/styles/dashboard.scss +++ b/app/javascript/flavours/glitch/styles/dashboard.scss @@ -35,7 +35,7 @@ font-weight: 500; font-size: 24px; color: $primary-text-color; - font-family: 'mastodon-font-display', sans-serif; + font-family: $font-display, sans-serif; margin-bottom: 20px; } diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index cbd3de94c..be2bf7cea 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -1,7 +1,7 @@ $no-columns-breakpoint: 600px; code { - font-family: 'mastodon-font-monospace', monospace; + font-family: $font-monospace, monospace; font-weight: 400; } @@ -474,7 +474,7 @@ code { width: 100%; border: none; padding: 10px; - font-family: 'mastodon-font-monospace', monospace; + font-family: $font-monospace, monospace; background: $ui-base-color; color: $primary-text-color; font-size: 14px; @@ -718,7 +718,7 @@ code { .form_admin_settings_custom_css, .form_admin_settings_closed_registrations_message { textarea { - font-family: 'mastodon-font-monospace', monospace; + font-family: $font-monospace, monospace; } } @@ -742,7 +742,7 @@ code { border: 0; padding: 10px; font-size: 14px; - font-family: 'mastodon-font-monospace', monospace; + font-family: $font-monospace, monospace; } button { diff --git a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss index aba8baf70..55a8983e5 100644 --- a/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss +++ b/app/javascript/flavours/glitch/styles/mastodon-light/diff.scss @@ -84,7 +84,8 @@ // Change the background colors of media and video spoilers .media-spoiler, -.video-player__spoiler { +.video-player__spoiler, +.account-gallery__item a { background: $ui-base-color; } diff --git a/app/javascript/flavours/glitch/styles/rtl.scss b/app/javascript/flavours/glitch/styles/rtl.scss index b8c0efad8..70aaa5bb1 100644 --- a/app/javascript/flavours/glitch/styles/rtl.scss +++ b/app/javascript/flavours/glitch/styles/rtl.scss @@ -145,6 +145,19 @@ body.rtl { margin-right: 6px; } + .status__action-bar { + + &__counter { + margin-right: 0; + margin-left: 11px; + + .status__action-bar-button { + margin-right: 0; + margin-left: 4px; + } + } + } + .status__action-bar-button { float: right; margin-right: 0; @@ -285,4 +298,18 @@ body.rtl { } } } + + .public-layout { + .header { + .nav-button { + margin-left: 8px; + margin-right: 0; + } + } + + .public-account-header__tabs { + margin-left: 0; + margin-right: 20px; + } + } } diff --git a/app/javascript/flavours/glitch/styles/tables.scss b/app/javascript/flavours/glitch/styles/tables.scss index fa876e603..9fd0b95bb 100644 --- a/app/javascript/flavours/glitch/styles/tables.scss +++ b/app/javascript/flavours/glitch/styles/tables.scss @@ -90,7 +90,7 @@ } samp { - font-family: 'mastodon-font-monospace', monospace; + font-family: $font-monospace, monospace; } button.table-action-link { diff --git a/app/javascript/flavours/glitch/styles/variables.scss b/app/javascript/flavours/glitch/styles/variables.scss index 715ecf98f..1ed1a5778 100644 --- a/app/javascript/flavours/glitch/styles/variables.scss +++ b/app/javascript/flavours/glitch/styles/variables.scss @@ -51,6 +51,10 @@ $media-modal-media-max-height: 80%; $no-gap-breakpoint: 415px; +$font-sans-serif: 'mastodon-font-sans-serif' !default; +$font-display: 'mastodon-font-display' !default; +$font-monospace: 'mastodon-font-monospace' !default; + // Avatar border size (8% default, 100% for rounded avatars) $ui-avatar-border-size: 8%; diff --git a/app/javascript/flavours/glitch/util/content_warning.js b/app/javascript/flavours/glitch/util/content_warning.js index 29e221c8e..5e874a49c 100644 --- a/app/javascript/flavours/glitch/util/content_warning.js +++ b/app/javascript/flavours/glitch/util/content_warning.js @@ -4,6 +4,11 @@ export function autoUnfoldCW (settings, status) { } const rawRegex = settings.getIn(['content_warnings', 'filter']); + + if (!rawRegex) { + return true; + } + let regex = null; try { diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js index fdf004527..0aaf65904 100644 --- a/app/javascript/flavours/glitch/util/initial_state.js +++ b/app/javascript/flavours/glitch/util/initial_state.js @@ -14,6 +14,7 @@ const getMeta = (prop) => initialState && initialState.meta && initialState.meta export const reduceMotion = getMeta('reduce_motion'); export const autoPlayGif = getMeta('auto_play_gif'); export const displaySensitiveMedia = getMeta('display_sensitive_media'); +export const displayMedia = getMeta('display_media') || (getMeta('display_sensitive_media') ? 'show_all' : 'default'); export const unfollowModal = getMeta('unfollow_modal'); export const boostModal = getMeta('boost_modal'); export const favouriteModal = getMeta('favourite_modal'); |