about summary refs log tree commit diff
path: root/app/javascript/flavours
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours')
-rw-r--r--app/javascript/flavours/glitch/components/media_gallery.js4
-rw-r--r--app/javascript/flavours/glitch/components/permalink.js15
-rw-r--r--app/javascript/flavours/glitch/components/scrollable_list.js1
-rw-r--r--app/javascript/flavours/glitch/containers/status_container.js15
-rw-r--r--app/javascript/flavours/glitch/features/account_gallery/components/media_item.js40
-rw-r--r--app/javascript/flavours/glitch/features/account_gallery/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/blocks/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/favourites/index.js1
-rw-r--r--app/javascript/flavours/glitch/features/follow_requests/index.js1
-rw-r--r--app/javascript/flavours/glitch/features/followers/index.js1
-rw-r--r--app/javascript/flavours/glitch/features/following/index.js3
-rw-r--r--app/javascript/flavours/glitch/features/getting_started/index.js9
-rw-r--r--app/javascript/flavours/glitch/features/local_settings/navigation/index.js8
-rw-r--r--app/javascript/flavours/glitch/features/local_settings/navigation/item/index.js8
-rw-r--r--app/javascript/flavours/glitch/features/local_settings/page/index.js32
-rw-r--r--app/javascript/flavours/glitch/features/local_settings/page/item/index.js95
-rw-r--r--app/javascript/flavours/glitch/features/mutes/index.js1
-rw-r--r--app/javascript/flavours/glitch/features/reblogs/index.js1
-rw-r--r--app/javascript/flavours/glitch/features/status/index.js18
-rw-r--r--app/javascript/flavours/glitch/features/ui/components/onboarding_modal.js2
-rw-r--r--app/javascript/flavours/glitch/features/ui/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/video/index.js4
-rw-r--r--app/javascript/flavours/glitch/styles/about.scss46
-rw-r--r--app/javascript/flavours/glitch/styles/admin.scss2
-rw-r--r--app/javascript/flavours/glitch/styles/basics.scss6
-rw-r--r--app/javascript/flavours/glitch/styles/components/accounts.scss11
-rw-r--r--app/javascript/flavours/glitch/styles/components/local_settings.scss50
-rw-r--r--app/javascript/flavours/glitch/styles/containers.scss4
-rw-r--r--app/javascript/flavours/glitch/styles/dashboard.scss2
-rw-r--r--app/javascript/flavours/glitch/styles/forms.scss8
-rw-r--r--app/javascript/flavours/glitch/styles/mastodon-light/diff.scss3
-rw-r--r--app/javascript/flavours/glitch/styles/rtl.scss27
-rw-r--r--app/javascript/flavours/glitch/styles/tables.scss2
-rw-r--r--app/javascript/flavours/glitch/styles/variables.scss4
-rw-r--r--app/javascript/flavours/glitch/util/content_warning.js5
-rw-r--r--app/javascript/flavours/glitch/util/initial_state.js1
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>&nbsp;•&nbsp;
-                <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>&nbsp;•&nbsp;
-                <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');