From 8cf246e4d3305a71e647c2f374468141b8bc846c Mon Sep 17 00:00:00 2001 From: Echo Date: Wed, 11 Jun 2025 13:12:39 +0200 Subject: [PATCH] Prevent two composers from being shown (#35006) --- .../features/ui/components/columns_area.jsx | 2 +- .../features/ui/components/compose_panel.jsx | 64 ------------------- .../features/ui/components/compose_panel.tsx | 56 ++++++++++++++++ app/javascript/mastodon/hooks/useLayout.ts | 13 ++++ 4 files changed, 70 insertions(+), 65 deletions(-) delete mode 100644 app/javascript/mastodon/features/ui/components/compose_panel.jsx create mode 100644 app/javascript/mastodon/features/ui/components/compose_panel.tsx create mode 100644 app/javascript/mastodon/hooks/useLayout.ts diff --git a/app/javascript/mastodon/features/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx index 97b54e50d3..4901ee2182 100644 --- a/app/javascript/mastodon/features/ui/components/columns_area.jsx +++ b/app/javascript/mastodon/features/ui/components/columns_area.jsx @@ -23,7 +23,7 @@ import { useColumnsContext } from '../util/columns_context'; import BundleColumnError from './bundle_column_error'; import { ColumnLoading } from './column_loading'; -import ComposePanel from './compose_panel'; +import { ComposePanel } from './compose_panel'; import DrawerLoading from './drawer_loading'; import NavigationPanel from './navigation_panel'; diff --git a/app/javascript/mastodon/features/ui/components/compose_panel.jsx b/app/javascript/mastodon/features/ui/components/compose_panel.jsx deleted file mode 100644 index e622c8859a..0000000000 --- a/app/javascript/mastodon/features/ui/components/compose_panel.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import PropTypes from 'prop-types'; -import { PureComponent } from 'react'; - -import { connect } from 'react-redux'; - -import { changeComposing, mountCompose, unmountCompose } from 'mastodon/actions/compose'; -import ServerBanner from 'mastodon/components/server_banner'; -import { Search } from 'mastodon/features/compose/components/search'; -import ComposeFormContainer from 'mastodon/features/compose/containers/compose_form_container'; -import { LinkFooter } from 'mastodon/features/ui/components/link_footer'; -import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; - -class ComposePanel extends PureComponent { - static propTypes = { - identity: identityContextPropShape, - dispatch: PropTypes.func.isRequired, - }; - - onFocus = () => { - const { dispatch } = this.props; - dispatch(changeComposing(true)); - }; - - onBlur = () => { - const { dispatch } = this.props; - dispatch(changeComposing(false)); - }; - - componentDidMount () { - const { dispatch } = this.props; - dispatch(mountCompose()); - } - - componentWillUnmount () { - const { dispatch } = this.props; - dispatch(unmountCompose()); - } - - render() { - const { signedIn } = this.props.identity; - - return ( -
- - - {!signedIn && ( - <> - -
- - )} - - {signedIn && ( - - )} - - -
- ); - } - -} - -export default connect()(withIdentity(ComposePanel)); diff --git a/app/javascript/mastodon/features/ui/components/compose_panel.tsx b/app/javascript/mastodon/features/ui/components/compose_panel.tsx new file mode 100644 index 0000000000..aa15520309 --- /dev/null +++ b/app/javascript/mastodon/features/ui/components/compose_panel.tsx @@ -0,0 +1,56 @@ +import { useCallback, useEffect } from 'react'; + +import { useLayout } from '@/mastodon/hooks/useLayout'; +import { useAppDispatch, useAppSelector } from '@/mastodon/store'; +import { + changeComposing, + mountCompose, + unmountCompose, +} from 'mastodon/actions/compose'; +import ServerBanner from 'mastodon/components/server_banner'; +import { Search } from 'mastodon/features/compose/components/search'; +import ComposeFormContainer from 'mastodon/features/compose/containers/compose_form_container'; +import { LinkFooter } from 'mastodon/features/ui/components/link_footer'; +import { useIdentity } from 'mastodon/identity_context'; + +export const ComposePanel: React.FC = () => { + const dispatch = useAppDispatch(); + const handleFocus = useCallback(() => { + dispatch(changeComposing(true)); + }, [dispatch]); + const { signedIn } = useIdentity(); + const hideComposer = useAppSelector((state) => { + const mounted = state.compose.get('mounted'); + if (typeof mounted === 'number') { + return mounted > 1; + } + return false; + }); + + useEffect(() => { + dispatch(mountCompose()); + return () => { + dispatch(unmountCompose()); + }; + }, [dispatch]); + + const { singleColumn } = useLayout(); + + return ( +
+ + + {!signedIn && ( + <> + +
+ + )} + + {signedIn && !hideComposer && } + {signedIn && hideComposer &&
} + + +
+ ); +}; diff --git a/app/javascript/mastodon/hooks/useLayout.ts b/app/javascript/mastodon/hooks/useLayout.ts new file mode 100644 index 0000000000..fc1cf136bf --- /dev/null +++ b/app/javascript/mastodon/hooks/useLayout.ts @@ -0,0 +1,13 @@ +import type { LayoutType } from '../is_mobile'; +import { useAppSelector } from '../store'; + +export const useLayout = () => { + const layout = useAppSelector( + (state) => state.meta.get('layout') as LayoutType, + ); + + return { + singleColumn: layout === 'single-column' || layout === 'mobile', + layout, + }; +};