Merge pull request #1815 from ClearlyClaire/glitch-soc/features/upstream-cw-reveal
Add option to share CW toggle state across instances of a postlolsob-rspec
commit
1b0e9f2136
|
@ -63,7 +63,7 @@ export function importFetchedStatuses(statuses) {
|
|||
const polls = [];
|
||||
|
||||
function processStatus(status) {
|
||||
pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id])));
|
||||
pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id]), getState().get('local_settings')));
|
||||
pushUnique(accounts, status.account);
|
||||
|
||||
if (status.reblog && status.reblog.id) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import escapeTextContentForBrowser from 'escape-html';
|
||||
import emojify from 'flavours/glitch/util/emoji';
|
||||
import { unescapeHTML } from 'flavours/glitch/util/html';
|
||||
import { autoHideCW } from 'flavours/glitch/util/content_warning';
|
||||
|
||||
const domParser = new DOMParser();
|
||||
|
||||
|
@ -41,7 +42,7 @@ export function normalizeAccount(account) {
|
|||
return account;
|
||||
}
|
||||
|
||||
export function normalizeStatus(status, normalOldStatus) {
|
||||
export function normalizeStatus(status, normalOldStatus, settings) {
|
||||
const normalStatus = { ...status };
|
||||
normalStatus.account = status.account.id;
|
||||
|
||||
|
@ -60,6 +61,7 @@ export function normalizeStatus(status, normalOldStatus) {
|
|||
normalStatus.search_index = normalOldStatus.get('search_index');
|
||||
normalStatus.contentHtml = normalOldStatus.get('contentHtml');
|
||||
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
|
||||
normalStatus.hidden = normalOldStatus.get('hidden');
|
||||
} else {
|
||||
const spoilerText = normalStatus.spoiler_text || '';
|
||||
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
|
||||
|
@ -68,6 +70,7 @@ export function normalizeStatus(status, normalOldStatus) {
|
|||
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
|
||||
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
|
||||
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
|
||||
normalStatus.hidden = (spoilerText.length > 0 || normalStatus.sensitive) && autoHideCW(settings, spoilerText);
|
||||
}
|
||||
|
||||
return normalStatus;
|
||||
|
|
|
@ -24,6 +24,10 @@ export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST';
|
|||
export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
|
||||
export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
|
||||
|
||||
export const STATUS_REVEAL = 'STATUS_REVEAL';
|
||||
export const STATUS_HIDE = 'STATUS_HIDE';
|
||||
export const STATUS_COLLAPSE = 'STATUS_COLLAPSE';
|
||||
|
||||
export const REDRAFT = 'REDRAFT';
|
||||
|
||||
export const STATUS_FETCH_SOURCE_REQUEST = 'STATUS_FETCH_SOURCE_REQUEST';
|
||||
|
@ -277,3 +281,33 @@ export function unmuteStatusFail(id, error) {
|
|||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export function hideStatus(ids) {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
}
|
||||
|
||||
return {
|
||||
type: STATUS_HIDE,
|
||||
ids,
|
||||
};
|
||||
};
|
||||
|
||||
export function revealStatus(ids) {
|
||||
if (!Array.isArray(ids)) {
|
||||
ids = [ids];
|
||||
}
|
||||
|
||||
return {
|
||||
type: STATUS_REVEAL,
|
||||
ids,
|
||||
};
|
||||
};
|
||||
|
||||
export function toggleStatusCollapse(id, isCollapsed) {
|
||||
return {
|
||||
type: STATUS_COLLAPSE,
|
||||
id,
|
||||
isCollapsed,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ class Status extends ImmutablePureComponent {
|
|||
onBlock: PropTypes.func,
|
||||
onEmbed: PropTypes.func,
|
||||
onHeightChange: PropTypes.func,
|
||||
onToggleHidden: PropTypes.func,
|
||||
muted: PropTypes.bool,
|
||||
collapse: PropTypes.bool,
|
||||
hidden: PropTypes.bool,
|
||||
unread: PropTypes.bool,
|
||||
prepend: PropTypes.string,
|
||||
|
@ -121,7 +121,6 @@ class Status extends ImmutablePureComponent {
|
|||
'settings',
|
||||
'prepend',
|
||||
'muted',
|
||||
'collapse',
|
||||
'notification',
|
||||
'hidden',
|
||||
'expanded',
|
||||
|
@ -149,14 +148,14 @@ class Status extends ImmutablePureComponent {
|
|||
let updated = false;
|
||||
|
||||
// Make sure the state mirrors props we track…
|
||||
if (nextProps.collapse !== prevState.collapseProp) {
|
||||
update.collapseProp = nextProps.collapse;
|
||||
updated = true;
|
||||
}
|
||||
if (nextProps.expanded !== prevState.expandedProp) {
|
||||
update.expandedProp = nextProps.expanded;
|
||||
updated = true;
|
||||
}
|
||||
if (nextProps.status?.get('hidden') !== prevState.statusPropHidden) {
|
||||
update.statusPropHidden = nextProps.status?.get('hidden');
|
||||
updated = true;
|
||||
}
|
||||
|
||||
// Update state based on new props
|
||||
if (!nextProps.settings.getIn(['collapsed', 'enabled'])) {
|
||||
|
@ -164,14 +163,19 @@ class Status extends ImmutablePureComponent {
|
|||
update.isCollapsed = false;
|
||||
updated = true;
|
||||
}
|
||||
} else if (
|
||||
nextProps.collapse !== prevState.collapseProp &&
|
||||
nextProps.collapse !== undefined
|
||||
}
|
||||
|
||||
// Handle uncollapsing toots when the shared CW state is expanded
|
||||
if (nextProps.settings.getIn(['content_warnings', 'shared_state']) &&
|
||||
nextProps.status?.get('spoiler_text')?.length && nextProps.status?.get('hidden') === false &&
|
||||
prevState.statusPropHidden !== false && prevState.isCollapsed
|
||||
) {
|
||||
update.isCollapsed = nextProps.collapse;
|
||||
if (nextProps.collapse) update.isExpanded = false;
|
||||
update.isCollapsed = false;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
// The “expanded” prop is used to one-off change the local state.
|
||||
// It's used in the thread view when unfolding/re-folding all CWs at once.
|
||||
if (nextProps.expanded !== prevState.expandedProp &&
|
||||
nextProps.expanded !== undefined
|
||||
) {
|
||||
|
@ -180,15 +184,9 @@ 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;
|
||||
}
|
||||
if (prevState.isExpanded === undefined && update.isExpanded === undefined) {
|
||||
update.isExpanded = autoUnfoldCW(nextProps.settings, nextProps.status);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (nextProps.status && nextProps.status.get('id') !== prevState.statusId) {
|
||||
|
@ -243,22 +241,18 @@ class Status extends ImmutablePureComponent {
|
|||
|
||||
const autoCollapseSettings = settings.getIn(['collapsed', 'auto']);
|
||||
|
||||
if (function () {
|
||||
switch (true) {
|
||||
case !!collapse:
|
||||
case !!autoCollapseSettings.get('all'):
|
||||
case autoCollapseSettings.get('notifications') && !!muted:
|
||||
case autoCollapseSettings.get('lengthy') && node.clientHeight > (
|
||||
status.get('media_attachments').size && !muted ? 650 : 400
|
||||
):
|
||||
case autoCollapseSettings.get('reblogs') && prepend === 'reblogged_by':
|
||||
case autoCollapseSettings.get('replies') && status.get('in_reply_to_id', null) !== null:
|
||||
case autoCollapseSettings.get('media') && !(status.get('spoiler_text').length) && !!status.get('media_attachments').size:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}()) {
|
||||
// Don't autocollapse if CW state is shared and status is explicitly revealed,
|
||||
// as it could cause surprising changes when receiving notifications
|
||||
if (settings.getIn(['content_warnings', 'shared_state']) && status.get('spoiler_text').length && !status.get('hidden')) return;
|
||||
|
||||
if (collapse ||
|
||||
autoCollapseSettings.get('all') ||
|
||||
(autoCollapseSettings.get('notifications') && muted) ||
|
||||
(autoCollapseSettings.get('lengthy') && node.clientHeight > ((status.get('media_attachments').size && !muted) ? 650 : 400)) ||
|
||||
(autoCollapseSettings.get('reblogs') && prepend === 'reblogged_by') ||
|
||||
(autoCollapseSettings.get('replies') && status.get('in_reply_to_id', null) !== null) ||
|
||||
(autoCollapseSettings.get('media') && !(status.get('spoiler_text').length) && status.get('media_attachments').size > 0)
|
||||
) {
|
||||
this.setCollapsed(true);
|
||||
// Hack to fix timeline jumps on second rendering when auto-collapsing
|
||||
this.setState({ autoCollapsed: true });
|
||||
|
@ -309,16 +303,20 @@ class Status extends ImmutablePureComponent {
|
|||
// is enabled, so we don't have to.
|
||||
setCollapsed = (value) => {
|
||||
if (this.props.settings.getIn(['collapsed', 'enabled'])) {
|
||||
this.setState({ isCollapsed: value });
|
||||
if (value) {
|
||||
this.setExpansion(false);
|
||||
}
|
||||
this.setState({ isCollapsed: value });
|
||||
} else {
|
||||
this.setState({ isCollapsed: false });
|
||||
}
|
||||
}
|
||||
|
||||
setExpansion = (value) => {
|
||||
if (this.props.settings.getIn(['content_warnings', 'shared_state']) && this.props.status.get('hidden') === value) {
|
||||
this.props.onToggleHidden(this.props.status);
|
||||
}
|
||||
|
||||
this.setState({ isExpanded: value });
|
||||
if (value) {
|
||||
this.setCollapsed(false);
|
||||
|
@ -365,7 +363,9 @@ class Status extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
handleExpandedToggle = () => {
|
||||
if (this.props.status.get('spoiler_text')) {
|
||||
if (this.props.settings.getIn(['content_warnings', 'shared_state'])) {
|
||||
this.props.onToggleHidden(this.props.status);
|
||||
} else if (this.props.status.get('spoiler_text')) {
|
||||
this.setExpansion(!this.state.isExpanded);
|
||||
}
|
||||
};
|
||||
|
@ -505,7 +505,7 @@ class Status extends ImmutablePureComponent {
|
|||
usingPiP,
|
||||
...other
|
||||
} = this.props;
|
||||
const { isExpanded, isCollapsed, forceFilter } = this.state;
|
||||
const { isCollapsed, forceFilter } = this.state;
|
||||
let background = null;
|
||||
let attachments = null;
|
||||
|
||||
|
@ -528,6 +528,8 @@ class Status extends ImmutablePureComponent {
|
|||
return null;
|
||||
}
|
||||
|
||||
const isExpanded = settings.getIn(['content_warnings', 'shared_state']) ? !status.get('hidden') : this.state.isExpanded;
|
||||
|
||||
const handlers = {
|
||||
reply: this.handleHotkeyReply,
|
||||
favourite: this.handleHotkeyFavourite,
|
||||
|
|
|
@ -17,7 +17,14 @@ import {
|
|||
pin,
|
||||
unpin,
|
||||
} from 'flavours/glitch/actions/interactions';
|
||||
import { muteStatus, unmuteStatus, deleteStatus, editStatus } from 'flavours/glitch/actions/statuses';
|
||||
import {
|
||||
muteStatus,
|
||||
unmuteStatus,
|
||||
deleteStatus,
|
||||
hideStatus,
|
||||
revealStatus,
|
||||
editStatus
|
||||
} from 'flavours/glitch/actions/statuses';
|
||||
import { initMuteModal } from 'flavours/glitch/actions/mutes';
|
||||
import { initBlockModal } from 'flavours/glitch/actions/blocks';
|
||||
import { initReport } from 'flavours/glitch/actions/reports';
|
||||
|
@ -252,6 +259,14 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
|
|||
}
|
||||
},
|
||||
|
||||
onToggleHidden (status) {
|
||||
if (status.get('hidden')) {
|
||||
dispatch(revealStatus(status.get('id')));
|
||||
} else {
|
||||
dispatch(hideStatus(status.get('id')));
|
||||
}
|
||||
},
|
||||
|
||||
deployPictureInPicture (status, type, mediaProps) {
|
||||
dispatch((_, getState) => {
|
||||
if (getState().getIn(['local_settings', 'media', 'pop_in_player'])) {
|
||||
|
|
|
@ -132,6 +132,8 @@ class Conversation extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
handleShowMore = () => {
|
||||
this.props.onToggleHidden(this.props.lastStatus);
|
||||
|
||||
if (this.props.lastStatus.get('spoiler_text')) {
|
||||
this.setExpansion(!this.state.isExpanded);
|
||||
}
|
||||
|
@ -143,12 +145,13 @@ class Conversation extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
const { accounts, lastStatus, unread, scrollKey, intl } = this.props;
|
||||
const { isExpanded } = this.state;
|
||||
|
||||
if (lastStatus === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isExpanded = this.props.settings.getIn(['content_warnings', 'shared_state']) ? !lastStatus.get('hidden') : this.state.isExpanded;
|
||||
|
||||
const menu = [
|
||||
{ text: intl.formatMessage(messages.open), action: this.handleClick },
|
||||
null,
|
||||
|
|
|
@ -23,6 +23,7 @@ const mapStateToProps = () => {
|
|||
accounts: conversation.get('accounts').map(accountId => state.getIn(['accounts', accountId], null)),
|
||||
unread: conversation.get('unread'),
|
||||
lastStatus: lastStatusId && getStatus(state, { id: lastStatusId }),
|
||||
settings: state.get('local_settings'),
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -303,6 +303,15 @@ class LocalSettingsPage extends React.PureComponent {
|
|||
({ intl, onChange, settings }) => (
|
||||
<div className='glitch local-settings__page content_warnings'>
|
||||
<h1><FormattedMessage id='settings.content_warnings' defaultMessage='Content warnings' /></h1>
|
||||
<LocalSettingsPageItem
|
||||
settings={settings}
|
||||
item={['content_warnings', 'shared_state']}
|
||||
id='mastodon-settings--content_warnings-shared_state'
|
||||
onChange={onChange}
|
||||
>
|
||||
<FormattedMessage id='settings.content_warnings_shared_state' defaultMessage='Show/hide content of all copies at once' />
|
||||
<span className='hint'><FormattedMessage id='settings.content_warnings_shared_state_hint' defaultMessage='Reproduce upstream Mastodon behavior by having the Content Warning button affect all copies of a post at once. This will prevent automatic collapsing of any copy of a toot with unfolded CW' /></span>
|
||||
</LocalSettingsPageItem>
|
||||
<LocalSettingsPageItem
|
||||
settings={settings}
|
||||
item={['content_warnings', 'media_outside']}
|
||||
|
@ -312,38 +321,41 @@ class LocalSettingsPage extends React.PureComponent {
|
|||
<FormattedMessage id='settings.content_warnings_media_outside' defaultMessage='Display media attachments outside content warnings' />
|
||||
<span className='hint'><FormattedMessage id='settings.content_warnings_media_outside_hint' defaultMessage='Reproduce upstream Mastodon behavior by having the Content Warning toggle not affect media attachments' /></span>
|
||||
</LocalSettingsPageItem>
|
||||
<DeprecatedLocalSettingsPageItem
|
||||
id='mastodon-settings--content_warnings-auto_unfold'
|
||||
value={expandSpoilers}
|
||||
>
|
||||
<FormattedMessage id='settings.enable_content_warnings_auto_unfold' defaultMessage='Automatically unfold content-warnings' />
|
||||
<span className='hint'>
|
||||
<FormattedMessage
|
||||
id='settings.deprecated_setting'
|
||||
defaultMessage="This setting is now controlled from Mastodon's {settings_page_link}"
|
||||
values={{
|
||||
settings_page_link: (
|
||||
<a href={preferenceLink('user_setting_expand_spoilers')}>
|
||||
<FormattedMessage
|
||||
id='settings.shared_settings_link'
|
||||
defaultMessage='user preferences'
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</DeprecatedLocalSettingsPageItem>
|
||||
<LocalSettingsPageItem
|
||||
settings={settings}
|
||||
item={['content_warnings', 'filter']}
|
||||
id='mastodon-settings--content_warnings-auto_unfold'
|
||||
onChange={onChange}
|
||||
placeholder={intl.formatMessage(messages.regexp)}
|
||||
disabled={!expandSpoilers}
|
||||
>
|
||||
<FormattedMessage id='settings.content_warnings_filter' defaultMessage='Content warnings to not automatically unfold:' />
|
||||
</LocalSettingsPageItem>
|
||||
<section>
|
||||
<h2><FormattedMessage id='settings.content_warnings_unfold_opts' defaultMessage='Auto-unfolding options' /></h2>
|
||||
<DeprecatedLocalSettingsPageItem
|
||||
id='mastodon-settings--content_warnings-auto_unfold'
|
||||
value={expandSpoilers}
|
||||
>
|
||||
<FormattedMessage id='settings.enable_content_warnings_auto_unfold' defaultMessage='Automatically unfold content-warnings' />
|
||||
<span className='hint'>
|
||||
<FormattedMessage
|
||||
id='settings.deprecated_setting'
|
||||
defaultMessage="This setting is now controlled from Mastodon's {settings_page_link}"
|
||||
values={{
|
||||
settings_page_link: (
|
||||
<a href={preferenceLink('user_setting_expand_spoilers')}>
|
||||
<FormattedMessage
|
||||
id='settings.shared_settings_link'
|
||||
defaultMessage='user preferences'
|
||||
/>
|
||||
</a>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</DeprecatedLocalSettingsPageItem>
|
||||
<LocalSettingsPageItem
|
||||
settings={settings}
|
||||
item={['content_warnings', 'filter']}
|
||||
id='mastodon-settings--content_warnings-auto_unfold'
|
||||
onChange={onChange}
|
||||
placeholder={intl.formatMessage(messages.regexp)}
|
||||
disabled={!expandSpoilers}
|
||||
>
|
||||
<FormattedMessage id='settings.content_warnings_filter' defaultMessage='Content warnings to not automatically unfold:' />
|
||||
</LocalSettingsPageItem>
|
||||
</section>
|
||||
</div>
|
||||
),
|
||||
({ intl, onChange, settings }) => (
|
||||
|
|
|
@ -26,7 +26,14 @@ import {
|
|||
directCompose,
|
||||
} from 'flavours/glitch/actions/compose';
|
||||
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
|
||||
import { muteStatus, unmuteStatus, deleteStatus, editStatus } from 'flavours/glitch/actions/statuses';
|
||||
import {
|
||||
muteStatus,
|
||||
unmuteStatus,
|
||||
deleteStatus,
|
||||
editStatus,
|
||||
hideStatus,
|
||||
revealStatus
|
||||
} from 'flavours/glitch/actions/statuses';
|
||||
import { initMuteModal } from 'flavours/glitch/actions/mutes';
|
||||
import { initBlockModal } from 'flavours/glitch/actions/blocks';
|
||||
import { initReport } from 'flavours/glitch/actions/reports';
|
||||
|
@ -215,11 +222,19 @@ class Status extends ImmutablePureComponent {
|
|||
return updated ? update : null;
|
||||
}
|
||||
|
||||
handleExpandedToggle = () => {
|
||||
if (this.props.status.get('spoiler_text')) {
|
||||
handleToggleHidden = () => {
|
||||
const { status } = this.props;
|
||||
|
||||
if (this.props.settings.getIn(['content_warnings', 'shared_state'])) {
|
||||
if (status.get('hidden')) {
|
||||
this.props.dispatch(revealStatus(status.get('id')));
|
||||
} else {
|
||||
this.props.dispatch(hideStatus(status.get('id')));
|
||||
}
|
||||
} else if (this.props.status.get('spoiler_text')) {
|
||||
this.setExpansion(!this.state.isExpanded);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
handleToggleMediaVisibility = () => {
|
||||
this.setState({ showMedia: !this.state.showMedia });
|
||||
|
@ -354,7 +369,19 @@ class Status extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
handleToggleAll = () => {
|
||||
const { isExpanded } = this.state;
|
||||
const { status, ancestorsIds, descendantsIds, settings } = this.props;
|
||||
const statusIds = [status.get('id')].concat(ancestorsIds.toJS(), descendantsIds.toJS());
|
||||
let { isExpanded } = this.state;
|
||||
|
||||
if (settings.getIn(['content_warnings', 'shared_state']))
|
||||
isExpanded = !status.get('hidden');
|
||||
|
||||
if (!isExpanded) {
|
||||
this.props.dispatch(revealStatus(statusIds));
|
||||
} else {
|
||||
this.props.dispatch(hideStatus(statusIds));
|
||||
}
|
||||
|
||||
this.setState({ isExpanded: !isExpanded, threadExpanded: !isExpanded });
|
||||
}
|
||||
|
||||
|
@ -513,9 +540,8 @@ class Status extends ImmutablePureComponent {
|
|||
|
||||
render () {
|
||||
let ancestors, descendants;
|
||||
const { setExpansion } = this;
|
||||
const { status, settings, ancestorsIds, descendantsIds, intl, domain, multiColumn, usingPiP } = this.props;
|
||||
const { fullscreen, isExpanded } = this.state;
|
||||
const { fullscreen } = this.state;
|
||||
|
||||
if (status === null) {
|
||||
return (
|
||||
|
@ -526,6 +552,8 @@ class Status extends ImmutablePureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
const isExpanded = settings.getIn(['content_warnings', 'shared_state']) ? !status.get('hidden') : this.state.isExpanded;
|
||||
|
||||
if (ancestorsIds && ancestorsIds.size > 0) {
|
||||
ancestors = <div>{this.renderChildren(ancestorsIds)}</div>;
|
||||
}
|
||||
|
@ -543,7 +571,7 @@ class Status extends ImmutablePureComponent {
|
|||
bookmark: this.handleHotkeyBookmark,
|
||||
mention: this.handleHotkeyMention,
|
||||
openProfile: this.handleHotkeyOpenProfile,
|
||||
toggleSpoiler: this.handleExpandedToggle,
|
||||
toggleSpoiler: this.handleToggleHidden,
|
||||
toggleSensitive: this.handleHotkeyToggleSensitive,
|
||||
openMedia: this.handleHotkeyOpenMedia,
|
||||
};
|
||||
|
@ -574,7 +602,7 @@ class Status extends ImmutablePureComponent {
|
|||
onOpenVideo={this.handleOpenVideo}
|
||||
onOpenMedia={this.handleOpenMedia}
|
||||
expanded={isExpanded}
|
||||
onToggleHidden={this.handleExpandedToggle}
|
||||
onToggleHidden={this.handleToggleHidden}
|
||||
domain={domain}
|
||||
showMedia={this.state.showMedia}
|
||||
onToggleMediaVisibility={this.handleToggleMediaVisibility}
|
||||
|
|
|
@ -27,6 +27,7 @@ const initialState = ImmutableMap({
|
|||
content_warnings : ImmutableMap({
|
||||
filter : null,
|
||||
media_outside: false,
|
||||
shared_state : false,
|
||||
}),
|
||||
collapsed : ImmutableMap({
|
||||
enabled : true,
|
||||
|
|
|
@ -10,6 +10,9 @@ import {
|
|||
import {
|
||||
STATUS_MUTE_SUCCESS,
|
||||
STATUS_UNMUTE_SUCCESS,
|
||||
STATUS_REVEAL,
|
||||
STATUS_HIDE,
|
||||
STATUS_COLLAPSE,
|
||||
} from 'flavours/glitch/actions/statuses';
|
||||
import {
|
||||
TIMELINE_DELETE,
|
||||
|
@ -56,6 +59,24 @@ export default function statuses(state = initialState, action) {
|
|||
return state.setIn([action.id, 'muted'], true);
|
||||
case STATUS_UNMUTE_SUCCESS:
|
||||
return state.setIn([action.id, 'muted'], false);
|
||||
case STATUS_REVEAL:
|
||||
return state.withMutations(map => {
|
||||
action.ids.forEach(id => {
|
||||
if (!(state.get(id) === undefined)) {
|
||||
map.setIn([id, 'hidden'], false);
|
||||
}
|
||||
});
|
||||
});
|
||||
case STATUS_HIDE:
|
||||
return state.withMutations(map => {
|
||||
action.ids.forEach(id => {
|
||||
if (!(state.get(id) === undefined)) {
|
||||
map.setIn([id, 'hidden'], true);
|
||||
}
|
||||
});
|
||||
});
|
||||
case STATUS_COLLAPSE:
|
||||
return state.setIn([action.id, 'collapsed'], action.isCollapsed);
|
||||
case TIMELINE_DELETE:
|
||||
return deleteStatus(state, action.id, action.references);
|
||||
default:
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
import { expandSpoilers } from 'flavours/glitch/util/initial_state';
|
||||
|
||||
export function autoUnfoldCW (settings, status) {
|
||||
if (!expandSpoilers) {
|
||||
function _autoUnfoldCW(spoiler_text, skip_unfold_regex) {
|
||||
if (!expandSpoilers)
|
||||
return false;
|
||||
}
|
||||
|
||||
const rawRegex = settings.getIn(['content_warnings', 'filter']);
|
||||
if (!skip_unfold_regex)
|
||||
return true;
|
||||
|
||||
if (!rawRegex) {
|
||||
let regex = null;
|
||||
|
||||
try {
|
||||
regex = new RegExp(skip_unfold_regex.trim(), 'i');
|
||||
} catch (e) {
|
||||
// Bad regex, skip filters
|
||||
return true;
|
||||
}
|
||||
|
||||
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'));
|
||||
return !regex.test(spoiler_text);
|
||||
}
|
||||
|
||||
export function autoHideCW(settings, spoiler_text) {
|
||||
return !_autoUnfoldCW(spoiler_text, settings.getIn(['content_warnings', 'filter']));
|
||||
}
|
||||
|
||||
export function autoUnfoldCW(settings, status) {
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
return _autoUnfoldCW(status.get('spoiler_text'), settings.getIn(['content_warnings', 'filter']));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue