diff --git a/app/javascript/flavours/glitch/actions/importer/normalizer.js b/app/javascript/flavours/glitch/actions/importer/normalizer.js
index bda15a9b085..c38af196af9 100644
--- a/app/javascript/flavours/glitch/actions/importer/normalizer.js
+++ b/app/javascript/flavours/glitch/actions/importer/normalizer.js
@@ -1,7 +1,6 @@
import escapeTextContentForBrowser from 'escape-html';
import emojify from 'flavours/glitch/util/emoji';
import { unescapeHTML } from 'flavours/glitch/util/html';
-import { expandSpoilers } from 'flavours/glitch/util/initial_state';
const domParser = new DOMParser();
diff --git a/app/javascript/flavours/glitch/actions/local_settings.js b/app/javascript/flavours/glitch/actions/local_settings.js
index 28660a4e82f..856674eb3c9 100644
--- a/app/javascript/flavours/glitch/actions/local_settings.js
+++ b/app/javascript/flavours/glitch/actions/local_settings.js
@@ -1,4 +1,46 @@
+import { expandSpoilers, disableSwiping } from 'flavours/glitch/util/initial_state';
+import { openModal } from './modal';
+
export const LOCAL_SETTING_CHANGE = 'LOCAL_SETTING_CHANGE';
+export const LOCAL_SETTING_DELETE = 'LOCAL_SETTING_DELETE';
+
+export function checkDeprecatedLocalSettings() {
+ return (dispatch, getState) => {
+ const local_auto_unfold = getState().getIn(['local_settings', 'content_warnings', 'auto_unfold']);
+ const local_swipe_to_change_columns = getState().getIn(['local_settings', 'swipe_to_change_columns']);
+ let changed_settings = [];
+
+ if (local_auto_unfold !== null && local_auto_unfold !== undefined) {
+ if (local_auto_unfold === expandSpoilers) {
+ dispatch(deleteLocalSetting(['content_warnings', 'auto_unfold']));
+ } else {
+ changed_settings.push('user_setting_expand_spoilers');
+ }
+ }
+
+ if (local_swipe_to_change_columns !== null && local_swipe_to_change_columns !== undefined) {
+ if (local_swipe_to_change_columns === !disableSwiping) {
+ dispatch(deleteLocalSetting(['swipe_to_change_columns']));
+ } else {
+ changed_settings.push('user_setting_disable_swiping');
+ }
+ }
+
+ if (changed_settings.length > 0) {
+ dispatch(openModal('DEPRECATED_SETTINGS', {
+ settings: changed_settings,
+ onConfirm: () => dispatch(clearDeprecatedLocalSettings()),
+ }));
+ }
+ };
+};
+
+export function clearDeprecatedLocalSettings() {
+ return (dispatch) => {
+ dispatch(deleteLocalSetting(['content_warnings', 'auto_unfold']));
+ dispatch(deleteLocalSetting(['swipe_to_change_columns']));
+ };
+};
export function changeLocalSetting(key, value) {
return dispatch => {
@@ -12,6 +54,17 @@ export function changeLocalSetting(key, value) {
};
};
+export function deleteLocalSetting(key) {
+ return dispatch => {
+ dispatch({
+ type: LOCAL_SETTING_DELETE,
+ key,
+ });
+
+ dispatch(saveLocalSettings());
+ };
+};
+
// __TODO :__
// Right now `saveLocalSettings()` doesn't keep track of which user
// is currently signed in, but it might be better to give each user
diff --git a/app/javascript/flavours/glitch/components/modal_root.js b/app/javascript/flavours/glitch/components/modal_root.js
index 0595f6a0e5b..056277447a3 100644
--- a/app/javascript/flavours/glitch/components/modal_root.js
+++ b/app/javascript/flavours/glitch/components/modal_root.js
@@ -55,6 +55,10 @@ export default class ModalRoot extends React.PureComponent {
window.addEventListener('keyup', this.handleKeyUp, false);
window.addEventListener('keydown', this.handleKeyDown, false);
this.history = this.context.router ? this.context.router.history : createBrowserHistory();
+
+ if (this.props.children) {
+ this._handleModalOpen();
+ }
}
componentWillReceiveProps (nextProps) {
diff --git a/app/javascript/flavours/glitch/containers/mastodon.js b/app/javascript/flavours/glitch/containers/mastodon.js
index de8ea8ee2fd..989e37024a9 100644
--- a/app/javascript/flavours/glitch/containers/mastodon.js
+++ b/app/javascript/flavours/glitch/containers/mastodon.js
@@ -8,6 +8,7 @@ import UI from 'flavours/glitch/features/ui';
import { fetchCustomEmojis } from 'flavours/glitch/actions/custom_emojis';
import { hydrateStore } from 'flavours/glitch/actions/store';
import { connectUserStream } from 'flavours/glitch/actions/streaming';
+import { checkDeprecatedLocalSettings } from 'flavours/glitch/actions/local_settings';
import { IntlProvider, addLocaleData } from 'react-intl';
import { getLocale } from 'locales';
import initialState from 'flavours/glitch/util/initial_state';
@@ -20,6 +21,9 @@ export const store = configureStore();
const hydrateAction = hydrateStore(initialState);
store.dispatch(hydrateAction);
+// check for deprecated local settings
+store.dispatch(checkDeprecatedLocalSettings());
+
// load custom emojis
store.dispatch(fetchCustomEmojis());
diff --git a/app/javascript/flavours/glitch/features/getting_started/components/announcements.js b/app/javascript/flavours/glitch/features/getting_started/components/announcements.js
index 2f6d2de5cdc..f7097e2ec1b 100644
--- a/app/javascript/flavours/glitch/features/getting_started/components/announcements.js
+++ b/app/javascript/flavours/glitch/features/getting_started/components/announcements.js
@@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
import IconButton from 'flavours/glitch/components/icon_button';
import Icon from 'flavours/glitch/components/icon';
import { defineMessages, injectIntl, FormattedMessage, FormattedDate } from 'react-intl';
-import { autoPlayGif, reduceMotion } from 'flavours/glitch/util/initial_state';
+import { autoPlayGif, reduceMotion, disableSwiping } from 'flavours/glitch/util/initial_state';
import elephantUIPlane from 'mastodon/../images/elephant_ui_plane.svg';
import { mascot } from 'flavours/glitch/util/initial_state';
import unicodeMapping from 'flavours/glitch/util/emoji/emoji_unicode_mapping_light';
@@ -430,6 +430,7 @@ class Announcements extends ImmutablePureComponent {
removeReaction={this.props.removeReaction}
intl={intl}
selected={index === idx}
+ disabled={disableSwiping}
/>
))}
diff --git a/app/javascript/flavours/glitch/features/local_settings/page/deprecated_item/index.js b/app/javascript/flavours/glitch/features/local_settings/page/deprecated_item/index.js
new file mode 100644
index 00000000000..362bd97c0a0
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/local_settings/page/deprecated_item/index.js
@@ -0,0 +1,83 @@
+// Package imports
+import React from 'react';
+import PropTypes from 'prop-types';
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+export default class LocalSettingsPageItem extends React.PureComponent {
+
+ static propTypes = {
+ children: PropTypes.node.isRequired,
+ id: PropTypes.string.isRequired,
+ options: PropTypes.arrayOf(PropTypes.shape({
+ value: PropTypes.string.isRequired,
+ message: PropTypes.string.isRequired,
+ hint: PropTypes.string,
+ })),
+ value: PropTypes.any,
+ placeholder: PropTypes.string,
+ };
+
+ render () {
+ const { id, options, children, placeholder, value } = this.props;
+
+ if (options && options.length > 0) {
+ const currentValue = value;
+ const optionElems = options && options.length > 0 && options.map((opt) => {
+ let optionId = `${id}--${opt.value}`;
+ return (
+
+ );
+ });
+ return (
+
-
-
+
+
+
+
+ )
+ }}
+ />
+
+
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 5a68523f62d..6b24e41435d 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
@@ -21,6 +21,7 @@ export default class LocalSettingsPageItem extends React.PureComponent {
})),
settings: ImmutablePropTypes.map.isRequired,
placeholder: PropTypes.string,
+ disabled: PropTypes.bool,
};
handleChange = e => {
@@ -33,8 +34,8 @@ export default class LocalSettingsPageItem extends React.PureComponent {
render () {
const { handleChange } = this;
- const { settings, item, id, options, children, dependsOn, dependsOnNot, placeholder } = this.props;
- let enabled = true;
+ const { settings, item, id, options, children, dependsOn, dependsOnNot, placeholder, disabled } = this.props;
+ let enabled = !disabled;
if (dependsOn) {
for (let i = 0; i < dependsOn.length; i++) {
diff --git a/app/javascript/flavours/glitch/features/ui/components/columns_area.js b/app/javascript/flavours/glitch/features/ui/components/columns_area.js
index 6cbcd81ee06..bfb1ae4057d 100644
--- a/app/javascript/flavours/glitch/features/ui/components/columns_area.js
+++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.js
@@ -8,6 +8,8 @@ import ReactSwipeableViews from 'react-swipeable-views';
import TabsBar, { links, getIndex, getLink } from './tabs_bar';
import { Link } from 'react-router-dom';
+import { disableSwiping } from 'flavours/glitch/util/initial_state';
+
import BundleContainer from '../containers/bundle_container';
import ColumnLoading from './column_loading';
import DrawerLoading from './drawer_loading';
@@ -63,7 +65,6 @@ class ColumnsArea extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
columns: ImmutablePropTypes.list.isRequired,
- swipeToChangeColumns: PropTypes.bool,
singleColumn: PropTypes.bool,
children: PropTypes.node,
navbarUnder: PropTypes.bool,
@@ -210,7 +211,7 @@ class ColumnsArea extends ImmutablePureComponent {
}
render () {
- const { columns, children, singleColumn, swipeToChangeColumns, intl, navbarUnder, openSettings } = this.props;
+ const { columns, children, singleColumn, intl, navbarUnder, openSettings } = this.props;
const { shouldAnimate, renderComposePanel } = this.state;
const columnIndex = getIndex(this.context.router.history.location.pathname);
@@ -219,7 +220,7 @@ class ColumnsArea extends ImmutablePureComponent {
const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null :
;
const content = columnIndex !== -1 ? (
-
+
{links.map(this.renderView)}
) : (
diff --git a/app/javascript/flavours/glitch/features/ui/components/deprecated_settings_modal.js b/app/javascript/flavours/glitch/features/ui/components/deprecated_settings_modal.js
new file mode 100644
index 00000000000..9cb5a30b91e
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/ui/components/deprecated_settings_modal.js
@@ -0,0 +1,86 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
+import { preferenceLink } from 'flavours/glitch/util/backend_links';
+import Button from 'flavours/glitch/components/button';
+import Icon from 'flavours/glitch/components/icon';
+import illustration from 'flavours/glitch/images/logo_warn_glitch.svg';
+
+const messages = defineMessages({
+ discardChanges: { id: 'confirmations.deprecated_settings.confirm', defaultMessage: 'Use Mastodon preferences' },
+ user_setting_expand_spoilers: { id: 'settings.enable_content_warnings_auto_unfold', defaultMessage: 'Automatically unfold content-warnings' },
+ user_setting_disable_swiping: { id: 'settings.swipe_to_change_columns', defaultMessage: 'Allow swiping to change columns (Mobile only)' },
+});
+
+export default @injectIntl
+class DeprecatedSettingsModal extends React.PureComponent {
+
+ static propTypes = {
+ settings: ImmutablePropTypes.list.isRequired,
+ onClose: PropTypes.func.isRequired,
+ onConfirm: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
+ };
+
+ componentDidMount() {
+ this.button.focus();
+ }
+
+ handleClick = () => {
+ this.props.onConfirm();
+ this.props.onClose();
+ }
+
+ setRef = (c) => {
+ this.button = c;
+ }
+
+ render () {
+ const { settings, intl } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+ ),
+ preferences: (
+
+
+
+ ),
+ }}
+ />
+
+
+
+ { settings.map((setting_name) => (
+ -
+
+
+ )) }
+
+
+
+
+
+
+ );
+ }
+
+}
diff --git a/app/javascript/flavours/glitch/features/ui/components/media_modal.js b/app/javascript/flavours/glitch/features/ui/components/media_modal.js
index 6974aab26c1..baa5ff2756e 100644
--- a/app/javascript/flavours/glitch/features/ui/components/media_modal.js
+++ b/app/javascript/flavours/glitch/features/ui/components/media_modal.js
@@ -12,6 +12,7 @@ import Icon from 'flavours/glitch/components/icon';
import GIFV from 'flavours/glitch/components/gifv';
import Footer from 'flavours/glitch/features/picture_in_picture/components/footer';
import { getAverageFromBlurhash } from 'flavours/glitch/blurhash';
+import { disableSwiping } from 'flavours/glitch/util/initial_state';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
@@ -227,6 +228,7 @@ class MediaModal extends ImmutablePureComponent {
onChangeIndex={this.handleSwipe}
onTransitionEnd={this.handleTransitionEnd}
index={index}
+ disabled={disableSwiping}
>
{content}
diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js
index a975c4013d2..8f18d93b737 100644
--- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js
+++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js
@@ -14,6 +14,7 @@ import AudioModal from './audio_modal';
import DoodleModal from './doodle_modal';
import ConfirmationModal from './confirmation_modal';
import FocalPointModal from './focal_point_modal';
+import DeprecatedSettingsModal from './deprecated_settings_modal';
import {
OnboardingModal,
MuteModal,
@@ -40,6 +41,7 @@ const MODAL_COMPONENTS = {
'BLOCK': BlockModal,
'REPORT': ReportModal,
'SETTINGS': SettingsModal,
+ 'DEPRECATED_SETTINGS': () => Promise.resolve({ default: DeprecatedSettingsModal }),
'ACTIONS': () => Promise.resolve({ default: ActionsModal }),
'EMBED': EmbedModal,
'LIST_EDITOR': ListEditor,
diff --git a/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js b/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js
index b69842cd6bd..1107be740d7 100644
--- a/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js
+++ b/app/javascript/flavours/glitch/features/ui/containers/columns_area_container.js
@@ -4,7 +4,6 @@ import { openModal } from 'flavours/glitch/actions/modal';
const mapStateToProps = state => ({
columns: state.getIn(['settings', 'columns']),
- swipeToChangeColumns: state.getIn(['local_settings', 'swipe_to_change_columns']),
});
const mapDispatchToProps = dispatch => ({
diff --git a/app/javascript/flavours/glitch/images/logo_warn_glitch.svg b/app/javascript/flavours/glitch/images/logo_warn_glitch.svg
new file mode 100644
index 00000000000..32c5854eed7
--- /dev/null
+++ b/app/javascript/flavours/glitch/images/logo_warn_glitch.svg
@@ -0,0 +1,49 @@
+
+
diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js
index c115cad6bac..a16c337fcac 100644
--- a/app/javascript/flavours/glitch/reducers/local_settings.js
+++ b/app/javascript/flavours/glitch/reducers/local_settings.js
@@ -3,13 +3,12 @@ import { Map as ImmutableMap } from 'immutable';
// Our imports.
import { STORE_HYDRATE } from 'flavours/glitch/actions/store';
-import { LOCAL_SETTING_CHANGE } from 'flavours/glitch/actions/local_settings';
+import { LOCAL_SETTING_CHANGE, LOCAL_SETTING_DELETE } from 'flavours/glitch/actions/local_settings';
const initialState = ImmutableMap({
layout : 'auto',
stretch : true,
navbar_under : false,
- swipe_to_change_columns: true,
side_arm : 'none',
side_arm_reply_mode : 'keep',
show_reply_count : false,
@@ -26,7 +25,6 @@ const initialState = ImmutableMap({
tag_misleading_links: true,
rewrite_mentions: 'no',
content_warnings : ImmutableMap({
- auto_unfold : false,
filter : null,
}),
collapsed : ImmutableMap({
@@ -66,6 +64,8 @@ export default function localSettings(state = initialState, action) {
return hydrate(state, action.state.get('local_settings'));
case LOCAL_SETTING_CHANGE:
return state.setIn(action.key, action.value);
+ case LOCAL_SETTING_DELETE:
+ return state.deleteIn(action.key);
default:
return state;
}
diff --git a/app/javascript/flavours/glitch/styles/components/local_settings.scss b/app/javascript/flavours/glitch/styles/components/local_settings.scss
index 0b7a74575cb..db2b9f154e1 100644
--- a/app/javascript/flavours/glitch/styles/components/local_settings.scss
+++ b/app/javascript/flavours/glitch/styles/components/local_settings.scss
@@ -98,6 +98,18 @@
.glitch.local-settings__page__item {
margin-bottom: 2px;
+
+ .hint a {
+ color: $lighter-text-color;
+ font-weight: 500;
+ text-decoration: underline;
+
+ &:active,
+ &:focus,
+ &:hover {
+ text-decoration: none;
+ }
+ }
}
.glitch.local-settings__page__item.string,
@@ -120,3 +132,29 @@
}
}
}
+
+.deprecated-settings-label {
+ white-space: nowrap;
+}
+
+.deprecated-settings-info {
+ text-align: start;
+
+ ul {
+ padding: 10px;
+ margin-left: 12px;
+ list-style: disc inside;
+ }
+
+ a {
+ color: $lighter-text-color;
+ font-weight: 500;
+ text-decoration: underline;
+
+ &:active,
+ &:focus,
+ &:hover {
+ text-decoration: none;
+ }
+ }
+}
diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss
index 61c292b1938..90e0da02a9c 100644
--- a/app/javascript/flavours/glitch/styles/components/modal.scss
+++ b/app/javascript/flavours/glitch/styles/components/modal.scss
@@ -1279,3 +1279,10 @@
pointer-events: auto;
z-index: 9999;
}
+
+img.modal-warning {
+ display: block;
+ margin: auto;
+ margin-bottom: 15px;
+ width: 60px;
+}
diff --git a/app/javascript/flavours/glitch/util/backend_links.js b/app/javascript/flavours/glitch/util/backend_links.js
index 2e5111a7f45..5b2dd8dbff0 100644
--- a/app/javascript/flavours/glitch/util/backend_links.js
+++ b/app/javascript/flavours/glitch/util/backend_links.js
@@ -7,3 +7,12 @@ export const statusAdminLink = (account_id, status_id) => `/admin/accounts/${acc
export const filterEditLink = (id) => `/filters/${id}/edit`;
export const relationshipsLink = '/relationships';
export const securityLink = '/auth/edit';
+export const preferenceLink = (setting_name) => {
+ switch (setting_name) {
+ case 'user_setting_expand_spoilers':
+ case 'user_setting_disable_swiping':
+ return `/settings/preferences/appearance#${setting_name}`;
+ default:
+ return preferencesLink;
+ }
+};
diff --git a/app/javascript/flavours/glitch/util/content_warning.js b/app/javascript/flavours/glitch/util/content_warning.js
index 5e874a49c0c..baeb97881f6 100644
--- a/app/javascript/flavours/glitch/util/content_warning.js
+++ b/app/javascript/flavours/glitch/util/content_warning.js
@@ -1,5 +1,7 @@
+import { expandSpoilers } from 'flavours/glitch/util/initial_state';
+
export function autoUnfoldCW (settings, status) {
- if (!settings.getIn(['content_warnings', 'auto_unfold'])) {
+ if (!expandSpoilers) {
return false;
}
diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js
index 7154e020be4..5cbf8f6c360 100644
--- a/app/javascript/flavours/glitch/util/initial_state.js
+++ b/app/javascript/flavours/glitch/util/initial_state.js
@@ -13,8 +13,8 @@ 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 expandSpoilers = getMeta('expand_spoilers');
export const unfollowModal = getMeta('unfollow_modal');
export const boostModal = getMeta('boost_modal');
export const favouriteModal = getMeta('favourite_modal');
@@ -37,5 +37,6 @@ export const useBlurhash = getMeta('use_blurhash');
export const usePendingItems = getMeta('use_pending_items');
export const useSystemEmojiFont = getMeta('system_emoji_font');
export const showTrends = getMeta('trends');
+export const disableSwiping = getMeta('disable_swiping');
export default initialState;