[Glitch] Change public accounts pages to mount the web UI

Port 839f893168 to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
master
Eugen Rochko 2022-10-20 14:35:29 +02:00 committed by Claire
parent 6013eeea4c
commit 9363e5c24e
47 changed files with 164 additions and 1104 deletions

View File

@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl';
import { source_url } from 'flavours/glitch/initial_state'; import { source_url } from 'flavours/glitch/initial_state';
import { preferencesLink } from 'flavours/glitch/utils/backend_links'; import { preferencesLink } from 'flavours/glitch/utils/backend_links';
import StackTrace from 'stacktrace-js'; import StackTrace from 'stacktrace-js';
import { Helmet } from 'react-helmet';
export default class ErrorBoundary extends React.PureComponent { export default class ErrorBoundary extends React.PureComponent {
@ -122,6 +123,10 @@ export default class ErrorBoundary extends React.PureComponent {
)} )}
</ul> </ul>
</div> </div>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</div> </div>
); );
} }

View File

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import illustration from 'flavours/glitch/images/elephant_ui_disappointed.svg'; import illustration from 'flavours/glitch/images/elephant_ui_disappointed.svg';
import classNames from 'classnames'; import classNames from 'classnames';
import { Helmet } from 'react-helmet';
const MissingIndicator = ({ fullPage }) => ( const MissingIndicator = ({ fullPage }) => (
<div className={classNames('regeneration-indicator', { 'regeneration-indicator--without-header': fullPage })}> <div className={classNames('regeneration-indicator', { 'regeneration-indicator--without-header': fullPage })}>
@ -14,6 +15,10 @@ const MissingIndicator = ({ fullPage }) => (
<FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' /> <FormattedMessage id='missing_indicator.label' tagName='strong' defaultMessage='Not found' />
<FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' /> <FormattedMessage id='missing_indicator.sublabel' defaultMessage='This resource could not be found' />
</div> </div>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</div> </div>
); );

View File

@ -83,7 +83,7 @@ export default class Mastodon extends React.PureComponent {
<IntlProvider locale={locale} messages={messages}> <IntlProvider locale={locale} messages={messages}>
<ReduxProvider store={store}> <ReduxProvider store={store}>
<ErrorBoundary> <ErrorBoundary>
<BrowserRouter basename='/web'> <BrowserRouter>
<ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}> <ScrollContext shouldUpdateScroll={this.shouldUpdateScroll}>
<Route path='/' component={UI} /> <Route path='/' component={UI} />
</ScrollContext> </ScrollContext>

View File

@ -94,6 +94,7 @@ class About extends React.PureComponent {
}), }),
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
multiColumn: PropTypes.bool,
}; };
componentDidMount () { componentDidMount () {
@ -108,11 +109,11 @@ class About extends React.PureComponent {
} }
render () { render () {
const { intl, server, extendedDescription, domainBlocks } = this.props; const { multiColumn, intl, server, extendedDescription, domainBlocks } = this.props;
const isLoading = server.get('isLoading'); const isLoading = server.get('isLoading');
return ( return (
<Column> <Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
<div className='scrollable about'> <div className='scrollable about'>
<div className='about__header'> <div className='about__header'>
<Image blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' /> <Image blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
@ -212,6 +213,7 @@ class About extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='all' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -273,7 +273,9 @@ class Header extends ImmutablePureComponent {
const content = { __html: account.get('note_emojified') }; const content = { __html: account.get('note_emojified') };
const displayNameHtml = { __html: account.get('display_name_html') }; const displayNameHtml = { __html: account.get('display_name_html') };
const fields = account.get('fields'); const fields = account.get('fields');
const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct'); const isLocal = account.get('acct').indexOf('@') === -1;
const acct = isLocal && domain ? `${account.get('acct')}@${domain}` : account.get('acct');
const isIndexable = !account.get('noindex');
let badge; let badge;
@ -353,6 +355,7 @@ class Header extends ImmutablePureComponent {
<Helmet> <Helmet>
<title>{titleFromAccount(account)}</title> <title>{titleFromAccount(account)}</title>
<meta name='robots' content={(isLocal && isIndexable) ? 'all' : 'noindex'} />
</Helmet> </Helmet>
</div> </div>
); );

View File

@ -136,7 +136,13 @@ class AccountTimeline extends ImmutablePureComponent {
render () { render () {
const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props;
if (!isAccount) { if (isLoading && statusIds.isEmpty()) {
return (
<Column>
<LoadingIndicator />
</Column>
);
} else if (!isLoading && !isAccount) {
return ( return (
<Column> <Column>
<ColumnBackButton multiColumn={multiColumn} /> <ColumnBackButton multiColumn={multiColumn} />
@ -145,14 +151,6 @@ class AccountTimeline extends ImmutablePureComponent {
); );
} }
if (!statusIds && isLoading) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
let emptyMessage; let emptyMessage;
const forceEmptyState = suspended || hidden; const forceEmptyState = suspended || hidden;

View File

@ -99,6 +99,7 @@ class Bookmarks extends ImmutablePureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.heading)}</title> <title>{intl.formatMessage(messages.heading)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -155,6 +155,7 @@ class CommunityTimeline extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -15,6 +15,7 @@ import { me, mascot } from 'flavours/glitch/initial_state';
import { cycleElefriendCompose } from 'flavours/glitch/actions/compose'; import { cycleElefriendCompose } from 'flavours/glitch/actions/compose';
import HeaderContainer from './containers/header_container'; import HeaderContainer from './containers/header_container';
import Column from 'flavours/glitch/components/column'; import Column from 'flavours/glitch/components/column';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new post' }, compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new post' },
@ -114,6 +115,10 @@ class Compose extends React.PureComponent {
<Column> <Column>
<NavigationContainer /> <NavigationContainer />
<ComposeFormContainer /> <ComposeFormContainer />
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -147,6 +147,7 @@ class DirectTimeline extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -169,6 +169,7 @@ class Directory extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -11,6 +11,7 @@ import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_bloc
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import ScrollableList from 'flavours/glitch/components/scrollable_list'; import ScrollableList from 'flavours/glitch/components/scrollable_list';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' }, heading: { id: 'column.domain_blocks', defaultMessage: 'Blocked domains' },
@ -59,6 +60,7 @@ class Blocks extends ImmutablePureComponent {
return ( return (
<Column bindToDocument={!multiColumn} icon='minus-circle' heading={intl.formatMessage(messages.heading)}> <Column bindToDocument={!multiColumn} icon='minus-circle' heading={intl.formatMessage(messages.heading)}>
<ColumnBackButtonSlim /> <ColumnBackButtonSlim />
<ScrollableList <ScrollableList
scrollKey='domain_blocks' scrollKey='domain_blocks'
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
@ -70,6 +72,10 @@ class Blocks extends ImmutablePureComponent {
<DomainContainer key={domain} domain={domain} />, <DomainContainer key={domain} domain={domain} />,
)} )}
</ScrollableList> </ScrollableList>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -85,6 +85,7 @@ class Explore extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content={isSearching ? 'noindex' : 'all'} />
</Helmet> </Helmet>
</React.Fragment> </React.Fragment>
)} )}

View File

@ -99,6 +99,7 @@ class Favourites extends ImmutablePureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.heading)}</title> <title>{intl.formatMessage(messages.heading)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -11,6 +11,7 @@ import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
import ScrollableList from 'flavours/glitch/components/scrollable_list'; import ScrollableList from 'flavours/glitch/components/scrollable_list';
import AccountContainer from 'flavours/glitch/containers/account_container'; import AccountContainer from 'flavours/glitch/containers/account_container';
import Column from 'flavours/glitch/features/ui/components/column'; import Column from 'flavours/glitch/features/ui/components/column';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'column.favourited_by', defaultMessage: 'Favourited by' }, heading: { id: 'column.favourited_by', defaultMessage: 'Favourited by' },
@ -91,6 +92,10 @@ class Favourites extends ImmutablePureComponent {
<AccountContainer key={id} id={id} withNote={false} />, <AccountContainer key={id} id={id} withNote={false} />,
)} )}
</ScrollableList> </ScrollableList>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -12,6 +12,7 @@ import Column from 'flavours/glitch/features/ui/components/column';
import Account from './components/account'; import Account from './components/account';
import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg'; import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg';
import Button from 'flavours/glitch/components/button'; import Button from 'flavours/glitch/components/button';
import { Helmet } from 'react-helmet';
const mapStateToProps = state => ({ const mapStateToProps = state => ({
suggestions: state.getIn(['suggestions', 'items']), suggestions: state.getIn(['suggestions', 'items']),
@ -104,6 +105,10 @@ class FollowRecommendations extends ImmutablePureComponent {
</React.Fragment> </React.Fragment>
)} )}
</div> </div>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -12,6 +12,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import ScrollableList from 'flavours/glitch/components/scrollable_list'; import ScrollableList from 'flavours/glitch/components/scrollable_list';
import { me } from 'flavours/glitch/initial_state'; import { me } from 'flavours/glitch/initial_state';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' }, heading: { id: 'column.follow_requests', defaultMessage: 'Follow requests' },
@ -88,6 +89,10 @@ class FollowRequests extends ImmutablePureComponent {
<AccountAuthorizeContainer key={id} id={id} />, <AccountAuthorizeContainer key={id} id={id} />,
)} )}
</ScrollableList> </ScrollableList>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -194,6 +194,7 @@ const NAVIGATION_PANEL_BREAKPOINT = 600 + (285 * 2) + (10 * 2);
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.menu)}</title> <title>{intl.formatMessage(messages.menu)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -228,6 +228,7 @@ class HashtagTimeline extends React.PureComponent {
<Helmet> <Helmet>
<title>#{id}</title> <title>#{id}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -20,7 +20,7 @@ const messages = defineMessages({
title: { id: 'column.home', defaultMessage: 'Home' }, title: { id: 'column.home', defaultMessage: 'Home' },
show_announcements: { id: 'home.show_announcements', defaultMessage: 'Show announcements' }, show_announcements: { id: 'home.show_announcements', defaultMessage: 'Show announcements' },
hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' }, hide_announcements: { id: 'home.hide_announcements', defaultMessage: 'Hide announcements' },
}); });
const mapStateToProps = state => ({ const mapStateToProps = state => ({
hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0, hasUnread: state.getIn(['timelines', 'home', 'unread']) > 0,
@ -170,6 +170,7 @@ class HomeTimeline extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -5,6 +5,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import ColumnHeader from 'flavours/glitch/components/column_header'; import ColumnHeader from 'flavours/glitch/components/column_header';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' }, heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
@ -137,6 +138,10 @@ class KeyboardShortcuts extends ImmutablePureComponent {
</tbody> </tbody>
</table> </table>
</div> </div>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -215,6 +215,7 @@ class ListTimeline extends React.PureComponent {
<Helmet> <Helmet>
<title>{title}</title> <title>{title}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -80,6 +80,7 @@ class Lists extends ImmutablePureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.heading)}</title> <title>{intl.formatMessage(messages.heading)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -11,6 +11,7 @@ import AccountContainer from 'flavours/glitch/containers/account_container';
import { fetchMutes, expandMutes } from 'flavours/glitch/actions/mutes'; import { fetchMutes, expandMutes } from 'flavours/glitch/actions/mutes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import ScrollableList from 'flavours/glitch/components/scrollable_list'; import ScrollableList from 'flavours/glitch/components/scrollable_list';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'column.mutes', defaultMessage: 'Muted users' }, heading: { id: 'column.mutes', defaultMessage: 'Muted users' },
@ -72,6 +73,10 @@ class Mutes extends ImmutablePureComponent {
<AccountContainer key={id} id={id} defaultAction='mute' />, <AccountContainer key={id} id={id} defaultAction='mute' />,
)} )}
</ScrollableList> </ScrollableList>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -373,6 +373,7 @@ class Notifications extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -8,6 +8,7 @@ import ColumnBackButtonSlim from 'flavours/glitch/components/column_back_button_
import StatusList from 'flavours/glitch/components/status_list'; import StatusList from 'flavours/glitch/components/status_list';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'column.pins', defaultMessage: 'Pinned post' }, heading: { id: 'column.pins', defaultMessage: 'Pinned post' },
@ -54,6 +55,9 @@ class PinnedStatuses extends ImmutablePureComponent {
hasMore={hasMore} hasMore={hasMore}
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
/> />
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -15,6 +15,7 @@ class PrivacyPolicy extends React.PureComponent {
static propTypes = { static propTypes = {
intl: PropTypes.object, intl: PropTypes.object,
multiColumn: PropTypes.bool,
}; };
state = { state = {
@ -32,11 +33,11 @@ class PrivacyPolicy extends React.PureComponent {
} }
render () { render () {
const { intl } = this.props; const { intl, multiColumn } = this.props;
const { isLoading, content, lastUpdated } = this.state; const { isLoading, content, lastUpdated } = this.state;
return ( return (
<Column> <Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
<div className='scrollable privacy-policy'> <div className='scrollable privacy-policy'>
<div className='column-title'> <div className='column-title'>
<h3><FormattedMessage id='privacy_policy.title' defaultMessage='Privacy Policy' /></h3> <h3><FormattedMessage id='privacy_policy.title' defaultMessage='Privacy Policy' /></h3>
@ -51,6 +52,7 @@ class PrivacyPolicy extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='all' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -159,6 +159,7 @@ class PublicTimeline extends React.PureComponent {
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.title)}</title> <title>{intl.formatMessage(messages.title)}</title>
<meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -11,6 +11,7 @@ import ColumnHeader from 'flavours/glitch/components/column_header';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import ScrollableList from 'flavours/glitch/components/scrollable_list'; import ScrollableList from 'flavours/glitch/components/scrollable_list';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
heading: { id: 'column.reblogged_by', defaultMessage: 'Boosted by' }, heading: { id: 'column.reblogged_by', defaultMessage: 'Boosted by' },
@ -92,6 +93,10 @@ class Reblogs extends ImmutablePureComponent {
<AccountContainer key={id} id={id} withNote={false} />, <AccountContainer key={id} id={id} withNote={false} />,
)} )}
</ScrollableList> </ScrollableList>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -135,6 +135,7 @@ const makeMapStateToProps = () => {
} }
return { return {
isLoading: state.getIn(['statuses', props.params.statusId, 'isLoading']),
status, status,
ancestorsIds, ancestorsIds,
descendantsIds, descendantsIds,
@ -178,6 +179,7 @@ class Status extends ImmutablePureComponent {
params: PropTypes.object.isRequired, params: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
status: ImmutablePropTypes.map, status: ImmutablePropTypes.map,
isLoading: PropTypes.bool,
settings: ImmutablePropTypes.map.isRequired, settings: ImmutablePropTypes.map.isRequired,
ancestorsIds: ImmutablePropTypes.list, ancestorsIds: ImmutablePropTypes.list,
descendantsIds: ImmutablePropTypes.list, descendantsIds: ImmutablePropTypes.list,
@ -589,9 +591,17 @@ class Status extends ImmutablePureComponent {
render () { render () {
let ancestors, descendants; let ancestors, descendants;
const { status, settings, ancestorsIds, descendantsIds, intl, domain, multiColumn, usingPiP } = this.props; const { isLoading, status, settings, ancestorsIds, descendantsIds, intl, domain, multiColumn, usingPiP } = this.props;
const { fullscreen } = this.state; const { fullscreen } = this.state;
if (isLoading) {
return (
<Column>
<LoadingIndicator />
</Column>
);
}
if (status === null) { if (status === null) {
return ( return (
<Column> <Column>
@ -611,6 +621,9 @@ class Status extends ImmutablePureComponent {
descendants = <div>{this.renderChildren(descendantsIds)}</div>; descendants = <div>{this.renderChildren(descendantsIds)}</div>;
} }
const isLocal = status.getIn(['account', 'acct'], '').indexOf('@') === -1;
const isIndexable = !status.getIn(['account', 'noindex']);
const handlers = { const handlers = {
moveUp: this.handleHotkeyMoveUp, moveUp: this.handleHotkeyMoveUp,
moveDown: this.handleHotkeyMoveDown, moveDown: this.handleHotkeyMoveDown,
@ -685,6 +698,7 @@ class Status extends ImmutablePureComponent {
<Helmet> <Helmet>
<title>{titleFromStatus(status)}</title> <title>{titleFromStatus(status)}</title>
<meta name='robots' content={(isLocal && isIndexable) ? 'all' : 'noindex'} />
</Helmet> </Helmet>
</Column> </Column>
); );

View File

@ -2,10 +2,10 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import Column from './column'; import Column from 'flavours/glitch/components/column';
import ColumnHeader from './column_header'; import ColumnHeader from 'flavours/glitch/components/column_header';
import ColumnBackButtonSlim from 'flavours/glitch/components/column_back_button_slim';
import IconButton from 'flavours/glitch/components/icon_button'; import IconButton from 'flavours/glitch/components/icon_button';
import { Helmet } from 'react-helmet';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' }, title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
@ -18,6 +18,7 @@ class BundleColumnError extends React.Component {
static propTypes = { static propTypes = {
onRetry: PropTypes.func.isRequired, onRetry: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
multiColumn: PropTypes.bool,
} }
handleRetry = () => { handleRetry = () => {
@ -25,16 +26,25 @@ class BundleColumnError extends React.Component {
} }
render () { render () {
const { intl: { formatMessage } } = this.props; const { multiColumn, intl: { formatMessage } } = this.props;
return ( return (
<Column> <Column bindToDocument={!multiColumn} label={formatMessage(messages.title)}>
<ColumnHeader icon='exclamation-circle' type={formatMessage(messages.title)} /> <ColumnHeader
<ColumnBackButtonSlim /> icon='exclamation-circle'
title={formatMessage(messages.title)}
showBackButton
multiColumn={multiColumn}
/>
<div className='error-column'> <div className='error-column'>
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} /> <IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
{formatMessage(messages.body)} {formatMessage(messages.body)}
</div> </div>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</Column> </Column>
); );
} }

View File

@ -10,6 +10,7 @@ export default class ColumnLoading extends ImmutablePureComponent {
static propTypes = { static propTypes = {
title: PropTypes.oneOfType([PropTypes.node, PropTypes.string]), title: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
icon: PropTypes.string, icon: PropTypes.string,
multiColumn: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
@ -18,10 +19,11 @@ export default class ColumnLoading extends ImmutablePureComponent {
}; };
render() { render() {
let { title, icon } = this.props; let { title, icon, multiColumn } = this.props;
return ( return (
<Column> <Column>
<ColumnHeader icon={icon} title={title} multiColumn={false} focusable={false} placeholder /> <ColumnHeader icon={icon} title={title} multiColumn={multiColumn} focusable={false} placeholder />
<div className='scrollable' /> <div className='scrollable' />
</Column> </Column>
); );

View File

@ -140,11 +140,11 @@ class ColumnsArea extends ImmutablePureComponent {
} }
renderLoading = columnId => () => { renderLoading = columnId => () => {
return columnId === 'COMPOSE' ? <DrawerLoading /> : <ColumnLoading />; return columnId === 'COMPOSE' ? <DrawerLoading /> : <ColumnLoading multiColumn />;
} }
renderError = (props) => { renderError = (props) => {
return <BundleColumnError {...props} />; return <BundleColumnError multiColumn {...props} />;
} }
render () { render () {

View File

@ -13,10 +13,8 @@ import FavouriteModal from './favourite_modal';
import AudioModal from './audio_modal'; import AudioModal from './audio_modal';
import DoodleModal from './doodle_modal'; import DoodleModal from './doodle_modal';
import ConfirmationModal from './confirmation_modal'; import ConfirmationModal from './confirmation_modal';
import SubscribedLanguagesModal from 'flavours/glitch/features/subscribed_languages_modal';
import FocalPointModal from './focal_point_modal'; import FocalPointModal from './focal_point_modal';
import DeprecatedSettingsModal from './deprecated_settings_modal'; import DeprecatedSettingsModal from './deprecated_settings_modal';
import InteractionModal from 'flavours/glitch/features/interaction_modal';
import { import {
OnboardingModal, OnboardingModal,
MuteModal, MuteModal,
@ -29,7 +27,10 @@ import {
PinnedAccountsEditor, PinnedAccountsEditor,
CompareHistoryModal, CompareHistoryModal,
FilterModal, FilterModal,
InteractionModal,
SubscribedLanguagesModal,
} from 'flavours/glitch/features/ui/util/async-components'; } from 'flavours/glitch/features/ui/util/async-components';
import { Helmet } from 'react-helmet';
const MODAL_COMPONENTS = { const MODAL_COMPONENTS = {
'MEDIA': () => Promise.resolve({ default: MediaModal }), 'MEDIA': () => Promise.resolve({ default: MediaModal }),
@ -53,8 +54,8 @@ const MODAL_COMPONENTS = {
'PINNED_ACCOUNTS_EDITOR': PinnedAccountsEditor, 'PINNED_ACCOUNTS_EDITOR': PinnedAccountsEditor,
'COMPARE_HISTORY': CompareHistoryModal, 'COMPARE_HISTORY': CompareHistoryModal,
'FILTER': FilterModal, 'FILTER': FilterModal,
'SUBSCRIBED_LANGUAGES': () => Promise.resolve({ default: SubscribedLanguagesModal }), 'SUBSCRIBED_LANGUAGES': SubscribedLanguagesModal,
'INTERACTION': () => Promise.resolve({ default: InteractionModal }), 'INTERACTION': InteractionModal,
}; };
export default class ModalRoot extends React.PureComponent { export default class ModalRoot extends React.PureComponent {
@ -119,9 +120,15 @@ export default class ModalRoot extends React.PureComponent {
return ( return (
<Base backgroundColor={backgroundColor} onClose={this.handleClose} noEsc={props ? props.noEsc : false} ignoreFocus={ignoreFocus}> <Base backgroundColor={backgroundColor} onClose={this.handleClose} noEsc={props ? props.noEsc : false} ignoreFocus={ignoreFocus}>
{visible && ( {visible && (
<BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}> <>
{(SpecificComponent) => <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={this.setModalRef} />} <BundleContainer fetchComponent={MODAL_COMPONENTS[type]} loading={this.renderLoading(type)} error={this.renderError} renderDelay={200}>
</BundleContainer> {(SpecificComponent) => <SpecificComponent {...props} onChangeBackgroundColor={this.setBackgroundColor} onClose={this.handleClose} ref={this.setModalRef} />}
</BundleContainer>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</>
)} )}
</Base> </Base>
); );

View File

@ -210,8 +210,8 @@ class SwitchingColumnsArea extends React.PureComponent {
<WrappedRoute path={['/@:acct', '/accounts/:id']} exact component={AccountTimeline} content={children} /> <WrappedRoute path={['/@:acct', '/accounts/:id']} exact component={AccountTimeline} content={children} />
<WrappedRoute path={['/@:acct/with_replies', '/accounts/:id/with_replies']} component={AccountTimeline} content={children} componentParams={{ withReplies: true }} /> <WrappedRoute path={['/@:acct/with_replies', '/accounts/:id/with_replies']} component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
<WrappedRoute path={['/@:acct/followers', '/accounts/:id/followers']} component={Followers} content={children} /> <WrappedRoute path={['/accounts/:id/followers', '/users/:acct/followers', '/@:acct/followers']} component={Followers} content={children} />
<WrappedRoute path={['/@:acct/following', '/accounts/:id/following']} component={Following} content={children} /> <WrappedRoute path={['/accounts/:id/following', '/users/:acct/following', '/@:acct/following']} component={Following} content={children} />
<WrappedRoute path={['/@:acct/media', '/accounts/:id/media']} component={AccountGallery} content={children} /> <WrappedRoute path={['/@:acct/media', '/accounts/:id/media']} component={AccountGallery} content={children} />
<WrappedRoute path='/@:acct/:statusId' exact component={Status} content={children} /> <WrappedRoute path='/@:acct/:statusId' exact component={Status} content={children} />
<WrappedRoute path='/@:acct/:statusId/reblogs' component={Reblogs} content={children} /> <WrappedRoute path='/@:acct/:statusId/reblogs' component={Reblogs} content={children} />

View File

@ -182,6 +182,14 @@ export function Explore () {
return import(/* webpackChunkName: "flavours/glitch/async/explore" */'flavours/glitch/features/explore'); return import(/* webpackChunkName: "flavours/glitch/async/explore" */'flavours/glitch/features/explore');
} }
export function InteractionModal () {
return import(/*webpackChunkName: "flavours/glitch/async/modals/interaction_modal" */'flavours/glitch/features/interaction_modal');
}
export function SubscribedLanguagesModal () {
return import(/*webpackChunkName: "flavours/glitch/async/modals/subscribed_languages_modal" */'flavours/glitch/features/subscribed_languages_modal');
}
export function About () { export function About () {
return import(/*webpackChunkName: "features/glitch/async/about" */'flavours/glitch/features/about'); return import(/*webpackChunkName: "features/glitch/async/about" */'flavours/glitch/features/about');
} }

View File

@ -53,7 +53,9 @@ export class WrappedRoute extends React.Component {
} }
renderLoading = () => { renderLoading = () => {
return <ColumnLoading />; const { multiColumn } = this.props;
return <ColumnLoading multiColumn={multiColumn} />;
} }
renderError = (props) => { renderError = (props) => {

View File

@ -12,14 +12,6 @@ const perf = require('flavours/glitch/performance');
function main() { function main() {
perf.start('main()'); perf.start('main()');
if (window.history && history.replaceState) {
const { pathname, search, hash } = window.location;
const path = pathname + search + hash;
if (!(/^\/web($|\/)/).test(path)) {
history.replaceState(null, document.title, `/web${path}`);
}
}
return ready(async () => { return ready(async () => {
const mountNode = document.getElementById('mastodon'); const mountNode = document.getElementById('mastodon');
const props = JSON.parse(mountNode.getAttribute('data-props')); const props = JSON.parse(mountNode.getAttribute('data-props'));

View File

@ -12,7 +12,6 @@ function main() {
const { messages } = getLocale(); const { messages } = getLocale();
const React = require('react'); const React = require('react');
const ReactDOM = require('react-dom'); const ReactDOM = require('react-dom');
const Rellax = require('rellax');
const { createBrowserHistory } = require('history'); const { createBrowserHistory } = require('history');
const scrollToDetailedStatus = () => { const scrollToDetailedStatus = () => {
@ -90,12 +89,6 @@ function main() {
scrollToDetailedStatus(); scrollToDetailedStatus();
} }
const parallaxComponents = document.querySelectorAll('.parallax');
if (parallaxComponents.length > 0 ) {
new Rellax('.parallax', { speed: -1 });
}
delegate(document, '#registration_user_password_confirmation,#registration_user_password', 'input', () => { delegate(document, '#registration_user_password_confirmation,#registration_user_password', 'input', () => {
const password = document.getElementById('registration_user_password'); const password = document.getElementById('registration_user_password');
const confirmation = document.getElementById('registration_user_password_confirmation'); const confirmation = document.getElementById('registration_user_password_confirmation');

View File

@ -13,6 +13,8 @@ import {
STATUS_REVEAL, STATUS_REVEAL,
STATUS_HIDE, STATUS_HIDE,
STATUS_COLLAPSE, STATUS_COLLAPSE,
STATUS_FETCH_REQUEST,
STATUS_FETCH_FAIL,
} from 'flavours/glitch/actions/statuses'; } from 'flavours/glitch/actions/statuses';
import { import {
TIMELINE_DELETE, TIMELINE_DELETE,
@ -37,6 +39,10 @@ const initialState = ImmutableMap();
export default function statuses(state = initialState, action) { export default function statuses(state = initialState, action) {
switch(action.type) { switch(action.type) {
case STATUS_FETCH_REQUEST:
return state.setIn([action.id, 'isLoading'], true);
case STATUS_FETCH_FAIL:
return state.delete(action.id);
case STATUS_IMPORT: case STATUS_IMPORT:
return importStatus(state, action.status); return importStatus(state, action.status);
case STATUSES_IMPORT: case STATUSES_IMPORT:

View File

@ -42,7 +42,7 @@ export const makeGetStatus = () => {
], ],
(statusBase, statusReblog, accountBase, accountReblog, filters) => { (statusBase, statusReblog, accountBase, accountReblog, filters) => {
if (!statusBase) { if (!statusBase || statusBase.get('isLoading')) {
return null; return null;
} }

View File

@ -106,789 +106,3 @@
margin-left: 10px; margin-left: 10px;
} }
} }
.grid-3 {
display: grid;
grid-gap: 10px;
grid-template-columns: 3fr 1fr;
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
grid-column: 1/3;
grid-row: 1;
}
.column-1 {
grid-column: 1;
grid-row: 2;
}
.column-2 {
grid-column: 2;
grid-row: 2;
}
.column-3 {
grid-column: 1/3;
grid-row: 3;
}
@media screen and (max-width: $no-gap-breakpoint) {
grid-gap: 0;
grid-template-columns: minmax(0, 100%);
.column-0 {
grid-column: 1;
}
.column-1 {
grid-column: 1;
grid-row: 3;
}
.column-2 {
grid-column: 1;
grid-row: 2;
}
.column-3 {
grid-column: 1;
grid-row: 4;
}
}
}
.grid-4 {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(4, minmax(0, 1fr));
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
grid-column: 1 / 5;
grid-row: 1;
}
.column-1 {
grid-column: 1 / 4;
grid-row: 2;
}
.column-2 {
grid-column: 4;
grid-row: 2;
}
.column-3 {
grid-column: 2 / 5;
grid-row: 3;
}
.column-4 {
grid-column: 1;
grid-row: 3;
}
.landing-page__call-to-action {
min-height: 100%;
}
.flash-message {
margin-bottom: 10px;
}
@media screen and (max-width: 738px) {
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
.landing-page__call-to-action {
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.row__information-board {
width: 100%;
justify-content: center;
align-items: center;
}
.row__mascot {
display: none;
}
}
@media screen and (max-width: $no-gap-breakpoint) {
grid-gap: 0;
grid-template-columns: minmax(0, 100%);
.column-0 {
grid-column: 1;
}
.column-1 {
grid-column: 1;
grid-row: 3;
}
.column-2 {
grid-column: 1;
grid-row: 2;
}
.column-3 {
grid-column: 1;
grid-row: 5;
}
.column-4 {
grid-column: 1;
grid-row: 4;
}
}
}
.public-layout {
@media screen and (max-width: $no-gap-breakpoint) {
padding-top: 48px;
}
.container {
max-width: 960px;
@media screen and (max-width: $no-gap-breakpoint) {
padding: 0;
}
}
.header {
background: lighten($ui-base-color, 8%);
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
border-radius: 4px;
height: 48px;
margin: 10px 0;
display: flex;
align-items: stretch;
justify-content: center;
flex-wrap: nowrap;
overflow: hidden;
@media screen and (max-width: $no-gap-breakpoint) {
position: fixed;
width: 100%;
top: 0;
left: 0;
margin: 0;
border-radius: 0;
box-shadow: none;
z-index: 110;
}
& > div {
flex: 1 1 33.3%;
min-height: 1px;
}
.nav-left {
display: flex;
align-items: stretch;
justify-content: flex-start;
flex-wrap: nowrap;
}
.nav-center {
display: flex;
align-items: stretch;
justify-content: center;
flex-wrap: nowrap;
}
.nav-right {
display: flex;
align-items: stretch;
justify-content: flex-end;
flex-wrap: nowrap;
}
.brand {
display: block;
padding: 15px;
.logo {
display: block;
height: 18px;
width: auto;
position: relative;
bottom: -2px;
fill: $primary-text-color;
@media screen and (max-width: $no-gap-breakpoint) {
height: 20px;
}
}
&:hover,
&:focus,
&:active {
background: lighten($ui-base-color, 12%);
}
}
.nav-link {
display: flex;
align-items: center;
padding: 0 1rem;
font-size: 12px;
font-weight: 500;
text-decoration: none;
color: $darker-text-color;
white-space: nowrap;
text-align: center;
&:hover,
&:focus,
&:active {
text-decoration: underline;
color: $primary-text-color;
}
@media screen and (max-width: 550px) {
&.optional {
display: none;
}
}
}
.nav-button {
background: lighten($ui-base-color, 16%);
margin: 8px;
margin-left: 0;
border-radius: 4px;
&:hover,
&:focus,
&:active {
text-decoration: none;
background: lighten($ui-base-color, 20%);
}
}
}
$no-columns-breakpoint: 600px;
.grid {
display: grid;
grid-gap: 10px;
grid-template-columns: minmax(300px, 3fr) minmax(298px, 1fr);
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
grid-row: 1;
grid-column: 1;
}
.column-1 {
grid-row: 1;
grid-column: 2;
}
@media screen and (max-width: $no-columns-breakpoint) {
grid-template-columns: 100%;
grid-gap: 0;
.column-1 {
display: none;
}
}
}
.page-header {
@media screen and (max-width: $no-gap-breakpoint) {
border-bottom: 0;
}
}
.public-account-header {
overflow: hidden;
margin-bottom: 10px;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
&.inactive {
opacity: 0.5;
.public-account-header__image,
.avatar {
filter: grayscale(100%);
}
.logo-button {
background-color: $secondary-text-color;
}
}
.logo-button {
padding: 3px 15px;
}
&__image {
border-radius: 4px 4px 0 0;
overflow: hidden;
height: 300px;
position: relative;
background: darken($ui-base-color, 12%);
&::after {
content: "";
display: block;
position: absolute;
width: 100%;
height: 100%;
box-shadow: inset 0 -1px 1px 1px rgba($base-shadow-color, 0.15);
top: 0;
left: 0;
}
img {
object-fit: cover;
display: block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 4px 4px 0 0;
}
@media screen and (max-width: 600px) {
height: 200px;
}
}
&--no-bar {
margin-bottom: 0;
.public-account-header__image,
.public-account-header__image img {
border-radius: 4px;
@media screen and (max-width: $no-gap-breakpoint) {
border-radius: 0;
}
}
}
@media screen and (max-width: $no-gap-breakpoint) {
margin-bottom: 0;
box-shadow: none;
&__image::after {
display: none;
}
&__image,
&__image img {
border-radius: 0;
}
}
&__bar {
position: relative;
margin-top: -80px;
display: flex;
justify-content: flex-start;
&::before {
content: "";
display: block;
background: lighten($ui-base-color, 4%);
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 60px;
border-radius: 0 0 4px 4px;
z-index: -1;
}
.avatar {
display: block;
width: 120px;
height: 120px;
@include avatar-size(120px);
padding-left: 20px - 4px;
flex: 0 0 auto;
img {
display: block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
border: 4px solid lighten($ui-base-color, 4%);
background: darken($ui-base-color, 8%);
@include avatar-radius();
}
}
@media screen and (max-width: 600px) {
margin-top: 0;
background: lighten($ui-base-color, 4%);
border-radius: 0 0 4px 4px;
padding: 5px;
&::before {
display: none;
}
.avatar {
width: 48px;
height: 48px;
@include avatar-size(48px);
padding: 7px 0;
padding-left: 10px;
img {
border: 0;
border-radius: 4px;
@include avatar-radius();
}
@media screen and (max-width: 360px) {
display: none;
}
}
}
@media screen and (max-width: $no-gap-breakpoint) {
border-radius: 0;
}
@media screen and (max-width: $no-columns-breakpoint) {
flex-wrap: wrap;
}
}
&__tabs {
flex: 1 1 auto;
margin-left: 20px;
&__name {
padding-top: 20px;
padding-bottom: 8px;
h1 {
font-size: 20px;
line-height: 18px * 1.5;
color: $primary-text-color;
font-weight: 500;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-shadow: 1px 1px 1px $base-shadow-color;
small {
display: block;
font-size: 14px;
color: $primary-text-color;
font-weight: 400;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
@media screen and (max-width: 600px) {
margin-left: 15px;
display: flex;
justify-content: space-between;
align-items: center;
&__name {
padding-top: 0;
padding-bottom: 0;
h1 {
font-size: 16px;
line-height: 24px;
text-shadow: none;
small {
color: $darker-text-color;
}
}
}
}
&__tabs {
display: flex;
justify-content: flex-start;
align-items: stretch;
height: 58px;
.details-counters {
display: flex;
flex-direction: row;
min-width: 300px;
}
@media screen and (max-width: $no-columns-breakpoint) {
.details-counters {
display: none;
}
}
.counter {
min-width: 33.3%;
box-sizing: border-box;
flex: 0 0 auto;
color: $darker-text-color;
padding: 10px;
border-right: 1px solid lighten($ui-base-color, 4%);
cursor: default;
text-align: center;
position: relative;
a {
display: block;
}
&:last-child {
border-right: 0;
}
&::after {
display: block;
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
border-bottom: 4px solid $ui-primary-color;
opacity: 0.5;
transition: all 400ms ease;
}
&.active {
&::after {
border-bottom: 4px solid $highlight-text-color;
opacity: 1;
}
&.inactive::after {
border-bottom-color: $secondary-text-color;
}
}
&:hover {
&::after {
opacity: 1;
transition-duration: 100ms;
}
}
a {
text-decoration: none;
color: inherit;
}
.counter-label {
font-size: 12px;
display: block;
}
.counter-number {
font-weight: 500;
font-size: 18px;
margin-bottom: 5px;
color: $primary-text-color;
font-family: $font-display, sans-serif;
}
}
.spacer {
flex: 1 1 auto;
height: 1px;
}
&__buttons {
padding: 7px 8px;
}
}
}
&__extra {
display: none;
margin-top: 4px;
.public-account-bio {
border-radius: 0;
box-shadow: none;
background: transparent;
margin: 0 -5px;
.account__header__fields {
border-top: 1px solid lighten($ui-base-color, 12%);
}
.roles {
display: none;
}
}
&__links {
margin-top: -15px;
font-size: 14px;
color: $darker-text-color;
a {
display: inline-block;
color: $darker-text-color;
text-decoration: none;
padding: 15px;
font-weight: 500;
strong {
font-weight: 700;
color: $primary-text-color;
}
}
}
@media screen and (max-width: $no-columns-breakpoint) {
display: block;
flex: 100%;
}
}
}
.account__section-headline {
border-radius: 4px 4px 0 0;
@media screen and (max-width: $no-gap-breakpoint) {
border-radius: 0;
}
}
.detailed-status__meta {
margin-top: 25px;
}
.public-account-bio {
background: lighten($ui-base-color, 8%);
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
border-radius: 4px;
overflow: hidden;
margin-bottom: 10px;
@media screen and (max-width: $no-gap-breakpoint) {
box-shadow: none;
margin-bottom: 0;
border-radius: 0;
}
.account__header__fields {
margin: 0;
border-top: 0;
a {
color: $highlight-text-color;
}
dl:first-child .verified {
border-radius: 0 4px 0 0;
}
.verified a {
color: $valid-value-color;
}
}
.account__header__content {
padding: 20px;
padding-bottom: 0;
color: $primary-text-color;
}
&__extra,
.roles {
padding: 20px;
font-size: 14px;
color: $darker-text-color;
}
.roles {
padding-bottom: 0;
}
}
.directory__list {
display: grid;
grid-gap: 10px;
grid-template-columns: minmax(0, 50%) minmax(0, 50%);
.account-card {
display: flex;
flex-direction: column;
}
@media screen and (max-width: $no-gap-breakpoint) {
display: block;
.account-card {
margin-bottom: 10px;
display: block;
}
}
}
.card-grid {
display: flex;
flex-wrap: wrap;
min-width: 100%;
margin: 0 -5px;
& > div {
box-sizing: border-box;
flex: 1 0 auto;
width: 300px;
padding: 0 5px;
margin-bottom: 10px;
max-width: 33.333%;
@media screen and (max-width: 900px) {
max-width: 50%;
}
@media screen and (max-width: 600px) {
max-width: 100%;
}
}
@media screen and (max-width: $no-gap-breakpoint) {
margin: 0;
border-top: 1px solid lighten($ui-base-color, 8%);
& > div {
width: 100%;
padding: 0;
margin-bottom: 0;
border-bottom: 1px solid lighten($ui-base-color, 8%);
&:last-child {
border-bottom: 0;
}
.card__bar {
background: $ui-base-color;
&:hover,
&:active,
&:focus {
background: lighten($ui-base-color, 4%);
}
}
}
}
}
}

View File

@ -1,152 +0,0 @@
.public-layout {
.footer {
text-align: left;
padding-top: 20px;
padding-bottom: 60px;
font-size: 12px;
color: lighten($ui-base-color, 34%);
@media screen and (max-width: $no-gap-breakpoint) {
padding-left: 20px;
padding-right: 20px;
}
.grid {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr 2fr 1fr 1fr;
.column-0 {
grid-column: 1;
grid-row: 1;
min-width: 0;
}
.column-1 {
grid-column: 2;
grid-row: 1;
min-width: 0;
}
.column-2 {
grid-column: 3;
grid-row: 1;
min-width: 0;
text-align: center;
h4 a {
color: lighten($ui-base-color, 34%);
}
}
.column-3 {
grid-column: 4;
grid-row: 1;
min-width: 0;
}
.column-4 {
grid-column: 5;
grid-row: 1;
min-width: 0;
}
@media screen and (max-width: 690px) {
grid-template-columns: 1fr 2fr 1fr;
.column-0,
.column-1 {
grid-column: 1;
}
.column-1 {
grid-row: 2;
}
.column-2 {
grid-column: 2;
}
.column-3,
.column-4 {
grid-column: 3;
}
.column-4 {
grid-row: 2;
}
}
@media screen and (max-width: 600px) {
.column-1 {
display: block;
}
}
@media screen and (max-width: $no-gap-breakpoint) {
.column-0,
.column-1,
.column-3,
.column-4 {
display: none;
}
.column-2 h4 {
display: none;
}
}
}
.legal-xs {
display: none;
text-align: center;
padding-top: 20px;
@media screen and (max-width: $no-gap-breakpoint) {
display: block;
}
}
h4 {
text-transform: uppercase;
font-weight: 700;
margin-bottom: 8px;
color: $darker-text-color;
a {
color: inherit;
text-decoration: none;
}
}
ul a,
.legal-xs a {
text-decoration: none;
color: lighten($ui-base-color, 34%);
&:hover,
&:active,
&:focus {
text-decoration: underline;
}
}
.brand {
.logo {
display: block;
height: 36px;
width: auto;
margin: 0 auto;
color: lighten($ui-base-color, 34%);
}
&:hover,
&:focus,
&:active {
.logo {
color: lighten($ui-base-color, 38%);
}
}
}
}
}

View File

@ -9,7 +9,6 @@
@import 'containers'; @import 'containers';
@import 'lists'; @import 'lists';
@import 'modal'; @import 'modal';
@import 'footer';
@import 'widgets'; @import 'widgets';
@import 'forms'; @import 'forms';
@import 'accounts'; @import 'accounts';

View File

@ -354,37 +354,6 @@
} }
} }
.public-layout {
.header,
.public-account-header,
.public-account-bio {
box-shadow: none;
}
.header {
background: lighten($ui-base-color, 12%);
}
.public-account-header {
&__image {
background: lighten($ui-base-color, 12%);
&::after {
box-shadow: none;
}
}
&__tabs {
&__name {
h1,
h1 small {
color: $white;
}
}
}
}
}
.account__section-headline a.active::after { .account__section-headline a.active::after {
border-color: transparent transparent $white; border-color: transparent transparent $white;
} }

View File

@ -30,16 +30,6 @@ body.rtl {
right: -26px; right: -26px;
} }
.landing-page__logo {
margin-right: 0;
margin-left: 20px;
}
.landing-page .features-list .features-list__row .visual {
margin-left: 0;
margin-right: 15px;
}
.column-link__icon, .column-link__icon,
.column-header__icon { .column-header__icon {
margin-right: 0; margin-right: 0;
@ -327,44 +317,6 @@ body.rtl {
margin-left: 45px; margin-left: 45px;
} }
.landing-page .header-wrapper .mascot {
right: 60px;
left: auto;
}
.landing-page__call-to-action .row__information-board {
direction: rtl;
}
.landing-page .header .hero .floats .float-1 {
left: -120px;
right: auto;
}
.landing-page .header .hero .floats .float-2 {
left: 210px;
right: auto;
}
.landing-page .header .hero .floats .float-3 {
left: 110px;
right: auto;
}
.landing-page .header .links .brand img {
left: 0;
}
.landing-page .fa-external-link {
padding-right: 5px;
padding-left: 0 !important;
}
.landing-page .features #mastodon-timeline {
margin-right: 0;
margin-left: 30px;
}
@media screen and (min-width: 631px) { @media screen and (min-width: 631px) {
.column, .column,
.drawer { .drawer {
@ -392,32 +344,6 @@ body.rtl {
padding-right: 0; padding-right: 0;
} }
.public-layout {
.header {
.nav-button {
margin-left: 8px;
margin-right: 0;
}
}
.public-account-header__tabs {
margin-left: 0;
margin-right: 20px;
}
}
.landing-page__information {
.account__display-name {
margin-right: 0;
margin-left: 5px;
}
.account__avatar-wrapper {
margin-left: 12px;
margin-right: 0;
}
}
.card__bar .display-name { .card__bar .display-name {
margin-left: 0; margin-left: 0;
margin-right: 15px; margin-right: 15px;

View File

@ -133,8 +133,7 @@ a.button.logo-button {
justify-content: center; justify-content: center;
} }
.embed, .embed {
.public-layout {
.status__content[data-spoiler=folded] { .status__content[data-spoiler=folded] {
.e-content { .e-content {
display: none; display: none;
@ -204,8 +203,7 @@ a.button.logo-button {
} }
// Styling from upstream's WebUI, as public pages use the same layout // Styling from upstream's WebUI, as public pages use the same layout
.embed, .embed {
.public-layout {
.status { .status {
.status__info { .status__info {
font-size: 15px; font-size: 15px;
@ -244,8 +242,7 @@ a.button.logo-button {
} }
.rtl { .rtl {
.embed, .embed {
.public-layout {
.status { .status {
padding-left: 10px; padding-left: 10px;
padding-right: 68px; padding-right: 68px;