From cdfd31372f7f04b6e80345682bccf4a87508874b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 16:54:47 -0500 Subject: [PATCH 01/10] Suggestions: chunk the wtf panel --- app/soapbox/features/ui/util/async-components.js | 4 ++++ app/soapbox/pages/default_page.js | 9 +++++++-- app/soapbox/pages/home_page.js | 9 ++++++--- app/soapbox/pages/profile_page.js | 9 +++++++-- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index d7543e842..489554014 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -282,6 +282,10 @@ export function ScheduleForm() { return import(/* webpackChunkName: "features/compose" */'../../compose/components/schedule_form'); } +export function WhoToFollowPanel() { + return import(/* webpackChunkName: "features/follow_recommendations" */'../components/who_to_follow_panel'); +} + export function FollowRecommendations() { return import(/* webpackChunkName: "features/follow_recommendations" */'../../follow_recommendations'); } diff --git a/app/soapbox/pages/default_page.js b/app/soapbox/pages/default_page.js index 71bfa96a2..6417e483e 100644 --- a/app/soapbox/pages/default_page.js +++ b/app/soapbox/pages/default_page.js @@ -1,7 +1,8 @@ import React from 'react'; import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import WhoToFollowPanel from 'soapbox/features/ui/components/who_to_follow_panel'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { WhoToFollowPanel } from 'soapbox/features/ui/util/async-components'; import TrendsPanel from 'soapbox/features/ui/components/trends_panel'; import PromoPanel from 'soapbox/features/ui/components/promo_panel'; import FeaturesPanel from 'soapbox/features/ui/components/features_panel'; @@ -45,7 +46,11 @@ class DefaultPage extends ImmutablePureComponent {
{me ? : } {showTrendsPanel && } - {showWhoToFollowPanel && } + {showWhoToFollowPanel && ( + + {Component => } + + )}
diff --git a/app/soapbox/pages/home_page.js b/app/soapbox/pages/home_page.js index 5ed036719..0188a766b 100644 --- a/app/soapbox/pages/home_page.js +++ b/app/soapbox/pages/home_page.js @@ -6,11 +6,10 @@ import BundleContainer from '../features/ui/containers/bundle_container'; import ComposeFormContainer from '../features/compose/containers/compose_form_container'; import Avatar from '../components/avatar'; import UserPanel from 'soapbox/features/ui/components/user_panel'; -import WhoToFollowPanel from 'soapbox/features/ui/components/who_to_follow_panel'; import TrendsPanel from 'soapbox/features/ui/components/trends_panel'; import PromoPanel from 'soapbox/features/ui/components/promo_panel'; import FundingPanel from 'soapbox/features/ui/components/funding_panel'; -import { CryptoDonatePanel } from 'soapbox/features/ui/util/async-components'; +import { WhoToFollowPanel, CryptoDonatePanel } from 'soapbox/features/ui/util/async-components'; // import GroupSidebarPanel from '../features/groups/sidebar_panel'; import FeaturesPanel from 'soapbox/features/ui/components/features_panel'; import SignUpPanel from 'soapbox/features/ui/components/sign_up_panel'; @@ -88,7 +87,11 @@ class HomePage extends ImmutablePureComponent {
{me ? : } {showTrendsPanel && } - {showWhoToFollowPanel && } + {showWhoToFollowPanel && ( + + {Component => } + + )}
diff --git a/app/soapbox/pages/profile_page.js b/app/soapbox/pages/profile_page.js index 648c26b07..c1376b2cf 100644 --- a/app/soapbox/pages/profile_page.js +++ b/app/soapbox/pages/profile_page.js @@ -5,7 +5,8 @@ import PropTypes from 'prop-types'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Helmet from 'soapbox/components/helmet'; import HeaderContainer from '../features/account_timeline/containers/header_container'; -import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { WhoToFollowPanel } from 'soapbox/features/ui/util/async-components'; import LinkFooter from '../features/ui/components/link_footer'; import SignUpPanel from '../features/ui/components/sign_up_panel'; import ProfileInfoPanel from '../features/ui/components/profile_info_panel'; @@ -99,8 +100,12 @@ class ProfilePage extends ImmutablePureComponent {
- {features.suggestions && } {account && } + {features.suggestions && ( + + {Component => } + + )}
From 7f741a3ad0691bc04cb9b216aa1ddfb9f0d69154 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 17:05:34 -0500 Subject: [PATCH 02/10] Suggestions: make DRY, fix isLoading state --- .../follow_recommendations_container.js | 36 +++++++++++++++++++ .../features/follow_recommendations/index.js | 21 ++--------- app/soapbox/features/home_timeline/index.js | 36 +++++-------------- 3 files changed, 48 insertions(+), 45 deletions(-) create mode 100644 app/soapbox/features/follow_recommendations/components/follow_recommendations_container.js diff --git a/app/soapbox/features/follow_recommendations/components/follow_recommendations_container.js b/app/soapbox/features/follow_recommendations/components/follow_recommendations_container.js new file mode 100644 index 000000000..657780f43 --- /dev/null +++ b/app/soapbox/features/follow_recommendations/components/follow_recommendations_container.js @@ -0,0 +1,36 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; +import Button from 'soapbox/components/button'; +import FollowRecommendationsList from './follow_recommendations_list'; + +export default class FollowRecommendationsContainer extends React.Component { + + static propTypes = { + onDone: PropTypes.func.isRequired, + } + + handleDone = () => { + this.props.onDone(); + } + + render() { + return ( +
+
+

+

+
+ + + +
+ +
+
+ ); + } + +} diff --git a/app/soapbox/features/follow_recommendations/index.js b/app/soapbox/features/follow_recommendations/index.js index 6e043c9f2..b3aa44ea6 100644 --- a/app/soapbox/features/follow_recommendations/index.js +++ b/app/soapbox/features/follow_recommendations/index.js @@ -1,9 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; import Column from 'soapbox/features/ui/components/column'; -import Button from 'soapbox/components/button'; -import FollowRecommendationsList from './components/follow_recommendations_list'; +import FollowRecommendationsContainer from './components/follow_recommendations_container'; export default class FollowRecommendations extends React.Component { @@ -11,7 +9,7 @@ export default class FollowRecommendations extends React.Component { router: PropTypes.object.isRequired, }; - handleDone = () => { + onDone = () => { const { router } = this.context; router.history.push('/'); @@ -20,20 +18,7 @@ export default class FollowRecommendations extends React.Component { render() { return ( -
-
-

-

-
- - - -
- -
-
+
); } diff --git a/app/soapbox/features/home_timeline/index.js b/app/soapbox/features/home_timeline/index.js index 71a146549..e62865c77 100644 --- a/app/soapbox/features/home_timeline/index.js +++ b/app/soapbox/features/home_timeline/index.js @@ -9,12 +9,11 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ColumnSettingsContainer from './containers/column_settings_container'; import HomeColumnHeader from '../../components/home_column_header'; import { Link } from 'react-router-dom'; -import Button from 'soapbox/components/button'; import { OrderedSet as ImmutableOrderedSet } from 'immutable'; import { getFeatures } from 'soapbox/utils/features'; -function FollowRecommendationsList() { - return import(/* webpackChunkName: "features/follow_recommendations" */'soapbox/features/follow_recommendations/components/follow_recommendations_list'); +function FollowRecommendationsContainer() { + return import(/* webpackChunkName: "features/follow_recommendations" */'soapbox/features/follow_recommendations/components/follow_recommendations_container'); } const messages = defineMessages({ @@ -29,6 +28,7 @@ const mapStateToProps = state => { hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0, isPartial: state.getIn(['timelines', 'home', 'isPartial']), siteTitle: state.getIn(['instance', 'title']), + isLoading: state.getIn(['timelines', 'home', 'isLoading'], true), isEmpty: state.getIn(['timelines', 'home', 'items'], ImmutableOrderedSet()).isEmpty(), features, }; @@ -44,6 +44,7 @@ class HomeTimeline extends React.PureComponent { hasUnread: PropTypes.bool, isPartial: PropTypes.bool, siteTitle: PropTypes.string, + isLoading: PropTypes.bool, isEmpty: PropTypes.bool, features: PropTypes.object.isRequired, }; @@ -94,29 +95,8 @@ class HomeTimeline extends React.PureComponent { this.setState({ done: true }); } - renderFollowRecommendations = () => { - return ( -
-
-

-

-
- - - {Component => } - - -
- -
-
- ); - } - render() { - const { intl, hasUnread, siteTitle, isEmpty, features } = this.props; + const { intl, hasUnread, siteTitle, isLoading, isEmpty, features } = this.props; const { done } = this.state; return ( @@ -124,8 +104,10 @@ class HomeTimeline extends React.PureComponent { - {(features.suggestions && isEmpty && !done) ? ( - this.renderFollowRecommendations() + {(features.suggestions && isEmpty && !isLoading && !done) ? ( + + {Component => } + ) : ( Date: Thu, 16 Sep 2021 15:44:39 -0500 Subject: [PATCH 03/10] Chunk modal components into features/ui --- .../features/ui/components/modal_root.js | 44 +++++++++---------- .../features/ui/util/async-components.js | 44 +++++++++++++++++++ 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/app/soapbox/features/ui/components/modal_root.js b/app/soapbox/features/ui/components/modal_root.js index 9f8a90b0a..220d7f7d8 100644 --- a/app/soapbox/features/ui/components/modal_root.js +++ b/app/soapbox/features/ui/components/modal_root.js @@ -4,45 +4,45 @@ import Base from '../../../components/modal_root'; import BundleContainer from '../containers/bundle_container'; import BundleModalError from './bundle_modal_error'; import ModalLoading from './modal_loading'; -import ActionsModal from './actions_modal'; -import MediaModal from './media_modal'; -import VideoModal from './video_modal'; -import BoostModal from './boost_modal'; -import ConfirmationModal from './confirmation_modal'; -import MissingDescriptionModal from './missing_description_modal'; -import FocalPointModal from './focal_point_modal'; -import HotkeysModal from './hotkeys_modal'; -import ComposeModal from './compose_modal'; -import UnauthorizedModal from './unauthorized_modal'; -import EditFederationModal from './edit_federation_modal'; import { + MediaModal, + VideoModal, + BoostModal, + ConfirmationModal, MuteModal, ReportModal, EmbedModal, CryptoDonateModal, ListEditor, ListAdder, + MissingDescriptionModal, + ActionsModal, + FocalPointModal, + HotkeysModal, + ComposeModal, + UnauthorizedModal, + EditFederationModal, } from '../../../features/ui/util/async-components'; const MODAL_COMPONENTS = { - 'MEDIA': () => Promise.resolve({ default: MediaModal }), - 'VIDEO': () => Promise.resolve({ default: VideoModal }), - 'BOOST': () => Promise.resolve({ default: BoostModal }), - 'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }), - 'MISSING_DESCRIPTION': () => Promise.resolve({ default: MissingDescriptionModal }), + 'MEDIA': MediaModal, + 'VIDEO': VideoModal, + 'BOOST': BoostModal, + 'CONFIRM': ConfirmationModal, + 'MISSING_DESCRIPTION': MissingDescriptionModal, 'MUTE': MuteModal, 'REPORT': ReportModal, - 'ACTIONS': () => Promise.resolve({ default: ActionsModal }), + 'ACTIONS': ActionsModal, 'EMBED': EmbedModal, 'LIST_EDITOR': ListEditor, - 'FOCAL_POINT': () => Promise.resolve({ default: FocalPointModal }), + 'FOCAL_POINT': FocalPointModal, 'LIST_ADDER':ListAdder, - 'HOTKEYS': () => Promise.resolve({ default: HotkeysModal }), - 'COMPOSE': () => Promise.resolve({ default: ComposeModal }), - 'UNAUTHORIZED': () => Promise.resolve({ default: UnauthorizedModal }), + 'HOTKEYS': HotkeysModal, + 'COMPOSE': ComposeModal, + 'UNAUTHORIZED': UnauthorizedModal, 'CRYPTO_DONATE': CryptoDonateModal, - 'EDIT_FEDERATION': () => Promise.resolve({ default: EditFederationModal }), + 'EDIT_FEDERATION': EditFederationModal, }; export default class ModalRoot extends React.PureComponent { diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 489554014..5c66f6919 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -150,6 +150,50 @@ export function Audio() { return import(/* webpackChunkName: "features/audio" */'../../audio'); } +export function MediaModal() { + return import(/* webpackChunkName: "features/ui" */'../components/media_modal'); +} + +export function VideoModal() { + return import(/* webpackChunkName: "features/ui" */'../components/video_modal'); +} + +export function BoostModal() { + return import(/* webpackChunkName: "features/ui" */'../components/boost_modal'); +} + +export function ConfirmationModal() { + return import(/* webpackChunkName: "features/ui" */'../components/confirmation_modal'); +} + +export function MissingDescriptionModal() { + return import(/* webpackChunkName: "features/ui" */'../components/missing_description_modal'); +} + +export function ActionsModal() { + return import(/* webpackChunkName: "features/ui" */'../components/actions_modal'); +} + +export function FocalPointModal() { + return import(/* webpackChunkName: "features/ui" */'../components/focal_point_modal'); +} + +export function HotkeysModal() { + return import(/* webpackChunkName: "features/ui" */'../components/hotkeys_modal'); +} + +export function ComposeModal() { + return import(/* webpackChunkName: "features/ui" */'../components/compose_modal'); +} + +export function UnauthorizedModal() { + return import(/* webpackChunkName: "features/ui" */'../components/unauthorized_modal'); +} + +export function EditFederationModal() { + return import(/* webpackChunkName: "features/ui" */'../components/edit_federation_modal'); +} + export function EmbedModal() { return import(/* webpackChunkName: "modals/embed_modal" */'../components/embed_modal'); } From b0e37c773e76cc658bcb296952af6d92a7a45daf Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 17:48:13 -0500 Subject: [PATCH 04/10] Load panels async --- app/soapbox/components/profile_hover_card.js | 7 ++- app/soapbox/containers/soapbox.js | 5 +- .../features/ui/util/async-components.js | 24 ++++++++++ app/soapbox/pages/default_page.js | 32 +++++++++---- app/soapbox/pages/home_page.js | 47 ++++++++++++++----- app/soapbox/pages/profile_page.js | 10 ++-- app/soapbox/pages/remote_instance_page.js | 17 +++++-- 7 files changed, 111 insertions(+), 31 deletions(-) diff --git a/app/soapbox/components/profile_hover_card.js b/app/soapbox/components/profile_hover_card.js index 202be475d..c9d1024e7 100644 --- a/app/soapbox/components/profile_hover_card.js +++ b/app/soapbox/components/profile_hover_card.js @@ -4,7 +4,8 @@ import { useSelector, useDispatch } from 'react-redux'; import { makeGetAccount } from 'soapbox/selectors'; import { injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import UserPanel from 'soapbox/features/ui/components/user_panel'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { UserPanel } from 'soapbox/features/ui/util/async-components'; import ActionButton from 'soapbox/features/ui/components/action_button'; import { isAdmin, isModerator } from 'soapbox/utils/accounts'; import Badge from 'soapbox/components/badge'; @@ -74,7 +75,9 @@ export const ProfileHoverCard = ({ visible }) => { }
- + + {Component => } + {badges.length > 0 &&
{badges} diff --git a/app/soapbox/containers/soapbox.js b/app/soapbox/containers/soapbox.js index bc53d5c9d..1bde94db0 100644 --- a/app/soapbox/containers/soapbox.js +++ b/app/soapbox/containers/soapbox.js @@ -15,8 +15,6 @@ import UI from '../features/ui'; // import Introduction from '../features/introduction'; import { preload } from '../actions/preload'; import { IntlProvider } from 'react-intl'; -import { previewState as previewMediaState } from 'soapbox/features/ui/components/media_modal'; -import { previewState as previewVideoState } from 'soapbox/features/ui/components/video_modal'; import ErrorBoundary from '../components/error_boundary'; import { fetchInstance } from 'soapbox/actions/instance'; import { fetchSoapboxConfig } from 'soapbox/actions/soapbox'; @@ -30,6 +28,9 @@ import { FE_SUBDIRECTORY } from 'soapbox/build_config'; const validLocale = locale => Object.keys(messages).includes(locale); +const previewMediaState = 'previewMediaModal'; +const previewVideoState = 'previewVideoModal'; + export const store = configureStore(); store.dispatch(preload()); diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 5c66f6919..0c72d0b7b 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -290,6 +290,30 @@ export function ModerationLog() { return import(/* webpackChunkName: "features/admin/moderation_log" */'../../admin/moderation_log'); } +export function UserPanel() { + return import(/* webpackChunkName: "features/ui" */'../components/user_panel'); +} + +export function FeaturesPanel() { + return import(/* webpackChunkName: "features/ui" */'../components/features_panel'); +} + +export function PromoPanel() { + return import(/* webpackChunkName: "features/ui" */'../components/promo_panel'); +} + +export function SignUpPanel() { + return import(/* webpackChunkName: "features/ui" */'../components/sign_up_panel'); +} + +export function FundingPanel() { + return import(/* webpackChunkName: "features/ui" */'../components/funding_panel'); +} + +export function TrendsPanel() { + return import(/* webpackChunkName: "features/trends" */'../components/trends_panel'); +} + export function CryptoDonate() { return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate'); } diff --git a/app/soapbox/pages/default_page.js b/app/soapbox/pages/default_page.js index 6417e483e..1733eb147 100644 --- a/app/soapbox/pages/default_page.js +++ b/app/soapbox/pages/default_page.js @@ -2,11 +2,13 @@ import React from 'react'; import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { WhoToFollowPanel } from 'soapbox/features/ui/util/async-components'; -import TrendsPanel from 'soapbox/features/ui/components/trends_panel'; -import PromoPanel from 'soapbox/features/ui/components/promo_panel'; -import FeaturesPanel from 'soapbox/features/ui/components/features_panel'; -import SignUpPanel from 'soapbox/features/ui/components/sign_up_panel'; +import { + WhoToFollowPanel, + TrendsPanel, + PromoPanel, + FeaturesPanel, + SignUpPanel, +} from 'soapbox/features/ui/util/async-components'; import LinkFooter from 'soapbox/features/ui/components/link_footer'; import { getFeatures } from 'soapbox/utils/features'; @@ -44,14 +46,28 @@ class DefaultPage extends ImmutablePureComponent {
- {me ? : } - {showTrendsPanel && } + {me ? ( + + {Component => } + + ) : ( + + {Component => } + + )} + {showTrendsPanel && ( + + {Component => } + + )} {showWhoToFollowPanel && ( {Component => } )} - + + {Component => } +
diff --git a/app/soapbox/pages/home_page.js b/app/soapbox/pages/home_page.js index 0188a766b..d571514dc 100644 --- a/app/soapbox/pages/home_page.js +++ b/app/soapbox/pages/home_page.js @@ -5,14 +5,17 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import BundleContainer from '../features/ui/containers/bundle_container'; import ComposeFormContainer from '../features/compose/containers/compose_form_container'; import Avatar from '../components/avatar'; -import UserPanel from 'soapbox/features/ui/components/user_panel'; -import TrendsPanel from 'soapbox/features/ui/components/trends_panel'; -import PromoPanel from 'soapbox/features/ui/components/promo_panel'; -import FundingPanel from 'soapbox/features/ui/components/funding_panel'; -import { WhoToFollowPanel, CryptoDonatePanel } from 'soapbox/features/ui/util/async-components'; +import { + WhoToFollowPanel, + CryptoDonatePanel, + UserPanel, + TrendsPanel, + PromoPanel, + FundingPanel, + FeaturesPanel, + SignUpPanel, +} from 'soapbox/features/ui/util/async-components'; // import GroupSidebarPanel from '../features/groups/sidebar_panel'; -import FeaturesPanel from 'soapbox/features/ui/components/features_panel'; -import SignUpPanel from 'soapbox/features/ui/components/sign_up_panel'; import LinkFooter from 'soapbox/features/ui/components/link_footer'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { getFeatures } from 'soapbox/utils/features'; @@ -56,8 +59,14 @@ class HomePage extends ImmutablePureComponent {
- - {showFundingPanel && } + + {Component => } + + {showFundingPanel && ( + + {Component => } + + )} {showCryptoDonatePanel && ( {Component => } @@ -85,14 +94,28 @@ class HomePage extends ImmutablePureComponent {
- {me ? : } - {showTrendsPanel && } + {me ? ( + + {Component => } + + ) : ( + + {Component => } + + )} + {showTrendsPanel && ( + + {Component => } + + )} {showWhoToFollowPanel && ( {Component => } )} - + + {Component => } +
diff --git a/app/soapbox/pages/profile_page.js b/app/soapbox/pages/profile_page.js index c1376b2cf..663c77b3e 100644 --- a/app/soapbox/pages/profile_page.js +++ b/app/soapbox/pages/profile_page.js @@ -6,9 +6,11 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import Helmet from 'soapbox/components/helmet'; import HeaderContainer from '../features/account_timeline/containers/header_container'; import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; -import { WhoToFollowPanel } from 'soapbox/features/ui/util/async-components'; +import { + WhoToFollowPanel, + SignUpPanel, +} from 'soapbox/features/ui/util/async-components'; import LinkFooter from '../features/ui/components/link_footer'; -import SignUpPanel from '../features/ui/components/sign_up_panel'; import ProfileInfoPanel from '../features/ui/components/profile_info_panel'; import ProfileMediaPanel from '../features/ui/components/profile_media_panel'; import { getAcct } from 'soapbox/utils/accounts'; @@ -99,7 +101,9 @@ class ProfilePage extends ImmutablePureComponent {
- + + {Component => } + {account && } {features.suggestions && ( diff --git a/app/soapbox/pages/remote_instance_page.js b/app/soapbox/pages/remote_instance_page.js index b1a86ba9a..d6ed14437 100644 --- a/app/soapbox/pages/remote_instance_page.js +++ b/app/soapbox/pages/remote_instance_page.js @@ -1,8 +1,11 @@ import React from 'react'; import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import PromoPanel from 'soapbox/features/ui/components/promo_panel'; -import FeaturesPanel from 'soapbox/features/ui/components/features_panel'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { + PromoPanel, + FeaturesPanel, +} from 'soapbox/features/ui/util/async-components'; import LinkFooter from 'soapbox/features/ui/components/link_footer'; import InstanceInfoPanel from 'soapbox/features/ui/components/instance_info_panel'; import InstanceModerationPanel from 'soapbox/features/ui/components/instance_moderation_panel'; @@ -46,8 +49,14 @@ class RemoteInstancePage extends ImmutablePureComponent {
- {me && } - + {me && ( + + {Component => } + + )} + + {Component => } +
From aeef12acf0d3c3706007eb3bfa7a19188c339528 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 18:31:22 -0500 Subject: [PATCH 05/10] Rip out react-redux-loading-bar --- .../features/ui/components/image_loader.js | 2 -- .../ui/containers/loading_bar_container.js | 8 ------ app/soapbox/features/ui/index.js | 2 -- app/soapbox/middleware/loading_bar.js | 25 ------------------- app/soapbox/reducers/index.js | 2 -- app/soapbox/store/configureStore.js | 2 -- app/styles/loading.scss | 8 ------ app/styles/ui.scss | 4 --- docs/store.md | 9 ------- package.json | 1 - yarn.lock | 8 ------ 11 files changed, 71 deletions(-) delete mode 100644 app/soapbox/features/ui/containers/loading_bar_container.js delete mode 100644 app/soapbox/middleware/loading_bar.js diff --git a/app/soapbox/features/ui/components/image_loader.js b/app/soapbox/features/ui/components/image_loader.js index 4b699365b..99f7c2981 100644 --- a/app/soapbox/features/ui/components/image_loader.js +++ b/app/soapbox/features/ui/components/image_loader.js @@ -1,7 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { LoadingBar } from 'react-redux-loading-bar'; import ZoomableImage from './zoomable_image'; export default class ImageLoader extends React.PureComponent { @@ -138,7 +137,6 @@ export default class ImageLoader extends React.PureComponent { return (
- {loading ? ( ({ - loading: state.get('loadingBar')[ownProps.scope || 'default'], -}); - -export default connect(mapStateToProps)(LoadingBar.WrappedComponent); diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index 80b3b314d..02d1c0cee 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -10,7 +10,6 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; import NotificationsContainer from './containers/notifications_container'; -import LoadingBarContainer from './containers/loading_bar_container'; import ModalContainer from './containers/modal_container'; import { debounce } from 'lodash'; import { uploadCompose, resetCompose } from '../../actions/compose'; @@ -660,7 +659,6 @@ class UI extends React.PureComponent { {me && floatingActionButton} - {me && } diff --git a/app/soapbox/middleware/loading_bar.js b/app/soapbox/middleware/loading_bar.js deleted file mode 100644 index da8cc4c7d..000000000 --- a/app/soapbox/middleware/loading_bar.js +++ /dev/null @@ -1,25 +0,0 @@ -import { showLoading, hideLoading } from 'react-redux-loading-bar'; - -const defaultTypeSuffixes = ['PENDING', 'FULFILLED', 'REJECTED']; - -export default function loadingBarMiddleware(config = {}) { - const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes; - - return ({ dispatch }) => next => (action) => { - if (action.type && !action.skipLoading) { - const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes; - - const isPending = new RegExp(`${PENDING}$`, 'g'); - const isFulfilled = new RegExp(`${FULFILLED}$`, 'g'); - const isRejected = new RegExp(`${REJECTED}$`, 'g'); - - if (action.type.match(isPending)) { - dispatch(showLoading()); - } else if (action.type.match(isFulfilled) || action.type.match(isRejected)) { - dispatch(hideLoading()); - } - } - - return next(action); - }; -} diff --git a/app/soapbox/reducers/index.js b/app/soapbox/reducers/index.js index 5c050b133..2b7ecd23c 100644 --- a/app/soapbox/reducers/index.js +++ b/app/soapbox/reducers/index.js @@ -5,7 +5,6 @@ import dropdown_menu from './dropdown_menu'; import timelines from './timelines'; import meta from './meta'; import alerts from './alerts'; -import { loadingBarReducer } from 'react-redux-loading-bar'; import modal from './modal'; import user_lists from './user_lists'; import domain_lists from './domain_lists'; @@ -61,7 +60,6 @@ const appReducer = combineReducers({ timelines, meta, alerts, - loadingBar: loadingBarReducer, modal, user_lists, domain_lists, diff --git a/app/soapbox/store/configureStore.js b/app/soapbox/store/configureStore.js index 0e0d45c66..63f92cf53 100644 --- a/app/soapbox/store/configureStore.js +++ b/app/soapbox/store/configureStore.js @@ -1,14 +1,12 @@ import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import appReducer from '../reducers'; -import loadingBarMiddleware from '../middleware/loading_bar'; import errorsMiddleware from '../middleware/errors'; import soundsMiddleware from '../middleware/sounds'; export default function configureStore() { return createStore(appReducer, compose(applyMiddleware( thunk, - loadingBarMiddleware({ promiseTypeSuffixes: ['REQUEST', 'SUCCESS', 'FAIL'] }), errorsMiddleware(), soundsMiddleware(), ), window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f)); diff --git a/app/styles/loading.scss b/app/styles/loading.scss index 6f5f1736f..45145d1f2 100644 --- a/app/styles/loading.scss +++ b/app/styles/loading.scss @@ -148,14 +148,6 @@ animation: shake-bottom 0.8s cubic-bezier(0.455, 0.03, 0.515, 0.955) 2s 2 both; } -.loading-bar { - background-color: var(--highlight-text-color); - height: 3px; - position: absolute; - top: 0; - left: 0; -} - .load-more { display: block; color: var(--primary-text-color); diff --git a/app/styles/ui.scss b/app/styles/ui.scss index d05a18e4c..a51495ec8 100644 --- a/app/styles/ui.scss +++ b/app/styles/ui.scss @@ -279,10 +279,6 @@ object-fit: contain; } - .loading-bar { - position: relative; - } - &.image-loader--amorphous .image-loader__preview-canvas { display: none; } diff --git a/docs/store.md b/docs/store.md index 69f2ba1e4..34088ab8c 100644 --- a/docs/store.md +++ b/docs/store.md @@ -104,15 +104,6 @@ If it's not documented, it's because I inherited it from Mastodon and I don't kn alerts: [] ``` -- `loadingBar` - Managed by [react-redux-loading-bar](https://github.com/mironov/react-redux-loading-bar) - - Sample: - ``` - loadingBar: { - 'default': 0 - } - ``` - - `modal` Sample: diff --git a/package.json b/package.json index e497e8b2b..f06f4fa27 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,6 @@ "react-overlays": "^0.9.0", "react-popper": "^2.2.3", "react-redux": "^7.2.5", - "react-redux-loading-bar": "^5.0.0", "react-router-dom": "^4.3.1", "react-router-scroll-4": "^1.0.0-beta.1", "react-sparklines": "^1.7.0", diff --git a/yarn.lock b/yarn.lock index 7fb7cb9f5..3bc208261 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7879,14 +7879,6 @@ react-popper@^2.2.3, react-popper@^2.2.5: react-fast-compare "^3.0.1" warning "^4.0.2" -react-redux-loading-bar@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/react-redux-loading-bar/-/react-redux-loading-bar-5.0.2.tgz#e62d527892b0a7682baa2ebbb3fd34c0b807e485" - integrity sha512-M+gK/Q79UG3iVljv6myRJptdQ5sIKdYDigeukwGocvWLCgWFdtpeP8IY8lBIYsqHXtuFBP/gj7E3qvGwCtcpRQ== - dependencies: - prop-types "^15.7.2" - react-lifecycles-compat "^3.0.4" - react-redux@^7.2.5: version "7.2.5" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.5.tgz#213c1b05aa1187d9c940ddfc0b29450957f6a3b8" From abcdc1fd63f1b3bec7b41707e879099ded125c60 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 19:17:55 -0500 Subject: [PATCH 06/10] Profile: make account panels async --- .../features/account/components/header.js | 21 +++++++++++-------- .../features/ui/util/async-components.js | 8 +++++++ app/soapbox/pages/profile_page.js | 14 +++++++++---- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/app/soapbox/features/account/components/header.js b/app/soapbox/features/account/components/header.js index f5a4efe35..53a78015f 100644 --- a/app/soapbox/features/account/components/header.js +++ b/app/soapbox/features/account/components/header.js @@ -22,7 +22,8 @@ import Avatar from 'soapbox/components/avatar'; import { shortNumberFormat } from 'soapbox/utils/numbers'; import { NavLink } from 'react-router-dom'; import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; -import ProfileInfoPanel from '../../ui/components/profile_info_panel'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { ProfileInfoPanel } from 'soapbox/features/ui/util/async-components'; import { debounce } from 'lodash'; import StillImage from 'soapbox/components/still_image'; import ActionButton from 'soapbox/features/ui/components/action_button'; @@ -303,12 +304,13 @@ class Header extends ImmutablePureComponent {
- { - isSmallScreen && + {isSmallScreen && (
- + + {Component => } +
- } + )}
); @@ -380,12 +382,13 @@ class Header extends ImmutablePureComponent { }
- { - isSmallScreen && + {isSmallScreen && (
- + + {Component => } +
- } + )}
diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 0c72d0b7b..278edeae4 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -314,6 +314,14 @@ export function TrendsPanel() { return import(/* webpackChunkName: "features/trends" */'../components/trends_panel'); } +export function ProfileInfoPanel() { + return import(/* webpackChunkName: "features/account_timeline" */'../components/profile_info_panel'); +} + +export function ProfileMediaPanel() { + return import(/* webpackChunkName: "features/account_gallery" */'../components/profile_media_panel'); +} + export function CryptoDonate() { return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate'); } diff --git a/app/soapbox/pages/profile_page.js b/app/soapbox/pages/profile_page.js index 663c77b3e..ad15d0cf3 100644 --- a/app/soapbox/pages/profile_page.js +++ b/app/soapbox/pages/profile_page.js @@ -9,10 +9,10 @@ import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { WhoToFollowPanel, SignUpPanel, + ProfileInfoPanel, + ProfileMediaPanel, } from 'soapbox/features/ui/util/async-components'; import LinkFooter from '../features/ui/components/link_footer'; -import ProfileInfoPanel from '../features/ui/components/profile_info_panel'; -import ProfileMediaPanel from '../features/ui/components/profile_media_panel'; import { getAcct } from 'soapbox/utils/accounts'; import { displayFqn } from 'soapbox/utils/state'; import { getFeatures } from 'soapbox/utils/features'; @@ -89,7 +89,9 @@ class ProfilePage extends ImmutablePureComponent {
- + + {Component => } +
@@ -104,7 +106,11 @@ class ProfilePage extends ImmutablePureComponent { {Component => } - {account && } + {account && ( + + {Component => } + + )} {features.suggestions && ( {Component => } From aa54e0bd0bfb52b6e8ad3677e6ea1dddc17b4872 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 19:23:48 -0500 Subject: [PATCH 07/10] RemoteInstance: async panels --- app/soapbox/features/ui/util/async-components.js | 8 ++++++++ app/soapbox/pages/remote_instance_page.js | 14 ++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 278edeae4..40b92d935 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -322,6 +322,14 @@ export function ProfileMediaPanel() { return import(/* webpackChunkName: "features/account_gallery" */'../components/profile_media_panel'); } +export function InstanceInfoPanel() { + return import(/* webpackChunkName: "features/remote_timeline" */'../components/profile_media_panel'); +} + +export function InstanceModerationPanel() { + return import(/* webpackChunkName: "features/remote_timeline" */'../components/profile_media_panel'); +} + export function CryptoDonate() { return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate'); } diff --git a/app/soapbox/pages/remote_instance_page.js b/app/soapbox/pages/remote_instance_page.js index d6ed14437..815a21ac7 100644 --- a/app/soapbox/pages/remote_instance_page.js +++ b/app/soapbox/pages/remote_instance_page.js @@ -5,10 +5,10 @@ import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { PromoPanel, FeaturesPanel, + InstanceInfoPanel, + InstanceModerationPanel, } from 'soapbox/features/ui/util/async-components'; import LinkFooter from 'soapbox/features/ui/components/link_footer'; -import InstanceInfoPanel from 'soapbox/features/ui/components/instance_info_panel'; -import InstanceModerationPanel from 'soapbox/features/ui/components/instance_moderation_panel'; import { federationRestrictionsDisclosed } from 'soapbox/utils/state'; import { isAdmin } from 'soapbox/utils/accounts'; @@ -36,8 +36,14 @@ class RemoteInstancePage extends ImmutablePureComponent {
- - {(disclosed || isAdmin) && } + + {Component => } + + {(disclosed || isAdmin) && ( + + {Component => } + + )}
From 1e77adda34c51caf25057b1e7f455dc601bdc390 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 19:34:45 -0500 Subject: [PATCH 08/10] Admin: async components --- app/soapbox/features/ui/util/async-components.js | 8 ++++++++ app/soapbox/pages/admin_page.js | 15 +++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 40b92d935..1d3eae519 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -330,6 +330,14 @@ export function InstanceModerationPanel() { return import(/* webpackChunkName: "features/remote_timeline" */'../components/profile_media_panel'); } +export function LatestAccountsPanel() { + return import(/* webpackChunkName: "features/admin" */'../../admin/components/latest_accounts_panel'); +} + +export function AdminNav() { + return import(/* webpackChunkName: "features/admin" */'../../admin/components/admin_nav'); +} + export function CryptoDonate() { return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate'); } diff --git a/app/soapbox/pages/admin_page.js b/app/soapbox/pages/admin_page.js index a010581cc..a91d87461 100644 --- a/app/soapbox/pages/admin_page.js +++ b/app/soapbox/pages/admin_page.js @@ -1,8 +1,11 @@ import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import LinkFooter from '../features/ui/components/link_footer'; -import AdminNav from 'soapbox/features/admin/components/admin_nav'; -import LatestAccountsPanel from 'soapbox/features/admin/components/latest_accounts_panel'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import { + AdminNav, + LatestAccountsPanel, +} from 'soapbox/features/ui/util/async-components'; export default class AdminPage extends ImmutablePureComponent { @@ -17,7 +20,9 @@ class AdminPage extends ImmutablePureComponent {
- + + {Component => } +
@@ -29,7 +34,9 @@ class AdminPage extends ImmutablePureComponent {
- + + {Component => } +
From aeddec28923c9a07709184ddc458304262d15fc0 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 20:01:04 -0500 Subject: [PATCH 09/10] UI: async UI components --- app/soapbox/features/public_layout/index.js | 17 ++++++-- app/soapbox/features/ui/index.js | 43 +++++++++++++------ .../features/ui/util/async-components.js | 24 +++++++++++ 3 files changed, 68 insertions(+), 16 deletions(-) diff --git a/app/soapbox/features/public_layout/index.js b/app/soapbox/features/public_layout/index.js index 09dc1f263..fa33ef48a 100644 --- a/app/soapbox/features/public_layout/index.js +++ b/app/soapbox/features/public_layout/index.js @@ -1,9 +1,12 @@ import React from 'react'; import { connect } from 'react-redux'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; import { Switch, Route, Redirect } from 'react-router-dom'; -import NotificationsContainer from 'soapbox/features/ui/containers/notifications_container'; -import ModalContainer from 'soapbox/features/ui/containers/modal_container'; +import { + NotificationsContainer, + ModalContainer, +} from 'soapbox/features/ui/util/async-components'; import Header from './components/header'; import Footer from './components/footer'; import LandingPage from '../landing_page'; @@ -44,8 +47,14 @@ class PublicLayout extends ImmutablePureComponent {
- - + + + {Component => } + + + + {Component => } +
); } diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index 02d1c0cee..694eb53ed 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -9,8 +9,6 @@ import { Switch, withRouter } from 'react-router-dom'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import SoapboxPropTypes from 'soapbox/utils/soapbox_prop_types'; -import NotificationsContainer from './containers/notifications_container'; -import ModalContainer from './containers/modal_container'; import { debounce } from 'lodash'; import { uploadCompose, resetCompose } from '../../actions/compose'; import { expandHomeTimeline } from '../../actions/timelines'; @@ -24,8 +22,6 @@ import { fetchFollowRequests } from '../../actions/accounts'; import { fetchScheduledStatuses } from '../../actions/scheduled_statuses'; import { WrappedRoute } from './util/react_router_helpers'; import BundleContainer from './containers/bundle_container'; -import UploadArea from './components/upload_area'; -import TabsBar from './components/tabs_bar'; import ProfilePage from 'soapbox/pages/profile_page'; // import GroupsPage from 'soapbox/pages/groups_page'; // import GroupPage from 'soapbox/pages/group_page'; @@ -35,12 +31,10 @@ import DefaultPage from 'soapbox/pages/default_page'; import EmptyPage from 'soapbox/pages/default_page'; import AdminPage from 'soapbox/pages/admin_page'; import RemoteInstancePage from 'soapbox/pages/remote_instance_page'; -import SidebarMenu from '../../components/sidebar_menu'; import { connectUserStream } from '../../actions/streaming'; import { Redirect } from 'react-router-dom'; import Icon from 'soapbox/components/icon'; import { isStaff, isAdmin } from 'soapbox/utils/accounts'; -import ProfileHoverCard from 'soapbox/components/profile_hover_card'; import { getAccessToken } from 'soapbox/utils/auth'; import { getFeatures } from 'soapbox/utils/features'; import { fetchCustomEmojis } from 'soapbox/actions/custom_emojis'; @@ -106,6 +100,12 @@ import { FederationRestrictions, Aliases, FollowRecommendations, + TabsBar, + SidebarMenu, + UploadArea, + NotificationsContainer, + ModalContainer, + ProfileHoverCard, } from './util/async-components'; // Dummy import, to make sure that ends up in the application bundle. @@ -651,23 +651,42 @@ class UI extends React.PureComponent { return (
- + + {Component => } + + {children} {me && floatingActionButton} - - - - {me && } + + {Component => } + + + + {Component => } + + + + {Component => } + + + {me && ( + + {Component => } + + )} {me && features.chats && !mobile && ( {Component => } )} - + + + {Component => } +
); diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 1d3eae519..3b2fe5df9 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -338,6 +338,30 @@ export function AdminNav() { return import(/* webpackChunkName: "features/admin" */'../../admin/components/admin_nav'); } +export function TabsBar() { + return import(/* webpackChunkName: "features/ui" */'../../ui/components/tabs_bar'); +} + +export function SidebarMenu() { + return import(/* webpackChunkName: "features/ui" */'../../../components/sidebar_menu'); +} + +export function UploadArea() { + return import(/* webpackChunkName: "features/compose" */'../components/upload_area'); +} + +export function NotificationsContainer() { + return import(/* webpackChunkName: "features/ui" */'../containers/notifications_container'); +} + +export function ModalContainer() { + return import(/* webpackChunkName: "features/ui" */'../containers/modal_container'); +} + +export function ProfileHoverCard() { + return import(/* webpackChunkName: "features/ui" */'soapbox/components/profile_hover_card'); +} + export function CryptoDonate() { return import(/* webpackChunkName: "features/crypto_donate" */'../../crypto_donate'); } From 08cdef59c9cdc3cd66a689110302963dae75850b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 18 Sep 2021 20:09:29 -0500 Subject: [PATCH 10/10] Don't load TabsBar async --- app/soapbox/features/ui/index.js | 6 ++---- app/soapbox/features/ui/util/async-components.js | 4 ---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index 694eb53ed..bc3e7c6fd 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -22,6 +22,7 @@ import { fetchFollowRequests } from '../../actions/accounts'; import { fetchScheduledStatuses } from '../../actions/scheduled_statuses'; import { WrappedRoute } from './util/react_router_helpers'; import BundleContainer from './containers/bundle_container'; +import TabsBar from './components/tabs_bar'; import ProfilePage from 'soapbox/pages/profile_page'; // import GroupsPage from 'soapbox/pages/groups_page'; // import GroupPage from 'soapbox/pages/group_page'; @@ -100,7 +101,6 @@ import { FederationRestrictions, Aliases, FollowRecommendations, - TabsBar, SidebarMenu, UploadArea, NotificationsContainer, @@ -651,9 +651,7 @@ class UI extends React.PureComponent { return (
- - {Component => } - + {children} diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 3b2fe5df9..e49797956 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -338,10 +338,6 @@ export function AdminNav() { return import(/* webpackChunkName: "features/admin" */'../../admin/components/admin_nav'); } -export function TabsBar() { - return import(/* webpackChunkName: "features/ui" */'../../ui/components/tabs_bar'); -} - export function SidebarMenu() { return import(/* webpackChunkName: "features/ui" */'../../../components/sidebar_menu'); }