diff --git a/app/javascript/flavours/glitch/actions/blocks.js b/app/javascript/flavours/glitch/actions/blocks.js index 66421ed455..e293657ad3 100644 --- a/app/javascript/flavours/glitch/actions/blocks.js +++ b/app/javascript/flavours/glitch/actions/blocks.js @@ -95,6 +95,6 @@ export function initBlockModal(account) { account, }); - dispatch(openModal('BLOCK')); + dispatch(openModal({ modalType: 'BLOCK' })); }; } diff --git a/app/javascript/flavours/glitch/actions/boosts.js b/app/javascript/flavours/glitch/actions/boosts.js index c0f0f3acc5..1fc2e391e2 100644 --- a/app/javascript/flavours/glitch/actions/boosts.js +++ b/app/javascript/flavours/glitch/actions/boosts.js @@ -14,7 +14,10 @@ export function initBoostModal(props) { privacy, }); - dispatch(openModal('BOOST', props)); + dispatch(openModal({ + modalType: 'BOOST', + modalProps: props, + })); }; } diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index c34a5e8991..9e0b123704 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -416,7 +416,10 @@ export function initMediaEditModal(id) { id, }); - dispatch(openModal('FOCAL_POINT', { id })); + dispatch(openModal({ + modalType: 'FOCAL_POINT', + modalProps: { id }, + })); }; } diff --git a/app/javascript/flavours/glitch/actions/filters.js b/app/javascript/flavours/glitch/actions/filters.js index 3774ee042a..a11956ac56 100644 --- a/app/javascript/flavours/glitch/actions/filters.js +++ b/app/javascript/flavours/glitch/actions/filters.js @@ -15,9 +15,12 @@ export const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS'; export const FILTERS_CREATE_FAIL = 'FILTERS_CREATE_FAIL'; export const initAddFilter = (status, { contextType }) => dispatch => - dispatch(openModal('FILTER', { - statusId: status?.get('id'), - contextType: contextType, + dispatch(openModal({ + modalType: 'FILTER', + modalProps: { + statusId: status?.get('id'), + contextType: contextType, + }, })); export const fetchFilters = () => (dispatch, getState) => { diff --git a/app/javascript/flavours/glitch/actions/local_settings.js b/app/javascript/flavours/glitch/actions/local_settings.js index a48669b6aa..f2878daa50 100644 --- a/app/javascript/flavours/glitch/actions/local_settings.js +++ b/app/javascript/flavours/glitch/actions/local_settings.js @@ -28,9 +28,12 @@ export function checkDeprecatedLocalSettings() { } if (changed_settings.length > 0) { - dispatch(openModal('DEPRECATED_SETTINGS', { - settings: changed_settings, - onConfirm: () => dispatch(clearDeprecatedLocalSettings()), + dispatch(openModal({ + modalType: 'DEPRECATED_SETTINGS', + modalProps: { + settings: changed_settings, + onConfirm: () => dispatch(clearDeprecatedLocalSettings()), + }, })); } }; diff --git a/app/javascript/flavours/glitch/actions/modal.js b/app/javascript/flavours/glitch/actions/modal.js deleted file mode 100644 index ef2ae0e4c7..0000000000 --- a/app/javascript/flavours/glitch/actions/modal.js +++ /dev/null @@ -1,18 +0,0 @@ -export const MODAL_OPEN = 'MODAL_OPEN'; -export const MODAL_CLOSE = 'MODAL_CLOSE'; - -export function openModal(type, props) { - return { - type: MODAL_OPEN, - modalType: type, - modalProps: props, - }; -} - -export function closeModal(type, options = { ignoreFocus: false }) { - return { - type: MODAL_CLOSE, - modalType: type, - ignoreFocus: options.ignoreFocus, - }; -} diff --git a/app/javascript/flavours/glitch/actions/modal.ts b/app/javascript/flavours/glitch/actions/modal.ts new file mode 100644 index 0000000000..af34f5d6af --- /dev/null +++ b/app/javascript/flavours/glitch/actions/modal.ts @@ -0,0 +1,17 @@ +import { createAction } from '@reduxjs/toolkit'; + +import type { MODAL_COMPONENTS } from '../features/ui/components/modal_root'; + +export type ModalType = keyof typeof MODAL_COMPONENTS; + +interface OpenModalPayload { + modalType: ModalType; + modalProps: unknown; +} +export const openModal = createAction<OpenModalPayload>('MODAL_OPEN'); + +interface CloseModalPayload { + modalType: ModalType | undefined; + ignoreFocus: boolean; +} +export const closeModal = createAction<CloseModalPayload>('MODAL_CLOSE'); diff --git a/app/javascript/flavours/glitch/actions/mutes.js b/app/javascript/flavours/glitch/actions/mutes.js index 2ff4d27c80..4af927d932 100644 --- a/app/javascript/flavours/glitch/actions/mutes.js +++ b/app/javascript/flavours/glitch/actions/mutes.js @@ -98,7 +98,7 @@ export function initMuteModal(account) { account, }); - dispatch(openModal('MUTE')); + dispatch(openModal({ modalType: 'MUTE' })); }; } diff --git a/app/javascript/flavours/glitch/actions/onboarding.js b/app/javascript/flavours/glitch/actions/onboarding.js index 5038b7eb67..a4a525c427 100644 --- a/app/javascript/flavours/glitch/actions/onboarding.js +++ b/app/javascript/flavours/glitch/actions/onboarding.js @@ -6,7 +6,9 @@ export function showOnboardingOnce() { const alreadySeen = getState().getIn(['settings', 'onboarded']); if (!alreadySeen) { - dispatch(openModal('ONBOARDING')); + dispatch(openModal({ + modalType: 'ONBOARDING', + })); dispatch(changeSetting(['onboarded'], true)); dispatch(saveSettings()); } diff --git a/app/javascript/flavours/glitch/actions/reports.js b/app/javascript/flavours/glitch/actions/reports.js index b3f9bf1ac3..756b8cd05e 100644 --- a/app/javascript/flavours/glitch/actions/reports.js +++ b/app/javascript/flavours/glitch/actions/reports.js @@ -7,9 +7,12 @@ export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS'; export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'; export const initReport = (account, status) => dispatch => - dispatch(openModal('REPORT', { - accountId: account.get('id'), - statusId: status?.get('id'), + dispatch(openModal({ + modalType: 'REPORT', + modalProps: { + accountId: account.get('id'), + statusId: status?.get('id'), + }, })); export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => { diff --git a/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx b/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx index 5189f80510..3dbac58b54 100644 --- a/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx +++ b/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx @@ -15,7 +15,10 @@ import DropdownMenu from './containers/dropdown_menu_container'; const mapDispatchToProps = (dispatch, { statusId }) => ({ onItemClick (index) { - dispatch(openModal('COMPARE_HISTORY', { index, statusId })); + dispatch(openModal({ + modalType: 'COMPARE_HISTORY', + modalProps: { index, statusId }, + })); }, }); diff --git a/app/javascript/flavours/glitch/containers/account_container.jsx b/app/javascript/flavours/glitch/containers/account_container.jsx index 537c63f3f1..f204545852 100644 --- a/app/javascript/flavours/glitch/containers/account_container.jsx +++ b/app/javascript/flavours/glitch/containers/account_container.jsx @@ -35,10 +35,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow (account) { if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { if (unfollowModal) { - dispatch(openModal('CONFIRM', { - message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, - confirm: intl.formatMessage(messages.unfollowConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, + confirm: intl.formatMessage(messages.unfollowConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, })); } else { dispatch(unfollowAccount(account.get('id'))); diff --git a/app/javascript/flavours/glitch/containers/domain_container.jsx b/app/javascript/flavours/glitch/containers/domain_container.jsx index 9a55b72cc3..c719a5775c 100644 --- a/app/javascript/flavours/glitch/containers/domain_container.jsx +++ b/app/javascript/flavours/glitch/containers/domain_container.jsx @@ -18,10 +18,13 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onBlockDomain (domain) { - dispatch(openModal('CONFIRM', { - message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.' values={{ domain: <strong>{domain}</strong> }} />, - confirm: intl.formatMessage(messages.blockDomainConfirm), - onConfirm: () => dispatch(blockDomain(domain)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.' values={{ domain: <strong>{domain}</strong> }} />, + confirm: intl.formatMessage(messages.blockDomainConfirm), + onConfirm: () => dispatch(blockDomain(domain)), + }, })); }, diff --git a/app/javascript/flavours/glitch/containers/dropdown_menu_container.js b/app/javascript/flavours/glitch/containers/dropdown_menu_container.js index 5ad13e5554..36aa4c4ea0 100644 --- a/app/javascript/flavours/glitch/containers/dropdown_menu_container.js +++ b/app/javascript/flavours/glitch/containers/dropdown_menu_container.js @@ -13,10 +13,13 @@ const mapStateToProps = state => ({ const mapDispatchToProps = (dispatch, { status, items, scrollKey }) => ({ onOpen(id, onItemClick, keyboard) { - dispatch(isUserTouching() ? openModal('ACTIONS', { - status, - actions: items, - onClick: onItemClick, + dispatch(isUserTouching() ? openModal({ + modalType: 'ACTIONS', + modalProps: { + status, + actions: items, + onClick: onItemClick, + }, }) : openDropdownMenu(id, keyboard, scrollKey)); }, diff --git a/app/javascript/flavours/glitch/containers/notification_purge_buttons_container.js b/app/javascript/flavours/glitch/containers/notification_purge_buttons_container.js index 58075b1c48..144d77f135 100644 --- a/app/javascript/flavours/glitch/containers/notification_purge_buttons_container.js +++ b/app/javascript/flavours/glitch/containers/notification_purge_buttons_container.js @@ -23,10 +23,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onDeleteMarked() { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.clearMessage), - confirm: intl.formatMessage(messages.clearConfirm), - onConfirm: () => dispatch(deleteMarkedNotifications()), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.clearMessage), + confirm: intl.formatMessage(messages.clearConfirm), + onConfirm: () => dispatch(deleteMarkedNotifications()), + }, })); }, diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index 6ae58aa3d5..5af818c8f5 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -99,11 +99,14 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ let state = getState(); if (state.getIn(['local_settings', 'confirm_before_clearing_draft']) && state.getIn(['compose', 'text']).trim().length !== 0) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.replyMessage), - confirm: intl.formatMessage(messages.replyConfirm), - onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), - onConfirm: () => dispatch(replyCompose(status, router)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), + onConfirm: () => dispatch(replyCompose(status, router)), + }, })); } else { dispatch(replyCompose(status, router)); @@ -151,7 +154,13 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ if (e.shiftKey || !favouriteModal) { this.onModalFavourite(status); } else { - dispatch(openModal('FAVOURITE', { status, onFavourite: this.onModalFavourite })); + dispatch(openModal({ + modalType: 'FAVOURITE', + modalProps: { + status, + onFavourite: this.onModalFavourite, + }, + })); } } }, @@ -165,9 +174,12 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onEmbed (status) { - dispatch(openModal('EMBED', { - url: status.get('url'), - onError: error => dispatch(showAlertForError(error)), + dispatch(openModal({ + modalType: 'EMBED', + modalProps: { + url: status.get('url'), + onError: error => dispatch(showAlertForError(error)), + }, })); }, @@ -175,10 +187,13 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ if (!deleteModal) { dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), - confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), + confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), + onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + }, })); } }, @@ -187,10 +202,13 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ dispatch((_, getState) => { let state = getState(); if (state.getIn(['compose', 'text']).trim().length !== 0) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.editMessage), - confirm: intl.formatMessage(messages.editConfirm), - onConfirm: () => dispatch(editStatus(status.get('id'), history)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.editMessage), + confirm: intl.formatMessage(messages.editConfirm), + onConfirm: () => dispatch(editStatus(status.get('id'), history)), + }, })); } else { dispatch(editStatus(status.get('id'), history)); @@ -215,11 +233,17 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onOpenMedia (statusId, media, index, lang) { - dispatch(openModal('MEDIA', { statusId, media, index, lang })); + dispatch(openModal({ + modalType: 'MEDIA', + modalProps: { statusId, media, index, lang }, + })); }, onOpenVideo (statusId, media, lang, options) { - dispatch(openModal('VIDEO', { statusId, media, lang, options })); + dispatch(openModal({ + modalType: 'VIDEO', + modalProps: { statusId, media, lang, options }, + })); }, onBlock (status) { @@ -264,10 +288,13 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }, onInteractionModal (type, status) { - dispatch(openModal('INTERACTION', { - type, - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type, + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); }, diff --git a/app/javascript/flavours/glitch/features/account_gallery/index.jsx b/app/javascript/flavours/glitch/features/account_gallery/index.jsx index c8567a1010..170b2ca3b7 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/index.jsx +++ b/app/javascript/flavours/glitch/features/account_gallery/index.jsx @@ -149,14 +149,23 @@ class AccountGallery extends ImmutablePureComponent { const lang = attachment.getIn(['status', 'language']); if (attachment.get('type') === 'video') { - dispatch(openModal('VIDEO', { media: attachment, statusId, lang, options: { autoPlay: true } })); + dispatch(openModal({ + modalType: 'VIDEO', + modalProps: { media: attachment, statusId, lang, options: { autoPlay: true } }, + })); } else if (attachment.get('type') === 'audio') { - dispatch(openModal('AUDIO', { media: attachment, statusId, lang, options: { autoPlay: true } })); + dispatch(openModal({ + modalType: 'AUDIO', + modalProps: { media: attachment, statusId, lang, options: { autoPlay: true } }, + })); } else { const media = attachment.getIn(['status', 'media_attachments']); const index = media.findIndex(x => x.get('id') === attachment.get('id')); - dispatch(openModal('MEDIA', { media, index, statusId, lang })); + dispatch(openModal({ + modalType: 'MEDIA', + modalProps: { media, index, statusId, lang }, + })); } }; diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx index d37c52b3bb..6ee5aba5fc 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.jsx @@ -48,20 +48,26 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onFollow (account) { if (account.getIn(['relationship', 'following'])) { if (unfollowModal) { - dispatch(openModal('CONFIRM', { - message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, - confirm: intl.formatMessage(messages.unfollowConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, + confirm: intl.formatMessage(messages.unfollowConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, })); } else { dispatch(unfollowAccount(account.get('id'))); } } else if (account.getIn(['relationship', 'requested'])) { if (unfollowModal) { - dispatch(openModal('CONFIRM', { - message: <FormattedMessage id='confirmations.cancel_follow_request.message' defaultMessage='Are you sure you want to withdraw your request to follow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, - confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: <FormattedMessage id='confirmations.cancel_follow_request.message' defaultMessage='Are you sure you want to withdraw your request to follow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, + confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, })); } else { dispatch(unfollowAccount(account.get('id'))); @@ -72,10 +78,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onInteractionModal (account) { - dispatch(openModal('INTERACTION', { - type: 'follow', - accountId: account.get('id'), - url: account.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'follow', + accountId: account.get('id'), + url: account.get('url'), + }, })); }, @@ -136,10 +145,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onBlockDomain (domain) { - dispatch(openModal('CONFIRM', { - message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />, - confirm: intl.formatMessage(messages.blockDomainConfirm), - onConfirm: () => dispatch(blockDomain(domain)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />, + confirm: intl.formatMessage(messages.blockDomainConfirm), + onConfirm: () => dispatch(blockDomain(domain)), + }, })); }, @@ -148,21 +160,30 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onAddToList (account) { - dispatch(openModal('LIST_ADDER', { - accountId: account.get('id'), + dispatch(openModal({ + modalType: 'LIST_ADDER', + modalProps: { + accountId: account.get('id'), + }, })); }, onChangeLanguages (account) { - dispatch(openModal('SUBSCRIBED_LANGUAGES', { - accountId: account.get('id'), + dispatch(openModal({ + modalType: 'SUBSCRIBED_LANGUAGES', + modalProps: { + accountId: account.get('id'), + }, })); }, onOpenAvatar (account) { - dispatch(openModal('IMAGE', { - src: account.get('avatar'), - alt: account.get('acct'), + dispatch(openModal({ + modalType: 'IMAGE', + modalProps: { + src: account.get('avatar'), + alt: account.get('acct'), + }, })); }, diff --git a/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js b/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js index e01ea3497f..e9724568cd 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js @@ -126,18 +126,24 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onMediaDescriptionConfirm(routerHistory, mediaId, overriddenVisibility = null) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.missingDescriptionMessage), - confirm: intl.formatMessage(messages.missingDescriptionConfirm), - onConfirm: () => { - if (overriddenVisibility) { - dispatch(changeComposeVisibility(overriddenVisibility)); - } - dispatch(submitCompose(routerHistory)); + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.missingDescriptionMessage), + confirm: intl.formatMessage(messages.missingDescriptionConfirm), + onConfirm: () => { + if (overriddenVisibility) { + dispatch(changeComposeVisibility(overriddenVisibility)); + } + dispatch(submitCompose(routerHistory)); + }, + secondary: intl.formatMessage(messages.missingDescriptionEdit), + onSecondary: () => dispatch(openModal({ + modalType: 'FOCAL_POINT', + modalProps: { id: mediaId }, + })), + onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_missing_media_description'], false)), }, - secondary: intl.formatMessage(messages.missingDescriptionEdit), - onSecondary: () => dispatch(openModal('FOCAL_POINT', { id: mediaId })), - onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_missing_media_description'], false)), })); }, diff --git a/app/javascript/flavours/glitch/features/compose/containers/dropdown_container.js b/app/javascript/flavours/glitch/features/compose/containers/dropdown_container.js index e7fca2a651..1f39edbffc 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/dropdown_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/dropdown_container.js @@ -7,7 +7,7 @@ import Dropdown from '../components/dropdown'; const mapDispatchToProps = dispatch => ({ isUserTouching, - onModalOpen: props => dispatch(openModal('ACTIONS', props)), + onModalOpen: props => dispatch(openModal({ modalType: 'ACTIONS', modalProps: props })), onModalClose: () => dispatch(closeModal()), }); diff --git a/app/javascript/flavours/glitch/features/compose/containers/header_container.js b/app/javascript/flavours/glitch/features/compose/containers/header_container.js index 500dbaedd5..5b78c8b9cd 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/header_container.js @@ -24,14 +24,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onSettingsClick (e) { e.preventDefault(); e.stopPropagation(); - dispatch(openModal('SETTINGS', {})); + dispatch(openModal({ modalType: 'SETTINGS', modalProps: {} })); }, onLogout () { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.logoutMessage), - confirm: intl.formatMessage(messages.logoutConfirm), - closeWhenConfirm: false, - onConfirm: () => logOut(), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.logoutMessage), + confirm: intl.formatMessage(messages.logoutConfirm), + closeWhenConfirm: false, + onConfirm: () => logOut(), + }, })); }, }); diff --git a/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js b/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js index ed0fc42c22..541365aa99 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/navigation_container.js @@ -21,11 +21,14 @@ const mapStateToProps = state => { const mapDispatchToProps = (dispatch, { intl }) => ({ onLogout () { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.logoutMessage), - confirm: intl.formatMessage(messages.logoutConfirm), - closeWhenConfirm: false, - onConfirm: () => logOut(), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.logoutMessage), + confirm: intl.formatMessage(messages.logoutConfirm), + closeWhenConfirm: false, + onConfirm: () => logOut(), + }, })); }, }); diff --git a/app/javascript/flavours/glitch/features/compose/containers/options_container.js b/app/javascript/flavours/glitch/features/compose/containers/options_container.js index 7494595346..c44d3ce305 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/options_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/options_container.js @@ -46,7 +46,10 @@ const mapDispatchToProps = (dispatch) => ({ }, onDoodleOpen() { - dispatch(openModal('DOODLE', { noEsc: true, noClose: true })); + dispatch(openModal({ + modalType: 'DOODLE', + modalProps: { noEsc: true, noClose: true }, + })); }, }); diff --git a/app/javascript/flavours/glitch/features/compose/containers/privacy_dropdown_container.js b/app/javascript/flavours/glitch/features/compose/containers/privacy_dropdown_container.js index 3e9ad63a07..dcbd977dae 100644 --- a/app/javascript/flavours/glitch/features/compose/containers/privacy_dropdown_container.js +++ b/app/javascript/flavours/glitch/features/compose/containers/privacy_dropdown_container.js @@ -17,8 +17,14 @@ const mapDispatchToProps = dispatch => ({ }, isUserTouching, - onModalOpen: props => dispatch(openModal('ACTIONS', props)), - onModalClose: () => dispatch(closeModal()), + onModalOpen: props => dispatch(openModal({ + modalType: 'ACTIONS', + modalProps: props, + })), + onModalClose: () => dispatch(closeModal({ + modalType: undefined, + ignoreFocus: false, + })), }); diff --git a/app/javascript/flavours/glitch/features/direct_timeline/containers/conversation_container.js b/app/javascript/flavours/glitch/features/direct_timeline/containers/conversation_container.js index c87a08df12..207d3ebb65 100644 --- a/app/javascript/flavours/glitch/features/direct_timeline/containers/conversation_container.js +++ b/app/javascript/flavours/glitch/features/direct_timeline/containers/conversation_container.js @@ -42,10 +42,13 @@ const mapDispatchToProps = (dispatch, { intl, conversationId }) => ({ 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)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(replyCompose(status, router)), + }, })); } else { dispatch(replyCompose(status, router)); diff --git a/app/javascript/flavours/glitch/features/directory/components/account_card.jsx b/app/javascript/flavours/glitch/features/directory/components/account_card.jsx index 989569f45b..655714beec 100644 --- a/app/javascript/flavours/glitch/features/directory/components/account_card.jsx +++ b/app/javascript/flavours/glitch/features/directory/components/account_card.jsx @@ -53,27 +53,32 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ if (account.getIn(['relationship', 'following'])) { if (unfollowModal) { dispatch( - openModal('CONFIRM', { - message: ( - <FormattedMessage - id='confirmations.unfollow.message' - defaultMessage='Are you sure you want to unfollow {name}?' - values={{ name: <strong>@{account.get('acct')}</strong> }} - /> - ), - confirm: intl.formatMessage(messages.unfollowConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), - }), + openModal({ + modalType: 'CONFIRM', + modalProps: { + message: ( + <FormattedMessage + id='confirmations.unfollow.message' + defaultMessage='Are you sure you want to unfollow {name}?' + values={{ name: <strong>@{account.get('acct')}</strong> }} + /> + ), + confirm: intl.formatMessage(messages.unfollowConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + } }), ); } else { dispatch(unfollowAccount(account.get('id'))); } } else if (account.getIn(['relationship', 'requested'])) { if (unfollowModal) { - dispatch(openModal('CONFIRM', { - message: <FormattedMessage id='confirmations.cancel_follow_request.message' defaultMessage='Are you sure you want to withdraw your request to follow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, - confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), - onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: <FormattedMessage id='confirmations.cancel_follow_request.message' defaultMessage='Are you sure you want to withdraw your request to follow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, + confirm: intl.formatMessage(messages.cancelFollowRequestConfirm), + onConfirm: () => dispatch(unfollowAccount(account.get('id'))), + }, })); } else { dispatch(unfollowAccount(account.get('id'))); diff --git a/app/javascript/flavours/glitch/features/getting_started/index.jsx b/app/javascript/flavours/glitch/features/getting_started/index.jsx index 26cfca0cbf..0f6f3330e8 100644 --- a/app/javascript/flavours/glitch/features/getting_started/index.jsx +++ b/app/javascript/flavours/glitch/features/getting_started/index.jsx @@ -69,7 +69,10 @@ const makeMapStateToProps = () => { const mapDispatchToProps = dispatch => ({ fetchFollowRequests: () => dispatch(fetchFollowRequests()), fetchLists: () => dispatch(fetchLists()), - openSettings: () => dispatch(openModal('SETTINGS', {})), + openSettings: () => dispatch(openModal({ + modalType: 'SETTINGS', + modalProps: {}, + })), }); const badgeDisplay = (number, limit) => { diff --git a/app/javascript/flavours/glitch/features/getting_started_misc/index.jsx b/app/javascript/flavours/glitch/features/getting_started_misc/index.jsx index ed93ba370d..20dfe80b47 100644 --- a/app/javascript/flavours/glitch/features/getting_started_misc/index.jsx +++ b/app/javascript/flavours/glitch/features/getting_started_misc/index.jsx @@ -38,11 +38,15 @@ class GettingStartedMisc extends ImmutablePureComponent { }; openOnboardingModal = () => { - this.props.dispatch(openModal('ONBOARDING')); + this.props.dispatch(openModal({ + modalType: 'ONBOARDING', + })); }; openFeaturedAccountsModal = () => { - this.props.dispatch(openModal('PINNED_ACCOUNTS_EDITOR')); + this.props.dispatch(openModal({ + modalType: 'PINNED_ACCOUNTS_EDITOR', + })); }; render () { diff --git a/app/javascript/flavours/glitch/features/interaction_modal/index.jsx b/app/javascript/flavours/glitch/features/interaction_modal/index.jsx index 557f760a1a..db28876476 100644 --- a/app/javascript/flavours/glitch/features/interaction_modal/index.jsx +++ b/app/javascript/flavours/glitch/features/interaction_modal/index.jsx @@ -18,8 +18,11 @@ const mapStateToProps = (state, { accountId }) => ({ const mapDispatchToProps = (dispatch) => ({ onSignupClick() { - dispatch(closeModal()); - dispatch(openModal('CLOSED_REGISTRATIONS')); + dispatch(closeModal({ + modalType: undefined, + ignoreFocus: false, + })); + dispatch(openModal({ modalType: 'CLOSED_REGISTRATIONS' })); }, }); diff --git a/app/javascript/flavours/glitch/features/list_timeline/index.jsx b/app/javascript/flavours/glitch/features/list_timeline/index.jsx index 7e37a4afeb..554a3a0e89 100644 --- a/app/javascript/flavours/glitch/features/list_timeline/index.jsx +++ b/app/javascript/flavours/glitch/features/list_timeline/index.jsx @@ -114,24 +114,30 @@ class ListTimeline extends PureComponent { }; handleEditClick = () => { - this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id })); + this.props.dispatch(openModal({ + modalType: 'LIST_EDITOR', + modalProps: { listId: this.props.params.id }, + })); }; handleDeleteClick = () => { const { dispatch, columnId, intl } = this.props; const { id } = this.props.params; - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.deleteMessage), - confirm: intl.formatMessage(messages.deleteConfirm), - onConfirm: () => { - dispatch(deleteList(id)); + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.deleteMessage), + confirm: intl.formatMessage(messages.deleteConfirm), + onConfirm: () => { + dispatch(deleteList(id)); - if (columnId) { - dispatch(removeColumn(columnId)); - } else { - this.context.router.history.push('/lists'); - } + if (columnId) { + dispatch(removeColumn(columnId)); + } else { + this.context.router.history.push('/lists'); + } + }, }, })); }; diff --git a/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js b/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js index a0a22192ac..024f4daabb 100644 --- a/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js +++ b/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js @@ -61,10 +61,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onClear () { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.clearMessage), - confirm: intl.formatMessage(messages.clearConfirm), - onConfirm: () => dispatch(clearNotifications()), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.clearMessage), + confirm: intl.formatMessage(messages.clearConfirm), + onConfirm: () => dispatch(clearNotifications()), + }, })); }, diff --git a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx index ab7de65328..7d5c4adb6f 100644 --- a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx @@ -76,19 +76,25 @@ class Footer extends ImmutablePureComponent { if (signedIn) { if (askReplyConfirmation) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.replyMessage), - confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: this._performReply, + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: this._performReply, + }, })); } else { this._performReply(); } } else { - dispatch(openModal('INTERACTION', { - type: 'reply', - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'reply', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); } }; @@ -104,10 +110,13 @@ class Footer extends ImmutablePureComponent { dispatch(favourite(status)); } } else { - dispatch(openModal('INTERACTION', { - type: 'favourite', - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'favourite', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); } }; @@ -130,10 +139,13 @@ class Footer extends ImmutablePureComponent { dispatch(initBoostModal({ status, onReblog: this._performReblog })); } } else { - dispatch(openModal('INTERACTION', { - type: 'reblog', - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'reblog', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); } }; diff --git a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js index 56757eed03..96d9090dad 100644 --- a/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js +++ b/app/javascript/flavours/glitch/features/status/containers/detailed_status_container.js @@ -58,10 +58,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ 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)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: () => dispatch(replyCompose(status, router)), + }, })); } else { dispatch(replyCompose(status, router)); @@ -102,9 +105,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onEmbed (status) { - dispatch(openModal('EMBED', { - url: status.get('url'), - onError: error => dispatch(showAlertForError(error)), + dispatch(openModal({ + modalType: 'EMBED', + modalProps: { + url: status.get('url'), + onError: error => dispatch(showAlertForError(error)), + }, })); }, @@ -112,10 +118,13 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ if (!deleteModal) { dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), - confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), + confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), + onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + }, })); } }, @@ -129,11 +138,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, onOpenMedia (media, index, lang) { - dispatch(openModal('MEDIA', { media, index, lang })); + dispatch(openModal({ + modalType: 'MEDIA', + modalProps: { media, index, lang }, + })); }, onOpenVideo (media, lang, options) { - dispatch(openModal('VIDEO', { media, lang, options })); + dispatch(openModal({ + modalType: 'VIDEO', + modalProps: { media, lang, options }, + })); }, onBlock (status) { diff --git a/app/javascript/flavours/glitch/features/status/index.jsx b/app/javascript/flavours/glitch/features/status/index.jsx index 8efb335b6a..0c7a016644 100644 --- a/app/javascript/flavours/glitch/features/status/index.jsx +++ b/app/javascript/flavours/glitch/features/status/index.jsx @@ -289,14 +289,23 @@ class Status extends ImmutablePureComponent { if ((e && e.shiftKey) || !favouriteModal) { this.handleModalFavourite(status); } else { - dispatch(openModal('FAVOURITE', { status, onFavourite: this.handleModalFavourite })); + dispatch(openModal({ + modalType: 'FAVOURITE', + modalProps: { + status, + onFavourite: this.handleModalFavourite, + }, + })); } } } else { - dispatch(openModal('INTERACTION', { - type: 'favourite', - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'favourite', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); } }; @@ -315,20 +324,26 @@ class Status extends ImmutablePureComponent { if (signedIn) { if (askReplyConfirmation) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.replyMessage), - confirm: intl.formatMessage(messages.replyConfirm), - onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), - onConfirm: () => dispatch(replyCompose(status, this.context.router.history)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), + onConfirm: () => dispatch(replyCompose(status, this.context.router.history)), + }, })); } else { dispatch(replyCompose(status, this.context.router.history)); } } else { - dispatch(openModal('INTERACTION', { - type: 'reply', - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'reply', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); } }; @@ -356,10 +371,13 @@ class Status extends ImmutablePureComponent { dispatch(initBoostModal({ status, onReblog: this.handleModalReblog })); } } else { - dispatch(openModal('INTERACTION', { - type: 'reblog', - accountId: status.getIn(['account', 'id']), - url: status.get('url'), + dispatch(openModal({ + modalType: 'INTERACTION', + modalProps: { + type: 'reblog', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + }, })); } }; @@ -378,10 +396,13 @@ class Status extends ImmutablePureComponent { if (!deleteModal) { dispatch(deleteStatus(status.get('id'), history, withRedraft)); } else { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), - confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), - onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), + confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), + onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), + }, })); } }; @@ -399,11 +420,17 @@ class Status extends ImmutablePureComponent { }; handleOpenMedia = (media, index, lang) => { - this.props.dispatch(openModal('MEDIA', { statusId: this.props.status.get('id'), media, index, lang })); + this.props.dispatch(openModal({ + modalType: 'MEDIA', + modalProps: { statusId: this.props.status.get('id'), media, index, lang }, + })); }; handleOpenVideo = (media, lang, options) => { - this.props.dispatch(openModal('VIDEO', { statusId: this.props.status.get('id'), media, lang, options })); + this.props.dispatch(openModal({ + modalType: 'VIDEO', + modalProps: { statusId: this.props.status.get('id'), media, lang, options }, + })); }; handleHotkeyOpenMedia = e => { @@ -470,7 +497,10 @@ class Status extends ImmutablePureComponent { }; handleEmbed = (status) => { - this.props.dispatch(openModal('EMBED', { url: status.get('url') })); + this.props.dispatch(openModal({ + modalType: 'EMBED', + modalProps: { url: status.get('url') }, + })); }; handleHotkeyToggleSensitive = () => { diff --git a/app/javascript/flavours/glitch/features/ui/components/block_modal.jsx b/app/javascript/flavours/glitch/features/ui/components/block_modal.jsx index 90f262410d..c2965d6173 100644 --- a/app/javascript/flavours/glitch/features/ui/components/block_modal.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/block_modal.jsx @@ -34,7 +34,10 @@ const mapDispatchToProps = dispatch => { }, onClose() { - dispatch(closeModal()); + dispatch(closeModal({ + modalType: undefined, + ignoreFocus: false, + })); }, }; }; diff --git a/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.jsx b/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.jsx index 9c1a9e27ee..409342bdd2 100644 --- a/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/compare_history_modal.jsx @@ -23,7 +23,10 @@ const mapStateToProps = (state, { statusId }) => ({ const mapDispatchToProps = dispatch => ({ onClose() { - dispatch(closeModal()); + dispatch(closeModal({ + modalType: undefined, + ignoreFocus: false, + })); }, }); diff --git a/app/javascript/flavours/glitch/features/ui/components/disabled_account_banner.jsx b/app/javascript/flavours/glitch/features/ui/components/disabled_account_banner.jsx index b9b68c2887..396127829b 100644 --- a/app/javascript/flavours/glitch/features/ui/components/disabled_account_banner.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/disabled_account_banner.jsx @@ -23,11 +23,14 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch, { intl }) => ({ onLogout () { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.logoutMessage), - confirm: intl.formatMessage(messages.logoutConfirm), - closeWhenConfirm: false, - onConfirm: () => logOut(), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.logoutMessage), + confirm: intl.formatMessage(messages.logoutConfirm), + closeWhenConfirm: false, + onConfirm: () => logOut(), + }, })); }, }); diff --git a/app/javascript/flavours/glitch/features/ui/components/header.jsx b/app/javascript/flavours/glitch/features/ui/components/header.jsx index 93bac5c7e7..bbef3a5fb8 100644 --- a/app/javascript/flavours/glitch/features/ui/components/header.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/header.jsx @@ -27,7 +27,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => ({ openClosedRegistrationsModal() { - dispatch(openModal('CLOSED_REGISTRATIONS')); + dispatch(openModal({ modalType: 'CLOSED_REGISTRATIONS' })); }, }); diff --git a/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx b/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx index ce65c3d827..1738116c7c 100644 --- a/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/link_footer.jsx @@ -19,11 +19,14 @@ const messages = defineMessages({ const mapDispatchToProps = (dispatch, { intl }) => ({ onLogout () { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.logoutMessage), - confirm: intl.formatMessage(messages.logoutConfirm), - closeWhenConfirm: false, - onConfirm: () => logOut(), + dispatch(openModal({ + modalType: 'CONFIRM', + modalProps: { + message: intl.formatMessage(messages.logoutMessage), + confirm: intl.formatMessage(messages.logoutConfirm), + closeWhenConfirm: false, + onConfirm: () => logOut(), + }, })); }, }); diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx b/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx index 97bf1f6ad1..03588e2768 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx @@ -40,7 +40,7 @@ import VideoModal from './video_modal'; -const MODAL_COMPONENTS = { +export const MODAL_COMPONENTS = { 'MEDIA': () => Promise.resolve({ default: MediaModal }), 'ONBOARDING': OnboardingModal, 'VIDEO': () => Promise.resolve({ default: VideoModal }), diff --git a/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx b/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx index 1060a9e63d..23f842f090 100644 --- a/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/mute_modal.jsx @@ -34,7 +34,10 @@ const mapDispatchToProps = dispatch => { }, onClose() { - dispatch(closeModal()); + dispatch(closeModal({ + modalType: undefined, + ignoreFocus: false, + })); }, onToggleNotifications() { diff --git a/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.jsx b/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.jsx index 819ad87366..31d43af7b1 100644 --- a/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.jsx @@ -10,7 +10,7 @@ const SignInBanner = () => { const dispatch = useAppDispatch(); const openClosedRegistrationsModal = useCallback( - () => dispatch(openModal('CLOSED_REGISTRATIONS')), + () => dispatch(openModal({ modalType: 'CLOSED_REGISTRATIONS' })), [dispatch], ); 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 9b6202af7b..a69abfb610 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 @@ -12,7 +12,10 @@ const mapDispatchToProps = dispatch => ({ openSettings (e) { e.preventDefault(); e.stopPropagation(); - dispatch(openModal('SETTINGS', {})); + dispatch(openModal({ + modalType: 'SETTINGS', + modalProps: {}, + })); }, }); diff --git a/app/javascript/flavours/glitch/features/ui/containers/modal_container.js b/app/javascript/flavours/glitch/features/ui/containers/modal_container.js index 55b87485e2..0d07d68a5d 100644 --- a/app/javascript/flavours/glitch/features/ui/containers/modal_container.js +++ b/app/javascript/flavours/glitch/features/ui/containers/modal_container.js @@ -14,14 +14,22 @@ const mapDispatchToProps = dispatch => ({ onClose (confirmationMessage, ignoreFocus = false) { if (confirmationMessage) { dispatch( - openModal('CONFIRM', { - message: confirmationMessage.message, - confirm: confirmationMessage.confirm, - onConfirm: () => dispatch(closeModal(undefined, { ignoreFocus })), - }), + openModal({ + modalType: 'CONFIRM', + modalProps: { + message: confirmationMessage.message, + confirm: confirmationMessage.confirm, + onConfirm: () => dispatch(closeModal({ + modalType: undefined, + ignoreFocus: { ignoreFocus }, + })), + } }), ); } else { - dispatch(closeModal(undefined, { ignoreFocus })); + dispatch(closeModal({ + modalType: undefined, + ignoreFocus: { ignoreFocus }, + })); } }, }); diff --git a/app/javascript/flavours/glitch/reducers/index.ts b/app/javascript/flavours/glitch/reducers/index.ts index eaef569f09..fdfa4104f6 100644 --- a/app/javascript/flavours/glitch/reducers/index.ts +++ b/app/javascript/flavours/glitch/reducers/index.ts @@ -26,7 +26,7 @@ import local_settings from './local_settings'; import markers from './markers'; import media_attachments from './media_attachments'; import meta from './meta'; -import modal from './modal'; +import { modalReducer } from './modal'; import mutes from './mutes'; import notifications from './notifications'; import picture_in_picture from './picture_in_picture'; @@ -52,7 +52,7 @@ const reducers = { meta, alerts, loadingBar: loadingBarReducer, - modal, + modal: modalReducer, user_lists, domain_lists, status_lists, diff --git a/app/javascript/flavours/glitch/reducers/modal.js b/app/javascript/flavours/glitch/reducers/modal.js deleted file mode 100644 index e8cea5032a..0000000000 --- a/app/javascript/flavours/glitch/reducers/modal.js +++ /dev/null @@ -1,40 +0,0 @@ -import { Stack as ImmutableStack, Map as ImmutableMap } from 'immutable'; - -import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from 'flavours/glitch/actions/compose'; -import { MODAL_OPEN, MODAL_CLOSE } from 'flavours/glitch/actions/modal'; -import { TIMELINE_DELETE } from 'flavours/glitch/actions/timelines'; - -const initialState = ImmutableMap({ - ignoreFocus: false, - stack: ImmutableStack(), -}); - -const popModal = (state, { modalType, ignoreFocus }) => { - if (modalType === undefined || modalType === state.getIn(['stack', 0, 'modalType'])) { - return state.set('ignoreFocus', !!ignoreFocus).update('stack', stack => stack.shift()); - } else { - return state; - } -}; - -const pushModal = (state, modalType, modalProps) => { - return state.withMutations(map => { - map.set('ignoreFocus', false); - map.update('stack', stack => stack.unshift(ImmutableMap({ modalType, modalProps }))); - }); -}; - -export default function modal(state = initialState, action) { - switch(action.type) { - case MODAL_OPEN: - return pushModal(state, action.modalType, action.modalProps); - case MODAL_CLOSE: - return popModal(state, action); - case COMPOSE_UPLOAD_CHANGE_SUCCESS: - return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false }); - case TIMELINE_DELETE: - return state.update('stack', stack => stack.filterNot((modal) => modal.get('modalProps').statusId === action.id)); - default: - return state; - } -} diff --git a/app/javascript/flavours/glitch/reducers/modal.ts b/app/javascript/flavours/glitch/reducers/modal.ts new file mode 100644 index 0000000000..6afbcc367c --- /dev/null +++ b/app/javascript/flavours/glitch/reducers/modal.ts @@ -0,0 +1,94 @@ +import { Record as ImmutableRecord, Stack } from 'immutable'; + +import type { PayloadAction } from '@reduxjs/toolkit'; + +import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose'; +import type { ModalType } from '../actions/modal'; +import { openModal, closeModal } from '../actions/modal'; +import { TIMELINE_DELETE } from '../actions/timelines'; + +type ModalProps = Record<string, unknown>; +interface Modal { + modalType: ModalType; + modalProps: ModalProps; +} + +const Modal = ImmutableRecord<Modal>({ + modalType: 'ACTIONS', + modalProps: ImmutableRecord({})(), +}); + +interface ModalState { + ignoreFocus: boolean; + stack: Stack<ImmutableRecord<Modal>>; +} + +const initialState = ImmutableRecord<ModalState>({ + ignoreFocus: false, + stack: Stack(), +})(); +type State = typeof initialState; + +interface PopModalOption { + modalType: ModalType | undefined; + ignoreFocus: boolean; +} +const popModal = ( + state: State, + { modalType, ignoreFocus }: PopModalOption +): State => { + if ( + modalType === undefined || + modalType === state.get('stack').get(0)?.get('modalType') + ) { + return state + .set('ignoreFocus', !!ignoreFocus) + .update('stack', (stack) => stack.shift()); + } else { + return state; + } +}; + +const pushModal = ( + state: State, + modalType: ModalType, + modalProps: ModalProps +): State => { + return state.withMutations((record) => { + record.set('ignoreFocus', false); + record.update('stack', (stack) => + stack.unshift(Modal({ modalType, modalProps })) + ); + }); +}; + +export function modalReducer( + state: State = initialState, + action: PayloadAction<{ + modalType: ModalType; + ignoreFocus: boolean; + modalProps: Record<string, unknown>; + }> +) { + switch (action.type) { + case openModal.type: + return pushModal( + state, + action.payload.modalType, + action.payload.modalProps + ); + case closeModal.type: + return popModal(state, action.payload); + case COMPOSE_UPLOAD_CHANGE_SUCCESS: + return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false }); + case TIMELINE_DELETE: + return state.update('stack', (stack) => + stack.filterNot( + // @ts-expect-error TIMELINE_DELETE action is not typed yet. + (modal) => modal.get('modalProps').statusId === action.id + ) + ); + default: + return state; + } +}