diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js
index e0d591ff69..9f47abfefd 100644
--- a/app/javascript/flavours/glitch/components/status.js
+++ b/app/javascript/flavours/glitch/components/status.js
@@ -13,6 +13,7 @@ import { MediaGallery, Video } from 'flavours/glitch/util/async-components';
import { HotKeys } from 'react-hotkeys';
import NotificationOverlayContainer from 'flavours/glitch/features/notifications/containers/overlay_container';
import classNames from 'classnames';
+import { autoUnfoldCW } from 'flavours/glitch/util/content_warning';
// We use the component (and not the container) since we do not want
// to use the progress bar to show download progress
@@ -56,7 +57,7 @@ export default class Status extends ImmutablePureComponent {
state = {
isCollapsed: false,
autoCollapsed: false,
- isExpanded: this.props.settings.getIn(['content_warnings', 'auto_unfold']),
+ isExpanded: undefined,
}
// Avoid checking props that are functions (and whose equality will always
@@ -124,6 +125,17 @@ export default class Status extends ImmutablePureComponent {
updated = true;
}
+ if (nextProps.expanded === undefined &&
+ prevState.isExpanded === undefined &&
+ update.isExpanded === undefined
+ ) {
+ const isExpanded = autoUnfoldCW(nextProps.settings, nextProps.status);
+ if (isExpanded !== undefined) {
+ update.isExpanded = isExpanded;
+ updated = true;
+ }
+ }
+
return updated ? update : 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 37396d970c..0db49ba5d2 100644
--- a/app/javascript/flavours/glitch/features/local_settings/page/index.js
+++ b/app/javascript/flavours/glitch/features/local_settings/page/index.js
@@ -17,6 +17,7 @@ const messages = defineMessages({
side_arm_keep: { id: 'settings.side_arm_reply_mode.keep', defaultMessage: 'Keep secondary toot button to set privacy' },
side_arm_copy: { id: 'settings.side_arm_reply_mode.copy', defaultMessage: 'Copy privacy setting of the toot being replied to' },
side_arm_restrict: { id: 'settings.side_arm_reply_mode.restrict', defaultMessage: 'Restrict privacy setting to that of the toot being replied to' },
+ regexp: { id: 'settings.content_warnings.regexp', defaultMessage: 'Regular expression' },
});
@injectIntl
@@ -122,7 +123,7 @@ export default class LocalSettingsPage extends React.PureComponent {
),
- ({ onChange, settings }) => (
+ ({ intl, onChange, settings }) => (
+
+
+
),
({ onChange, settings }) => (
diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js
index 060f2f345f..3d309976a3 100644
--- a/app/javascript/flavours/glitch/features/status/index.js
+++ b/app/javascript/flavours/glitch/features/status/index.js
@@ -38,6 +38,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys';
import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/util/initial_state';
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from 'flavours/glitch/util/fullscreen';
+import { autoUnfoldCW } from 'flavours/glitch/util/content_warning';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@@ -82,7 +83,7 @@ export default class Status extends ImmutablePureComponent {
state = {
fullscreen: false,
- isExpanded: this.props.settings.getIn(['content_warnings', 'auto_unfold']),
+ isExpanded: undefined,
threadExpanded: undefined,
};
@@ -95,9 +96,14 @@ export default class Status extends ImmutablePureComponent {
}
componentWillReceiveProps (nextProps) {
+ if (this.state.isExpanded === undefined) {
+ const isExpanded = autoUnfoldCW(nextProps.settings, nextProps.status);
+ if (isExpanded !== undefined) this.setState({ isExpanded: isExpanded });
+ }
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
this._scrolledIntoView = false;
this.props.dispatch(fetchStatus(nextProps.params.statusId));
+ this.setState({ isExpanded: autoUnfoldCW(nextProps.settings, nextProps.status) });
}
}
diff --git a/app/javascript/flavours/glitch/reducers/local_settings.js b/app/javascript/flavours/glitch/reducers/local_settings.js
index ce33cac834..063ae39437 100644
--- a/app/javascript/flavours/glitch/reducers/local_settings.js
+++ b/app/javascript/flavours/glitch/reducers/local_settings.js
@@ -16,6 +16,7 @@ const initialState = ImmutableMap({
confirm_missing_media_description: false,
content_warnings : ImmutableMap({
auto_unfold : false,
+ filter : null,
}),
collapsed : ImmutableMap({
enabled : true,
diff --git a/app/javascript/flavours/glitch/util/content_warning.js b/app/javascript/flavours/glitch/util/content_warning.js
new file mode 100644
index 0000000000..29e221c8e3
--- /dev/null
+++ b/app/javascript/flavours/glitch/util/content_warning.js
@@ -0,0 +1,19 @@
+export function autoUnfoldCW (settings, status) {
+ if (!settings.getIn(['content_warnings', 'auto_unfold'])) {
+ return false;
+ }
+
+ const rawRegex = settings.getIn(['content_warnings', 'filter']);
+ let regex = null;
+
+ try {
+ regex = rawRegex && new RegExp(rawRegex.trim(), 'i');
+ } catch (e) {
+ // Bad regex, don't affect filters
+ }
+
+ if (!(status && regex)) {
+ return undefined;
+ }
+ return !regex.test(status.get('spoiler_text'));
+}