diff options
26 files changed, 55 insertions, 30 deletions
diff --git a/app/javascript/mastodon/components/column.js b/app/javascript/mastodon/components/column.js index d45387463..55e3bfd5e 100644 --- a/app/javascript/mastodon/components/column.js +++ b/app/javascript/mastodon/components/column.js @@ -8,10 +8,11 @@ export default class Column extends React.PureComponent { static propTypes = { children: PropTypes.node, label: PropTypes.string, + bindToDocument: PropTypes.bool, }; scrollTop () { - const scrollable = this.node.querySelector('.scrollable'); + const scrollable = this.props.bindToDocument ? document.scrollingElement : this.node.querySelector('.scrollable'); if (!scrollable) { return; @@ -33,11 +34,19 @@ export default class Column extends React.PureComponent { } componentDidMount () { - this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + if (this.props.bindToDocument) { + document.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + } else { + this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false); + } } componentWillUnmount () { - this.node.removeEventListener('wheel', this.handleWheel); + if (this.props.bindToDocument) { + document.removeEventListener('wheel', this.handleWheel); + } else { + this.node.removeEventListener('wheel', this.handleWheel); + } } render () { diff --git a/app/javascript/mastodon/components/column_back_button.js b/app/javascript/mastodon/components/column_back_button.js index f41045787..cc0e5c07c 100644 --- a/app/javascript/mastodon/components/column_back_button.js +++ b/app/javascript/mastodon/components/column_back_button.js @@ -2,6 +2,7 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import PropTypes from 'prop-types'; import Icon from 'mastodon/components/icon'; +import { createPortal } from 'react-dom'; export default class ColumnBackButton extends React.PureComponent { @@ -9,6 +10,10 @@ export default class ColumnBackButton extends React.PureComponent { router: PropTypes.object, }; + static propTypes = { + multiColumn: PropTypes.bool, + }; + handleClick = () => { if (window.history && window.history.length === 1) { this.context.router.history.push('/'); @@ -18,12 +23,20 @@ export default class ColumnBackButton extends React.PureComponent { } render () { - return ( + const { multiColumn } = this.props; + + const component = ( <button onClick={this.handleClick} className='column-back-button'> <Icon id='chevron-left' className='column-back-button__icon' fixedWidth /> <FormattedMessage id='column_back_button.label' defaultMessage='Back' /> </button> ); + + if (multiColumn) { + return component; + } else { + return createPortal(component, document.getElementById('tabs-bar__portal')); + } } } diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js index 5d6a53e18..f1a665d8f 100644 --- a/app/javascript/mastodon/features/account_gallery/index.js +++ b/app/javascript/mastodon/features/account_gallery/index.js @@ -56,6 +56,7 @@ class AccountGallery extends ImmutablePureComponent { isLoading: PropTypes.bool, hasMore: PropTypes.bool, isAccount: PropTypes.bool, + multiColumn: PropTypes.bool, }; state = { @@ -116,7 +117,7 @@ class AccountGallery extends ImmutablePureComponent { } render () { - const { attachments, shouldUpdateScroll, isLoading, hasMore, isAccount } = this.props; + const { attachments, shouldUpdateScroll, isLoading, hasMore, isAccount, multiColumn } = this.props; const { width } = this.state; if (!isAccount) { @@ -143,7 +144,7 @@ class AccountGallery extends ImmutablePureComponent { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <ScrollContainer scrollKey='account_gallery' shouldUpdateScroll={shouldUpdateScroll}> <div className='scrollable scrollable--flex' onScroll={this.handleScroll}> diff --git a/app/javascript/mastodon/features/account_timeline/index.js b/app/javascript/mastodon/features/account_timeline/index.js index 9914b7e65..69bab1e86 100644 --- a/app/javascript/mastodon/features/account_timeline/index.js +++ b/app/javascript/mastodon/features/account_timeline/index.js @@ -100,7 +100,7 @@ class AccountTimeline extends ImmutablePureComponent { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <StatusList prepend={<HeaderContainer accountId={this.props.params.accountId} />} diff --git a/app/javascript/mastodon/features/blocks/index.js b/app/javascript/mastodon/features/blocks/index.js index 8fb0f051b..051431ed2 100644 --- a/app/javascript/mastodon/features/blocks/index.js +++ b/app/javascript/mastodon/features/blocks/index.js @@ -57,7 +57,7 @@ class Blocks extends ImmutablePureComponent { const emptyMessage = <FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />; return ( - <Column icon='ban' heading={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} icon='ban' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> <ScrollableList scrollKey='blocks' diff --git a/app/javascript/mastodon/features/community_timeline/index.js b/app/javascript/mastodon/features/community_timeline/index.js index 2f6999f61..f95fa4970 100644 --- a/app/javascript/mastodon/features/community_timeline/index.js +++ b/app/javascript/mastodon/features/community_timeline/index.js @@ -105,7 +105,7 @@ class CommunityTimeline extends React.PureComponent { const pinned = !!columnId; return ( - <Column ref={this.setRef} label={intl.formatMessage(messages.title)}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}> <ColumnHeader icon='users' active={hasUnread} diff --git a/app/javascript/mastodon/features/direct_timeline/index.js b/app/javascript/mastodon/features/direct_timeline/index.js index d202f3bfd..5ce795760 100644 --- a/app/javascript/mastodon/features/direct_timeline/index.js +++ b/app/javascript/mastodon/features/direct_timeline/index.js @@ -75,7 +75,7 @@ class DirectTimeline extends React.PureComponent { const pinned = !!columnId; return ( - <Column ref={this.setRef} label={intl.formatMessage(messages.title)}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}> <ColumnHeader icon='envelope' active={hasUnread} diff --git a/app/javascript/mastodon/features/domain_blocks/index.js b/app/javascript/mastodon/features/domain_blocks/index.js index 16e200b31..482245c86 100644 --- a/app/javascript/mastodon/features/domain_blocks/index.js +++ b/app/javascript/mastodon/features/domain_blocks/index.js @@ -58,7 +58,7 @@ class Blocks extends ImmutablePureComponent { const emptyMessage = <FormattedMessage id='empty_column.domain_blocks' defaultMessage='There are no hidden domains yet.' />; return ( - <Column icon='minus-circle' heading={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} icon='minus-circle' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> <ScrollableList scrollKey='domain_blocks' diff --git a/app/javascript/mastodon/features/favourited_statuses/index.js b/app/javascript/mastodon/features/favourited_statuses/index.js index 8c7b23869..db8a3f815 100644 --- a/app/javascript/mastodon/features/favourited_statuses/index.js +++ b/app/javascript/mastodon/features/favourited_statuses/index.js @@ -74,7 +74,7 @@ class Favourites extends ImmutablePureComponent { const emptyMessage = <FormattedMessage id='empty_column.favourited_statuses' defaultMessage="You don't have any favourite toots yet. When you favourite one, it will show up here." />; return ( - <Column ref={this.setRef} label={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}> <ColumnHeader icon='star' title={intl.formatMessage(messages.heading)} diff --git a/app/javascript/mastodon/features/favourites/index.js b/app/javascript/mastodon/features/favourites/index.js index 464f7aeb0..62d3c2f06 100644 --- a/app/javascript/mastodon/features/favourites/index.js +++ b/app/javascript/mastodon/features/favourites/index.js @@ -51,7 +51,7 @@ class Favourites extends ImmutablePureComponent { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <ScrollableList scrollKey='favourites' diff --git a/app/javascript/mastodon/features/follow_requests/index.js b/app/javascript/mastodon/features/follow_requests/index.js index 570cf57c8..57ef44145 100644 --- a/app/javascript/mastodon/features/follow_requests/index.js +++ b/app/javascript/mastodon/features/follow_requests/index.js @@ -57,7 +57,7 @@ class FollowRequests extends ImmutablePureComponent { const emptyMessage = <FormattedMessage id='empty_column.follow_requests' defaultMessage="You don't have any follow requests yet. When you receive one, it will show up here." />; return ( - <Column icon='user-plus' heading={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} icon='user-plus' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> <ScrollableList scrollKey='follow_requests' diff --git a/app/javascript/mastodon/features/followers/index.js b/app/javascript/mastodon/features/followers/index.js index dce05bdc6..3913bf8d0 100644 --- a/app/javascript/mastodon/features/followers/index.js +++ b/app/javascript/mastodon/features/followers/index.js @@ -78,7 +78,7 @@ class Followers extends ImmutablePureComponent { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <ScrollableList scrollKey='followers' diff --git a/app/javascript/mastodon/features/following/index.js b/app/javascript/mastodon/features/following/index.js index d9f2ef079..8e126f4c3 100644 --- a/app/javascript/mastodon/features/following/index.js +++ b/app/javascript/mastodon/features/following/index.js @@ -78,7 +78,7 @@ class Following extends ImmutablePureComponent { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <ScrollableList scrollKey='following' diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js index fc7840ec1..791f22d47 100644 --- a/app/javascript/mastodon/features/getting_started/index.js +++ b/app/javascript/mastodon/features/getting_started/index.js @@ -148,7 +148,7 @@ class GettingStarted extends ImmutablePureComponent { } return ( - <Column label={intl.formatMessage(messages.menu)}> + <Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.menu)}> {multiColumn && <div className='column-header__wrapper'> <h1 className='column-header'> <button> diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.js b/app/javascript/mastodon/features/hashtag_timeline/index.js index c50f6a79a..28200e6c2 100644 --- a/app/javascript/mastodon/features/hashtag_timeline/index.js +++ b/app/javascript/mastodon/features/hashtag_timeline/index.js @@ -135,7 +135,7 @@ class HashtagTimeline extends React.PureComponent { const pinned = !!columnId; return ( - <Column ref={this.setRef} label={`#${id}`}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={`#${id}`}> <ColumnHeader icon='hashtag' active={hasUnread} diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js index bf8ff117b..1cafb88ed 100644 --- a/app/javascript/mastodon/features/home_timeline/index.js +++ b/app/javascript/mastodon/features/home_timeline/index.js @@ -98,7 +98,7 @@ class HomeTimeline extends React.PureComponent { const pinned = !!columnId; return ( - <Column ref={this.setRef} label={intl.formatMessage(messages.title)}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}> <ColumnHeader icon='home' active={hasUnread} diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.js b/app/javascript/mastodon/features/keyboard_shortcuts/index.js index 01b45652c..90dc87cbb 100644 --- a/app/javascript/mastodon/features/keyboard_shortcuts/index.js +++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.js @@ -18,10 +18,10 @@ class KeyboardShortcuts extends ImmutablePureComponent { }; render () { - const { intl } = this.props; + const { intl, multiColumn } = this.props; return ( - <Column icon='question' heading={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} icon='question' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> <div className='keyboard-shortcuts scrollable optionally-scrollable'> <table> diff --git a/app/javascript/mastodon/features/list_timeline/index.js b/app/javascript/mastodon/features/list_timeline/index.js index 844c93db1..f3205b2bf 100644 --- a/app/javascript/mastodon/features/list_timeline/index.js +++ b/app/javascript/mastodon/features/list_timeline/index.js @@ -148,14 +148,14 @@ class ListTimeline extends React.PureComponent { } else if (list === false) { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <MissingIndicator /> </Column> ); } return ( - <Column ref={this.setRef} label={title}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={title}> <ColumnHeader icon='list-ul' active={hasUnread} diff --git a/app/javascript/mastodon/features/lists/index.js b/app/javascript/mastodon/features/lists/index.js index a06e0b934..7f7f5009c 100644 --- a/app/javascript/mastodon/features/lists/index.js +++ b/app/javascript/mastodon/features/lists/index.js @@ -61,7 +61,7 @@ class Lists extends ImmutablePureComponent { const emptyMessage = <FormattedMessage id='empty_column.lists' defaultMessage="You don't have any lists yet. When you create one, it will show up here." />; return ( - <Column icon='list-ul' heading={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} icon='list-ul' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> <NewListForm /> diff --git a/app/javascript/mastodon/features/mutes/index.js b/app/javascript/mastodon/features/mutes/index.js index 57d8b9915..91dd268c1 100644 --- a/app/javascript/mastodon/features/mutes/index.js +++ b/app/javascript/mastodon/features/mutes/index.js @@ -57,7 +57,7 @@ class Mutes extends ImmutablePureComponent { const emptyMessage = <FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />; return ( - <Column icon='volume-off' heading={intl.formatMessage(messages.heading)}> + <Column bindToDocument={!multiColumn} icon='volume-off' heading={intl.formatMessage(messages.heading)}> <ColumnBackButtonSlim /> <ScrollableList scrollKey='mutes' diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js index e708c4fcf..f2b239afe 100644 --- a/app/javascript/mastodon/features/notifications/index.js +++ b/app/javascript/mastodon/features/notifications/index.js @@ -198,7 +198,7 @@ class Notifications extends React.PureComponent { ); return ( - <Column ref={this.setColumnRef} label={intl.formatMessage(messages.title)}> + <Column bindToDocument={!multiColumn} ref={this.setColumnRef} label={intl.formatMessage(messages.title)}> <ColumnHeader icon='bell' active={isUnread} diff --git a/app/javascript/mastodon/features/pinned_statuses/index.js b/app/javascript/mastodon/features/pinned_statuses/index.js index 64ebfc7ae..ad5c9cafc 100644 --- a/app/javascript/mastodon/features/pinned_statuses/index.js +++ b/app/javascript/mastodon/features/pinned_statuses/index.js @@ -47,7 +47,7 @@ class PinnedStatuses extends ImmutablePureComponent { const { intl, shouldUpdateScroll, statusIds, hasMore, multiColumn } = this.props; return ( - <Column icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef}> + <Column bindToDocument={!multiColumn} icon='thumb-tack' heading={intl.formatMessage(messages.heading)} ref={this.setRef}> <ColumnBackButtonSlim /> <StatusList statusIds={statusIds} diff --git a/app/javascript/mastodon/features/public_timeline/index.js b/app/javascript/mastodon/features/public_timeline/index.js index 1edb303b8..e7825e236 100644 --- a/app/javascript/mastodon/features/public_timeline/index.js +++ b/app/javascript/mastodon/features/public_timeline/index.js @@ -105,7 +105,7 @@ class PublicTimeline extends React.PureComponent { const pinned = !!columnId; return ( - <Column ref={this.setRef} label={intl.formatMessage(messages.title)}> + <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}> <ColumnHeader icon='globe' active={hasUnread} diff --git a/app/javascript/mastodon/features/reblogs/index.js b/app/javascript/mastodon/features/reblogs/index.js index 26f93ad1b..229f626b3 100644 --- a/app/javascript/mastodon/features/reblogs/index.js +++ b/app/javascript/mastodon/features/reblogs/index.js @@ -51,7 +51,7 @@ class Reblogs extends ImmutablePureComponent { return ( <Column> - <ColumnBackButton /> + <ColumnBackButton multiColumn={multiColumn} /> <ScrollableList scrollKey='reblogs' diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js index 6c8cf3f1b..ad4f75820 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.js @@ -471,7 +471,7 @@ class Status extends ImmutablePureComponent { }; return ( - <Column label={intl.formatMessage(messages.detailedStatus)}> + <Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.detailedStatus)}> <ColumnHeader showBackButton multiColumn={multiColumn} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index b979c9b9a..57b387b0d 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2411,6 +2411,8 @@ a.account__display-name { } .column-back-button { + box-sizing: border-box; + width: 100%; background: lighten($ui-base-color, 4%); color: $highlight-text-color; cursor: pointer; |