Merge remote-tracking branch 'origin/develop' into next
This commit is contained in:
commit
008d53a7d9
25 changed files with 370 additions and 207 deletions
|
@ -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…
Reference in a new issue