Make right sidebar available on most pages

This commit is contained in:
Alex Gleason 2021-06-16 13:34:54 -05:00
parent 26421e6f42
commit 5ca4d4c3d7
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
4 changed files with 69 additions and 110 deletions

View file

@ -27,10 +27,15 @@ import TabsBar from './components/tabs_bar';
import LinkFooter from './components/link_footer'; import LinkFooter from './components/link_footer';
import FeaturesPanel from './components/features_panel'; import FeaturesPanel from './components/features_panel';
import ProfilePage from 'soapbox/pages/profile_page'; import ProfilePage from 'soapbox/pages/profile_page';
import UserPanel from './components/user_panel';
import WhoToFollowPanel from './components/who_to_follow_panel';
import TrendsPanel from './components/trends_panel';
import PromoPanel from './components/promo_panel';
import FundingPanel from './components/funding_panel';
import CryptoDonatePanel from 'soapbox/features/crypto_donate/components/crypto_donate_panel';
// import GroupsPage from 'soapbox/pages/groups_page'; // import GroupsPage from 'soapbox/pages/groups_page';
// import GroupPage from 'soapbox/pages/group_page'; // import GroupPage from 'soapbox/pages/group_page';
// import GroupSidebarPanel from '../groups/sidebar_panel'; // import GroupSidebarPanel from '../groups/sidebar_panel';
import SearchPage from 'soapbox/pages/search_page';
import HomePage from 'soapbox/pages/home_page'; import HomePage from 'soapbox/pages/home_page';
import AdminPage from 'soapbox/pages/admin_page'; import AdminPage from 'soapbox/pages/admin_page';
import SidebarMenu from '../../components/sidebar_menu'; import SidebarMenu from '../../components/sidebar_menu';
@ -41,6 +46,8 @@ import { isStaff } from 'soapbox/utils/accounts';
import ChatPanes from 'soapbox/features/chats/components/chat_panes'; import ChatPanes from 'soapbox/features/chats/components/chat_panes';
import ProfileHoverCard from 'soapbox/components/profile_hover_card'; import ProfileHoverCard from 'soapbox/components/profile_hover_card';
import { getAccessToken } from 'soapbox/utils/auth'; import { getAccessToken } from 'soapbox/utils/auth';
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
import { getFeatures } from 'soapbox/utils/features';
import { import {
Status, Status,
@ -101,6 +108,43 @@ import '../../components/status';
const isMobile = width => width <= 1190; const isMobile = width => width <= 1190;
const makeLayouts = state => {
const me = state.get('me');
const soapbox = getSoapboxConfig(state);
const hasPatron = soapbox.getIn(['extensions', 'patron', 'enabled']);
const hasCrypto = typeof soapbox.getIn(['cryptoAddresses', 0, 'ticker']) === 'string';
const cryptoLimit = soapbox.getIn(['cryptoDonatePanel', 'limit']);
const features = getFeatures(state.get('instance'));
const EMPTY = {
LEFT: null,
RIGHT: null,
};
const DEFAULT = {
LEFT: EMPTY.LEFT,
RIGHT: [
features.trends && <TrendsPanel limit={3} key='trends-panel' />,
features.suggestions && <WhoToFollowPanel limit={5} key='wtf-panel' />,
<FeaturesPanel key='features-panel' />,
<PromoPanel key='promo-panel' />,
<LinkFooter key='link-footer' />,
],
};
const HOME = {
LEFT: [
<UserPanel accountId={me} key='user-panel' />,
hasPatron && <FundingPanel key='funding-panel' />,
hasCrypto && <CryptoDonatePanel limit={cryptoLimit} key='crypto-panel' />,
],
RIGHT: DEFAULT.RIGHT,
};
return { EMPTY, DEFAULT, HOME };
};
const messages = defineMessages({ const messages = defineMessages({
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave.' }, beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave.' },
publish: { id: 'compose_form.publish', defaultMessage: 'Publish' }, publish: { id: 'compose_form.publish', defaultMessage: 'Publish' },
@ -119,6 +163,7 @@ const mapStateToProps = state => {
streamingUrl: state.getIn(['instance', 'urls', 'streaming_api']), streamingUrl: state.getIn(['instance', 'urls', 'streaming_api']),
me, me,
account, account,
layouts: makeLayouts(state),
}; };
}; };
@ -150,33 +195,13 @@ const keyMap = {
toggleSensitive: 'h', toggleSensitive: 'h',
}; };
const LAYOUT = {
EMPTY: {
LEFT: null,
RIGHT: null,
},
DEFAULT: {
LEFT: null,
RIGHT: [
<FeaturesPanel key='0' />,
<LinkFooter key='1' />,
],
},
STATUS: {
TOP: null,
LEFT: null,
RIGHT: [
<LinkFooter key='2' />,
],
},
};
class SwitchingColumnsArea extends React.PureComponent { class SwitchingColumnsArea extends React.PureComponent {
static propTypes = { static propTypes = {
children: PropTypes.node, children: PropTypes.node,
location: PropTypes.object, location: PropTypes.object,
onLayoutChange: PropTypes.func.isRequired, onLayoutChange: PropTypes.func.isRequired,
layouts: PropTypes.object.isRequired,
}; };
state = { state = {
@ -205,7 +230,7 @@ class SwitchingColumnsArea extends React.PureComponent {
} }
render() { render() {
const { children } = this.props; const { children, layouts: LAYOUT } = this.props;
return ( return (
<Switch> <Switch>
@ -214,10 +239,10 @@ class SwitchingColumnsArea extends React.PureComponent {
<WrappedRoute path='/auth/edit' layout={LAYOUT.DEFAULT} component={SecurityForm} exact /> <WrappedRoute path='/auth/edit' layout={LAYOUT.DEFAULT} component={SecurityForm} exact />
<WrappedRoute path='/auth/mfa' layout={LAYOUT.DEFAULT} component={MfaForm} exact /> <WrappedRoute path='/auth/mfa' layout={LAYOUT.DEFAULT} component={MfaForm} exact />
<WrappedRoute path='/' exact page={HomePage} component={HomeTimeline} content={children} /> <WrappedRoute path='/' exact page={HomePage} layout={LAYOUT.HOME} component={HomeTimeline} content={children} />
<WrappedRoute path='/timeline/local' exact page={HomePage} component={CommunityTimeline} content={children} publicRoute /> <WrappedRoute path='/timeline/local' exact page={HomePage} layout={LAYOUT.HOME} component={CommunityTimeline} content={children} publicRoute />
<WrappedRoute path='/timeline/fediverse' exact page={HomePage} component={PublicTimeline} content={children} publicRoute /> <WrappedRoute path='/timeline/fediverse' exact page={HomePage} layout={LAYOUT.HOME} component={PublicTimeline} content={children} publicRoute />
<WrappedRoute path='/timeline/:instance' exact page={HomePage} component={RemoteTimeline} content={children} /> <WrappedRoute path='/timeline/:instance' exact page={HomePage} layout={LAYOUT.HOME} component={RemoteTimeline} content={children} />
<WrappedRoute path='/messages' layout={LAYOUT.DEFAULT} component={DirectTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} /> <WrappedRoute path='/messages' layout={LAYOUT.DEFAULT} component={DirectTimeline} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
{/* {/*
@ -237,7 +262,7 @@ class SwitchingColumnsArea extends React.PureComponent {
<Redirect from='/main/friends' to='/' /> <Redirect from='/main/friends' to='/' />
<Redirect from='/tag/:id' to='/tags/:id' /> <Redirect from='/tag/:id' to='/tags/:id' />
<Redirect from='/user-settings' to='/settings/profile' /> <Redirect from='/user-settings' to='/settings/profile' />
<WrappedRoute path='/notice/:statusId' publicRoute exact layout={LAYOUT.STATUS} component={Status} content={children} /> <WrappedRoute path='/notice/:statusId' publicRoute exact layout={LAYOUT.DEFAULT} component={Status} content={children} />
<Redirect from='/users/:username' to='/@:username' /> <Redirect from='/users/:username' to='/@:username' />
<Redirect from='/home' to='/' /> <Redirect from='/home' to='/' />
@ -248,12 +273,12 @@ class SwitchingColumnsArea extends React.PureComponent {
<WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} /> <WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} />
<WrappedRoute path='/lists' layout={LAYOUT.DEFAULT} component={Lists} content={children} /> <WrappedRoute path='/lists' layout={LAYOUT.DEFAULT} component={Lists} content={children} />
<WrappedRoute path='/list/:id' page={HomePage} component={ListTimeline} content={children} /> <WrappedRoute path='/list/:id' page={HomePage} layout={LAYOUT.DEFAULT} component={ListTimeline} content={children} />
<WrappedRoute path='/bookmarks' layout={LAYOUT.DEFAULT} component={Bookmarks} content={children} /> <WrappedRoute path='/bookmarks' layout={LAYOUT.DEFAULT} component={Bookmarks} content={children} />
<WrappedRoute path='/notifications' layout={LAYOUT.DEFAULT} component={Notifications} content={children} /> <WrappedRoute path='/notifications' layout={LAYOUT.DEFAULT} component={Notifications} content={children} />
<WrappedRoute path='/search' publicRoute page={SearchPage} component={Search} content={children} /> <WrappedRoute path='/search' publicRoute layout={LAYOUT.DEFAULT} component={Search} content={children} />
<WrappedRoute path='/chats' exact layout={LAYOUT.DEFAULT} component={ChatIndex} content={children} /> <WrappedRoute path='/chats' exact layout={LAYOUT.DEFAULT} component={ChatIndex} content={children} />
<WrappedRoute path='/chats/:chatId' layout={LAYOUT.DEFAULT} component={ChatRoom} content={children} /> <WrappedRoute path='/chats/:chatId' layout={LAYOUT.DEFAULT} component={ChatRoom} content={children} />
@ -271,8 +296,8 @@ class SwitchingColumnsArea extends React.PureComponent {
<WrappedRoute path='/@:username/tagged/:tag' exact component={AccountTimeline} page={ProfilePage} content={children} /> <WrappedRoute path='/@:username/tagged/:tag' exact component={AccountTimeline} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} /> <WrappedRoute path='/@:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} /> <WrappedRoute path='/@:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
<WrappedRoute path='/@:username/posts/:statusId' publicRoute exact layout={LAYOUT.STATUS} component={Status} content={children} /> <WrappedRoute path='/@:username/posts/:statusId' publicRoute exact layout={LAYOUT.DEFAULT} component={Status} content={children} />
<WrappedRoute path='/@:username/posts/:statusId/reblogs' layout={LAYOUT.STATUS} component={Reblogs} content={children} /> <WrappedRoute path='/@:username/posts/:statusId/reblogs' layout={LAYOUT.DEFAULT} component={Reblogs} content={children} />
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} /> <WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} componentParams={{ shouldUpdateScroll: this.shouldUpdateScroll }} />
@ -320,6 +345,7 @@ class UI extends React.PureComponent {
me: SoapboxPropTypes.me, me: SoapboxPropTypes.me,
streamingUrl: PropTypes.string, streamingUrl: PropTypes.string,
account: PropTypes.object, account: PropTypes.object,
layouts: PropTypes.object.isRequired,
}; };
state = { state = {
@ -625,7 +651,7 @@ class UI extends React.PureComponent {
render() { render() {
const { streamingUrl } = this.props; const { streamingUrl } = this.props;
const { draggingOver, mobile } = this.state; const { draggingOver, mobile } = this.state;
const { intl, children, isComposing, location, dropdownMenuIsOpen, me } = this.props; const { intl, children, isComposing, location, dropdownMenuIsOpen, me, layouts } = this.props;
if (me === null || !streamingUrl) return null; if (me === null || !streamingUrl) return null;
@ -673,7 +699,7 @@ class UI extends React.PureComponent {
<HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused> <HotKeys keyMap={keyMap} handlers={handlers} ref={this.setHotkeysRef} attach={window} focused>
<div className={classnames} ref={this.setRef} style={style}> <div className={classnames} ref={this.setRef} style={style}>
<TabsBar /> <TabsBar />
<SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange}> <SwitchingColumnsArea location={location} onLayoutChange={this.handleLayoutChange} layouts={layouts}>
{children} {children}
</SwitchingColumnsArea> </SwitchingColumnsArea>

View file

@ -38,7 +38,7 @@ class WrappedRoute extends React.Component {
<BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}> <BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}>
{Component => {Component =>
( (
<Page params={match.params} {...componentParams}> <Page params={match.params} layout={layout} {...componentParams}>
<Component params={match.params} {...componentParams}> <Component params={match.params} {...componentParams}>
{content} {content}
</Component> </Component>

View file

@ -1,30 +1,15 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
import TrendsPanel from '../features/ui/components/trends_panel';
import LinkFooter from '../features/ui/components/link_footer';
import FeaturesPanel from '../features/ui/components/features_panel';
import PromoPanel from '../features/ui/components/promo_panel';
import UserPanel from '../features/ui/components/user_panel';
import FundingPanel from '../features/ui/components/funding_panel';
import CryptoDonatePanel from 'soapbox/features/crypto_donate/components/crypto_donate_panel';
import ComposeFormContainer from '../features/compose/containers/compose_form_container'; import ComposeFormContainer from '../features/compose/containers/compose_form_container';
import Avatar from '../components/avatar'; import Avatar from '../components/avatar';
import { getFeatures } from 'soapbox/utils/features';
// import GroupSidebarPanel from '../features/groups/sidebar_panel'; // import GroupSidebarPanel from '../features/groups/sidebar_panel';
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
const mapStateToProps = state => { const mapStateToProps = state => {
const me = state.get('me'); const me = state.get('me');
const soapbox = getSoapboxConfig(state);
return { return {
me, me,
account: state.getIn(['accounts', me]), account: state.getIn(['accounts', me]),
hasPatron: soapbox.getIn(['extensions', 'patron', 'enabled']),
hasCrypto: typeof soapbox.getIn(['cryptoAddresses', 0, 'ticker']) === 'string',
cryptoLimit: soapbox.getIn(['cryptoDonatePanel', 'limit']),
features: getFeatures(state.get('instance')),
}; };
}; };
@ -36,8 +21,13 @@ class HomePage extends ImmutablePureComponent {
this.composeBlock = React.createRef(); this.composeBlock = React.createRef();
} }
static defaultProps = {
layout: { LEFT: null, RIGHT: null },
}
render() { render() {
const { me, children, account, hasPatron, features, hasCrypto, cryptoLimit } = this.props; const { me, children, account } = this.props;
const LAYOUT = this.props.layout || this.defaultProps.layout;
return ( return (
<div className='page'> <div className='page'>
@ -46,9 +36,7 @@ class HomePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--left'> <div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'> <div className='columns-area__panels__pane__inner'>
<UserPanel accountId={me} /> {LAYOUT.LEFT}
{hasPatron && <FundingPanel />}
{hasCrypto && <CryptoDonatePanel limit={cryptoLimit} />}
</div> </div>
</div> </div>
@ -71,12 +59,7 @@ class HomePage extends ImmutablePureComponent {
<div className='columns-area__panels__pane columns-area__panels__pane--right'> <div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'> <div className='columns-area__panels__pane__inner'>
{/* <GroupSidebarPanel /> */} {LAYOUT.RIGHT}
{features.trends && <TrendsPanel limit={3} />}
{features.suggestions && <WhoToFollowPanel limit={5} />}
<FeaturesPanel />
<PromoPanel />
<LinkFooter />
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,50 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Header from '../features/search/components/header';
import WhoToFollowPanel from '../features/ui/components/who_to_follow_panel';
import LinkFooter from '../features/ui/components/link_footer';
import SignUpPanel from '../features/ui/components/sign_up_panel';
import { getFeatures } from 'soapbox/utils/features';
const mapStateToProps = state => ({
features: getFeatures(state.get('instance')),
});
const SearchPage = ({ children, features }) => (
<div className='page'>
<div className='page__top'>
<Header />
</div>
<div className='page__columns'>
<div className='columns-area__panels'>
<div className='columns-area__panels__pane columns-area__panels__pane--left'>
<div className='columns-area__panels__pane__inner'>
<LinkFooter />
</div>
</div>
<div className='columns-area__panels__main'>
<div className='columns-area columns-area--mobile'>
{children}
</div>
</div>
<div className='columns-area__panels__pane columns-area__panels__pane--right'>
<div className='columns-area__panels__pane__inner'>
<SignUpPanel />
{features.suggestions && <WhoToFollowPanel />}
</div>
</div>
</div>
</div>
</div>
);
SearchPage.propTypes = {
children: PropTypes.node,
features: PropTypes.object,
};
export default connect(mapStateToProps)(SearchPage);