diff --git a/app/javascript/mastodon/actions/dropdown_menu.js b/app/javascript/mastodon/actions/dropdown_menu.js deleted file mode 100644 index 023151d4bf..0000000000 --- a/app/javascript/mastodon/actions/dropdown_menu.js +++ /dev/null @@ -1,10 +0,0 @@ -export const DROPDOWN_MENU_OPEN = 'DROPDOWN_MENU_OPEN'; -export const DROPDOWN_MENU_CLOSE = 'DROPDOWN_MENU_CLOSE'; - -export function openDropdownMenu(id, keyboard, scroll_key) { - return { type: DROPDOWN_MENU_OPEN, id, keyboard, scroll_key }; -} - -export function closeDropdownMenu(id) { - return { type: DROPDOWN_MENU_CLOSE, id }; -} diff --git a/app/javascript/mastodon/actions/dropdown_menu.ts b/app/javascript/mastodon/actions/dropdown_menu.ts new file mode 100644 index 0000000000..3694df1ae0 --- /dev/null +++ b/app/javascript/mastodon/actions/dropdown_menu.ts @@ -0,0 +1,11 @@ +import { createAction } from '@reduxjs/toolkit'; + +export const openDropdownMenu = createAction<{ + id: string; + keyboard: boolean; + scrollKey: string; +}>('dropdownMenu/open'); + +export const closeDropdownMenu = createAction<{ id: string }>( + 'dropdownMenu/close', +); diff --git a/app/javascript/mastodon/components/edited_timestamp/containers/dropdown_menu_container.js b/app/javascript/mastodon/components/edited_timestamp/containers/dropdown_menu_container.js index a0896d985e..726fee9076 100644 --- a/app/javascript/mastodon/components/edited_timestamp/containers/dropdown_menu_container.js +++ b/app/javascript/mastodon/components/edited_timestamp/containers/dropdown_menu_container.js @@ -4,9 +4,14 @@ import { openDropdownMenu, closeDropdownMenu } from 'mastodon/actions/dropdown_m import { fetchHistory } from 'mastodon/actions/history'; import DropdownMenu from 'mastodon/components/dropdown_menu'; +/** + * + * @param {import('mastodon/store').RootState} state + * @param {*} props + */ const mapStateToProps = (state, { statusId }) => ({ - openDropdownId: state.getIn(['dropdown_menu', 'openId']), - openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']), + openDropdownId: state.dropdownMenu.openId, + openedViaKeyboard: state.dropdownMenu.keyboard, items: state.getIn(['history', statusId, 'items']), loading: state.getIn(['history', statusId, 'loading']), }); @@ -15,11 +20,11 @@ const mapDispatchToProps = (dispatch, { statusId }) => ({ onOpen (id, onItemClick, keyboard) { dispatch(fetchHistory(statusId)); - dispatch(openDropdownMenu(id, keyboard)); + dispatch(openDropdownMenu({ id, keyboard })); }, onClose (id) { - dispatch(closeDropdownMenu(id)); + dispatch(closeDropdownMenu({ id })); }, }); diff --git a/app/javascript/mastodon/components/scrollable_list.jsx b/app/javascript/mastodon/components/scrollable_list.jsx index ce0b579f50..7672a4e424 100644 --- a/app/javascript/mastodon/components/scrollable_list.jsx +++ b/app/javascript/mastodon/components/scrollable_list.jsx @@ -23,9 +23,14 @@ const MOUSE_IDLE_DELAY = 300; const listenerOptions = supportsPassiveEvents ? { passive: true } : false; +/** + * + * @param {import('mastodon/store').RootState} state + * @param {*} props + */ const mapStateToProps = (state, { scrollKey }) => { return { - preventScroll: scrollKey === state.getIn(['dropdown_menu', 'scroll_key']), + preventScroll: scrollKey === state.dropdownMenu.scrollKey, }; }; diff --git a/app/javascript/mastodon/containers/dropdown_menu_container.js b/app/javascript/mastodon/containers/dropdown_menu_container.js index 6cf180cd53..bc9124c041 100644 --- a/app/javascript/mastodon/containers/dropdown_menu_container.js +++ b/app/javascript/mastodon/containers/dropdown_menu_container.js @@ -7,9 +7,12 @@ import { openModal, closeModal } from '../actions/modal'; import DropdownMenu from '../components/dropdown_menu'; import { isUserTouching } from '../is_mobile'; +/** + * @param {import('mastodon/store').RootState} state + */ const mapStateToProps = state => ({ - openDropdownId: state.getIn(['dropdown_menu', 'openId']), - openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']), + openDropdownId: state.dropdownMenu.openId, + openedViaKeyboard: state.dropdownMenu.keyboard, }); const mapDispatchToProps = (dispatch, { status, items, scrollKey }) => ({ @@ -25,7 +28,7 @@ const mapDispatchToProps = (dispatch, { status, items, scrollKey }) => ({ actions: items, onClick: onItemClick, }, - }) : openDropdownMenu(id, keyboard, scrollKey)); + }) : openDropdownMenu({ id, keyboard, scrollKey })); }, onClose(id) { @@ -33,7 +36,7 @@ const mapDispatchToProps = (dispatch, { status, items, scrollKey }) => ({ modalType: 'ACTIONS', ignoreFocus: false, })); - dispatch(closeDropdownMenu(id)); + dispatch(closeDropdownMenu({ id })); }, }); diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index 55ccde72f5..ac5e2d9361 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -79,7 +79,7 @@ const mapStateToProps = state => ({ hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0, hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0, canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4, - dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null, + dropdownMenuIsOpen: state.dropdownMenu.openId !== null, firstLaunch: state.getIn(['settings', 'introductionVersion'], 0) < INTRODUCTION_VERSION, username: state.getIn(['accounts', me, 'username']), }); diff --git a/app/javascript/mastodon/reducers/dropdown_menu.js b/app/javascript/mastodon/reducers/dropdown_menu.js deleted file mode 100644 index 6f92f1bbe8..0000000000 --- a/app/javascript/mastodon/reducers/dropdown_menu.js +++ /dev/null @@ -1,19 +0,0 @@ -import Immutable from 'immutable'; - -import { - DROPDOWN_MENU_OPEN, - DROPDOWN_MENU_CLOSE, -} from '../actions/dropdown_menu'; - -const initialState = Immutable.Map({ openId: null, keyboard: false, scroll_key: null }); - -export default function dropdownMenu(state = initialState, action) { - switch (action.type) { - case DROPDOWN_MENU_OPEN: - return state.merge({ openId: action.id, keyboard: action.keyboard, scroll_key: action.scroll_key }); - case DROPDOWN_MENU_CLOSE: - return state.get('openId') === action.id ? state.set('openId', null).set('scroll_key', null) : state; - default: - return state; - } -} diff --git a/app/javascript/mastodon/reducers/dropdown_menu.ts b/app/javascript/mastodon/reducers/dropdown_menu.ts new file mode 100644 index 0000000000..59e19bb16d --- /dev/null +++ b/app/javascript/mastodon/reducers/dropdown_menu.ts @@ -0,0 +1,33 @@ +import { createReducer } from '@reduxjs/toolkit'; + +import { closeDropdownMenu, openDropdownMenu } from '../actions/dropdown_menu'; + +interface DropdownMenuState { + openId: string | null; + keyboard: boolean; + scrollKey: string | null; +} + +const initialState: DropdownMenuState = { + openId: null, + keyboard: false, + scrollKey: null, +}; + +export const dropdownMenuReducer = createReducer(initialState, (builder) => { + builder + .addCase( + openDropdownMenu, + (state, { payload: { id, keyboard, scrollKey } }) => { + state.openId = id; + state.keyboard = keyboard; + state.scrollKey = scrollKey; + }, + ) + .addCase(closeDropdownMenu, (state, { payload: { id } }) => { + if (state.openId === id) { + state.openId = null; + state.scrollKey = null; + } + }); +}); diff --git a/app/javascript/mastodon/reducers/index.ts b/app/javascript/mastodon/reducers/index.ts index c61c862cfe..722f04f370 100644 --- a/app/javascript/mastodon/reducers/index.ts +++ b/app/javascript/mastodon/reducers/index.ts @@ -15,7 +15,7 @@ import contexts from './contexts'; import conversations from './conversations'; import custom_emojis from './custom_emojis'; import domain_lists from './domain_lists'; -import dropdown_menu from './dropdown_menu'; +import { dropdownMenuReducer } from './dropdown_menu'; import filters from './filters'; import followed_tags from './followed_tags'; import height_cache from './height_cache'; @@ -46,7 +46,7 @@ import user_lists from './user_lists'; const reducers = { announcements, - dropdown_menu, + dropdownMenu: dropdownMenuReducer, timelines, meta, alerts,