Merge remote-tracking branch 'origin/develop' into next

merge-requests/782/head
Alex Gleason 3 years ago
commit 008d53a7d9
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7

@ -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 }) => {
<FormattedMessage id='account.follows_you' defaultMessage='Follows you' />
</span>}
<div className='profile-hover-card__action-button'><ActionButton account={account} small /></div>
<UserPanel className='profile-hover-card__user' accountId={account.get('id')} />
<BundleContainer fetchComponent={UserPanel}>
{Component => <Component className='profile-hover-card__user' accountId={account.get('id')} />}
</BundleContainer>
{badges.length > 0 &&
<div className='profile-hover-card__badges'>
{badges}

@ -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());

@ -20,7 +20,8 @@ import {
import classNames from 'classnames';
import Avatar from 'soapbox/components/avatar';
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';
@ -301,12 +302,13 @@ class Header extends ImmutablePureComponent {
<div className='account__header__extra'>
<div className='account__header__avatar' />
</div>
{
isSmallScreen &&
{isSmallScreen && (
<div className='account-mobile-container account-mobile-container--nonuser'>
<ProfileInfoPanel username={username} />
<BundleContainer fetchComponent={ProfileInfoPanel}>
{Component => <Component username={username} />}
</BundleContainer>
</div>
}
)}
</div>
</div>
);
@ -343,12 +345,13 @@ class Header extends ImmutablePureComponent {
<Avatar account={account} size={avatarSize} />
</a>
{
isSmallScreen &&
{isSmallScreen && (
<div className={classNames('account-mobile-container', { 'deactivated': deactivated })}>
<ProfileInfoPanel username={username} account={account} />
<BundleContainer fetchComponent={ProfileInfoPanel}>
{Component => <Component username={username} account={account} />}
</BundleContainer>
</div>
}
)}
<div className='account__header__extra__buttons'>
<ActionButton account={account} />

@ -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 (
<div className='scrollable follow-recommendations-container'>
<div className='column-title'>
<h3><FormattedMessage id='follow_recommendations.heading' defaultMessage="Follow people you'd like to see posts from! Here are some suggestions." /></h3>
<p><FormattedMessage id='follow_recommendations.lead' defaultMessage="Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!" /></p>
</div>
<FollowRecommendationsList />
<div className='column-actions'>
<Button onClick={this.handleDone}>
<FormattedMessage id='follow_recommendations.done' defaultMessage='Done' />
</Button>
</div>
</div>
);
}
}

@ -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 (
<Column>
<div className='scrollable follow-recommendations-container'>
<div className='column-title'>
<h3><FormattedMessage id='follow_recommendations.heading' defaultMessage="Follow people you'd like to see posts from! Here are some suggestions." /></h3>
<p><FormattedMessage id='follow_recommendations.lead' defaultMessage="Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!" /></p>
</div>
<FollowRecommendationsList />
<div className='column-actions'>
<Button onClick={this.handleDone}>
<FormattedMessage id='follow_recommendations.done' defaultMessage='Done' />
</Button>
</div>
</div>
<FollowRecommendationsContainer onDone={this.onDone} />
</Column>
);
}

