diff --git a/app/controllers/about_controller.rb b/app/controllers/about_controller.rb index 52a51fd62..76f040e54 100644 --- a/app/controllers/about_controller.rb +++ b/app/controllers/about_controller.rb @@ -6,6 +6,8 @@ class AboutController < ApplicationController before_action :set_instance_presenter, only: [:show, :more, :terms] def show + serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer) + @initial_state_json = serializable_resource.to_json @hide_navbar = true end @@ -27,4 +29,11 @@ class AboutController < ApplicationController def set_instance_presenter @instance_presenter = InstancePresenter.new end + + def initial_state_params + { + settings: { known_fediverse: Setting.show_known_fediverse_at_about_page }, + token: current_session&.token, + } + end end diff --git a/app/javascript/mastodon/containers/timeline_container.js b/app/javascript/mastodon/containers/timeline_container.js index 54f8eb310..a1a4bd024 100644 --- a/app/javascript/mastodon/containers/timeline_container.js +++ b/app/javascript/mastodon/containers/timeline_container.js @@ -7,6 +7,7 @@ import { hydrateStore } from '../actions/store'; import { IntlProvider, addLocaleData } from 'react-intl'; import { getLocale } from '../locales'; import PublicTimeline from '../features/standalone/public_timeline'; +import CommunityTimeline from '../features/standalone/community_timeline'; import HashtagTimeline from '../features/standalone/hashtag_timeline'; import ModalContainer from '../features/ui/containers/modal_container'; import initialState from '../initial_state'; @@ -25,22 +26,24 @@ export default class TimelineContainer extends React.PureComponent { static propTypes = { locale: PropTypes.string.isRequired, hashtag: PropTypes.string, - local: PropTypes.bool, + showPublicTimeline: PropTypes.bool.isRequired, }; static defaultProps = { - local: !initialState.settings.known_fediverse, + showPublicTimeline: initialState.settings.known_fediverse, }; render () { - const { locale, hashtag, local } = this.props; + const { locale, hashtag, showPublicTimeline } = this.props; let timeline; if (hashtag) { timeline = ; + } else if (showPublicTimeline) { + timeline = ; } else { - timeline = ; + timeline = ; } return ( @@ -48,7 +51,6 @@ export default class TimelineContainer extends React.PureComponent { {timeline} - {ReactDOM.createPortal( , document.getElementById('modal-container'), diff --git a/app/javascript/mastodon/features/standalone/community_timeline/index.js b/app/javascript/mastodon/features/standalone/community_timeline/index.js new file mode 100644 index 000000000..f917f41c9 --- /dev/null +++ b/app/javascript/mastodon/features/standalone/community_timeline/index.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import StatusListContainer from '../../ui/containers/status_list_container'; +import { expandCommunityTimeline } from '../../../actions/timelines'; +import Column from '../../../components/column'; +import ColumnHeader from '../../../components/column_header'; +import { defineMessages, injectIntl } from 'react-intl'; +import { connectCommunityStream } from '../../../actions/streaming'; + +const messages = defineMessages({ + title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' }, +}); + +export default @connect() +@injectIntl +class CommunityTimeline extends React.PureComponent { + + static propTypes = { + dispatch: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + handleHeaderClick = () => { + this.column.scrollTop(); + } + + setRef = c => { + this.column = c; + } + + componentDidMount () { + const { dispatch } = this.props; + + dispatch(expandCommunityTimeline()); + this.disconnect = dispatch(connectCommunityStream()); + } + + componentWillUnmount () { + if (this.disconnect) { + this.disconnect(); + this.disconnect = null; + } + } + + handleLoadMore = maxId => { + this.props.dispatch(expandCommunityTimeline({ maxId })); + } + + render () { + const { intl } = this.props; + + return ( + + + + + + ); + } + +} diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss index b078d4d24..701642be8 100644 --- a/app/javascript/styles/mastodon/about.scss +++ b/app/javascript/styles/mastodon/about.scss @@ -841,6 +841,14 @@ $small-breakpoint: 960px; strong { font-weight: 500; + display: inline; + margin: 0; + padding: 0; + font-weight: 700; + background: transparent; + font-family: inherit; + font-size: inherit; + line-height: inherit; color: lighten($darker-text-color, 10%); } diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index 368c2304b..719640ef5 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -196,8 +196,6 @@ } .container { - max-width: 960px; - @media screen and (max-width: $no-gap-breakpoint) { padding: 0; } diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml index 162062754..feabcdb66 100644 --- a/app/views/about/show.html.haml +++ b/app/views/about/show.html.haml @@ -3,6 +3,8 @@ - content_for :header_tags do %link{ rel: 'canonical', href: about_url }/ + %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) + = javascript_pack_tag 'about', integrity: true, crossorigin: 'anonymous' = render partial: 'shared/og' .landing-page.alternative @@ -127,3 +129,5 @@ = link_to about_more_path do = t('about.learn_more') = fa_icon 'angle-double-right' + +#modal-container