@ -7,12 +7,11 @@ import Column from '../../components/column';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
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({
@ -27,6 +26,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,
};
@ -42,6 +42,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,
};
@ -92,35 +93,16 @@ class HomeTimeline extends React.PureComponent {
this.setState({ done: true });
}
renderFollowRecommendations = () => {
return (
<div className='scrollable follow-recommendations-container'>
<div className='column-title'>
<h3><FormattedMessage id='follow_recommendations.heading' defaultMessage="Follow people you'd like to see posts from! Here are some suggestions." /></h3>
<p><FormattedMessage id='follow_recommendations.lead' defaultMessage="Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!" /></p>
</div>
<BundleContainer fetchComponent={FollowRecommendationsList}>
{Component => <Component />}
</BundleContainer>
<div className='column-actions'>
<Button onClick={this.handleDone}>
<FormattedMessage id='follow_recommendations.done' defaultMessage='Done' />
</Button>
</div>
</div>
);
}
render() {
const { intl, siteTitle, isEmpty, features } = this.props;
const { intl, siteTitle, isLoading, isEmpty, features } = this.props;
const { done } = this.state;
return (
<Column label={intl.formatMessage(messages.title)}>
{(features.suggestions && isEmpty && !done) ? (
this.renderFollowRecommendations()
{(features.suggestions && isEmpty && !isLoading && !done) ? (
<BundleContainer fetchComponent={FollowRecommendationsContainer}>
{Component => <Component onDone={this.handleDone} />}
</BundleContainer>
) : (
<StatusListContainer
scrollKey='home_timeline'

@ -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 {
</div>
</div>
<Footer />
<NotificationsContainer />
<ModalContainer />
<BundleContainer fetchComponent={NotificationsContainer}>
{Component => <Component />}
</BundleContainer>
<BundleContainer fetchComponent={ModalContainer}>
{Component => <Component />}
</BundleContainer>
</div>
);
}

@ -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 (
<div className={className}>
<LoadingBar loading={loading ? 1 : 0} className='loading-bar' style={{ width: this.state.width || width }} />
{loading ? (
<canvas
className='image-loader__preview-canvas'

@ -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 {

@ -1,8 +0,0 @@
import { connect } from 'react-redux';
import LoadingBar from 'react-redux-loading-bar';
const mapStateToProps = (state, ownProps) => ({
loading: state.get('loadingBar')[ownProps.scope || 'default'],
});
export default connect(mapStateToProps)(LoadingBar.WrappedComponent);

@ -9,9 +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 LoadingBarContainer from './containers/loading_bar_container';
import ModalContainer from './containers/modal_container';
import { debounce } from 'lodash';
import { uploadCompose, resetCompose } from '../../actions/compose';
import { expandHomeTimeline } from '../../actions/timelines';
@ -25,7 +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';
@ -37,12 +33,10 @@ import StatusPage from 'soapbox/pages/status_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';
@ -110,6 +104,11 @@ import {
FederationRestrictions,
Aliases,
FollowRecommendations,
SidebarMenu,
UploadArea,
NotificationsContainer,
ModalContainer,
ProfileHoverCard,
} from './util/async-components';
// Dummy import, to make sure that <Status /> ends up in the application bundle.
@ -657,24 +656,40 @@ class UI extends React.PureComponent {
<div className={classnames} ref={this.setRef} style={style}>
<TabsBar />
<SubNavigation />
<SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange} soapbox={soapbox}>
{children}
</SwitchingColumnsArea>
{me && floatingActionButton}
<NotificationsContainer />
<LoadingBarContainer className='loading-bar' />
<ModalContainer />
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />
{me && <SidebarMenu />}
<BundleContainer fetchComponent={NotificationsContainer}>
{Component => <Component />}
</BundleContainer>
<BundleContainer fetchComponent={ModalContainer}>
{Component => <Component />}
</BundleContainer>
<BundleContainer fetchComponent={UploadArea}>
{Component => <Component active={draggingOver} onClose={this.closeUploadModal} />}
</BundleContainer>
{me && (
<BundleContainer fetchComponent={SidebarMenu}>
{Component => <Component />}
</BundleContainer>
)}
{me && features.chats && !mobile && (
<BundleContainer fetchComponent={ChatPanes}>
{Component => <Component />}
</BundleContainer>
)}
<ProfileHoverCard />
<ThumbNavigation />
<BundleContainer fetchComponent={ProfileHoverCard}>
{Component => <Component />}
</BundleContainer>
</div>
</HotKeys>
);

@ -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');
}
@ -246,6 +290,74 @@ 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 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 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 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 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');
}
@ -282,6 +394,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');
}

@ -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);
};
}

@ -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 {
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
<AdminNav />
<BundleContainer fetchComponent={AdminNav}>
{Component => <Component />}
</BundleContainer>
</div>
</div>
@ -29,7 +34,9 @@ class AdminPage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<LatestAccountsPanel limit={5} />
<BundleContainer fetchComponent={LatestAccountsPanel}>
{Component => <Component limit={5} />}
</BundleContainer>
<LinkFooter />
</div>
</div>

@ -2,11 +2,14 @@ import React from 'react';
import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component';
import PrimaryNavigation from 'soapbox/components/primary_navigation';
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 FeaturesPanel from 'soapbox/features/ui/components/features_panel';
import SignUpPanel from 'soapbox/features/ui/components/sign_up_panel';
import BundleContainer from 'soapbox/features/ui/containers/bundle_container';
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';
@ -46,10 +49,28 @@ class DefaultPage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
{me ? <FeaturesPanel key='features-panel' /> : <SignUpPanel key='sign-up-panel' />}
{showTrendsPanel && <TrendsPanel limit={3} key='trends-panel' />}
{showWhoToFollowPanel && <WhoToFollowPanel limit={5} key='wtf-panel' />}
<PromoPanel key='promo-panel' />
{me ? (
<BundleContainer fetchComponent={FeaturesPanel}>
{Component => <Component key='features-panel' />}
</BundleContainer>
) : (
<BundleContainer fetchComponent={SignUpPanel}>
{Component => <Component key='sign-up-panel' />}
</BundleContainer>
)}
{showTrendsPanel && (
<BundleContainer fetchComponent={TrendsPanel}>
{Component => <Component key='trends-panel' />}
</BundleContainer>
)}
{showWhoToFollowPanel && (
<BundleContainer fetchComponent={WhoToFollowPanel}>
{Component => <Component limit={5} key='wtf-panel' />}
</BundleContainer>
)}
<BundleContainer fetchComponent={PromoPanel}>
{Component => <Component key='promo-panel' />}
</BundleContainer>
<LinkFooter key='link-footer' />
</div>
</div>

@ -5,16 +5,18 @@ 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 PrimaryNavigation from 'soapbox/components/primary_navigation';
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,
// 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';
@ -81,11 +83,33 @@ class HomePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
{me ? <FeaturesPanel key='features-panel' /> : <SignUpPanel key='sign-up-panel' />}
{showTrendsPanel && <TrendsPanel limit={3} key='trends-panel' />}
{showWhoToFollowPanel && <WhoToFollowPanel limit={5} key='wtf-panel' />}
<PromoPanel key='promo-panel' />
{showFundingPanel && <FundingPanel key='funding-panel' />}
{me ? (
<BundleContainer fetchComponent={FeaturesPanel}>
{Component => <Component key='features-panel' />}
</BundleContainer>
) : (
<BundleContainer fetchComponent={SignUpPanel}>
{Component => <Component key='sign-up-panel' />}
</BundleContainer>
)}
{showTrendsPanel && (
<BundleContainer fetchComponent={TrendsPanel}>
{Component => <Component key='trends-panel' />}
</BundleContainer>
)}
{showWhoToFollowPanel && (
<BundleContainer fetchComponent={WhoToFollowPanel}>
{Component => <Component limit={5} key='wtf-panel' />}
</BundleContainer>
)}
<BundleContainer fetchComponent={PromoPanel}>
{Component => <Component key='promo-panel' />}
</BundleContainer>
{showFundingPanel && (
<BundleContainer fetchComponent={FundingPanel}>
{Component => <Component key='funding-panel' />}
</BundleContainer>
)}
{showCryptoDonatePanel && (
<BundleContainer fetchComponent={CryptoDonatePanel}>
{Component => <Component limit={cryptoLimit} key='crypto-panel' />}

@ -5,11 +5,14 @@ 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,
SignUpPanel,
ProfileInfoPanel,
ProfileMediaPanel,
} 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';
import { displayFqn } from 'soapbox/utils/state';
import { getFeatures } from 'soapbox/utils/features';
@ -86,7 +89,9 @@ class ProfilePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
<ProfileInfoPanel username={accountUsername} account={account} />
<BundleContainer fetchComponent={ProfileInfoPanel}>
{Component => <Component username={accountUsername} account={account} />}
</BundleContainer>
</div>
</div>
@ -98,9 +103,19 @@ class ProfilePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<SignUpPanel />
{features.suggestions && <WhoToFollowPanel />}
{account && <ProfileMediaPanel account={account} />}
<BundleContainer fetchComponent={SignUpPanel}>
{Component => <Component />}
</BundleContainer>
{account && (
<BundleContainer fetchComponent={ProfileMediaPanel}>
{Component => <Component account={account} />}
</BundleContainer>
)}
{features.suggestions && (
<BundleContainer fetchComponent={WhoToFollowPanel}>
{Component => <Component />}
</BundleContainer>
)}
<LinkFooter />
</div>
</div>

@ -1,11 +1,14 @@
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,
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';
@ -33,8 +36,14 @@ class RemoteInstancePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
<InstanceInfoPanel host={host} />
{(disclosed || isAdmin) && <InstanceModerationPanel host={host} />}
<BundleContainer fetchComponent={InstanceInfoPanel}>
{Component => <Component host={host} />}
</BundleContainer>
{(disclosed || isAdmin) && (
<BundleContainer fetchComponent={InstanceModerationPanel}>
{Component => <Component host={host} />}
</BundleContainer>
)}
</div>
</div>
@ -46,8 +55,14 @@ class RemoteInstancePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
{me && <FeaturesPanel key='features-panel' />}
<PromoPanel key='promo-panel' />
{me && (
<BundleContainer fetchComponent={FeaturesPanel}>
{Component => <Component key='features-panel' />}
</BundleContainer>
)}
<BundleContainer fetchComponent={PromoPanel}>
{Component => <Component key='promo-panel' />}
</BundleContainer>
<LinkFooter key='link-footer' />
</div>
</div>

@ -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,

@ -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));

@ -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);

@ -279,10 +279,6 @@
object-fit: contain;
}
.loading-bar {
position: relative;
}
&.image-loader--amorphous .image-loader__preview-canvas {
display: none;
}

@ -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:

@ -126,7 +126,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",

@ -7897,14 +7897,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"

Loading…
Cancel
Save