diff --git a/app/assets/javascripts/components/components/status_list.jsx b/app/assets/javascripts/components/components/status_list.jsx
index dc2a9509d..517c8fe5d 100644
--- a/app/assets/javascripts/components/components/status_list.jsx
+++ b/app/assets/javascripts/components/components/status_list.jsx
@@ -60,7 +60,7 @@ class StatusList extends React.PureComponent {
}
render () {
- const { statusIds, onScrollToBottom, trackScroll, isLoading, isUnread, hasMore, prepend, emptyMessage } = this.props;
+ const { statusIds, onScrollToBottom, scrollKey, shouldUpdateScroll, isLoading, isUnread, hasMore, prepend, emptyMessage } = this.props;
let loadMore = '';
let scrollableArea = '';
@@ -98,25 +98,22 @@ class StatusList extends React.PureComponent {
);
}
- if (trackScroll) {
- return (
-
- {scrollableArea}
-
- );
- } else {
- return scrollableArea;
- }
+ return (
+
+ {scrollableArea}
+
+ );
}
}
StatusList.propTypes = {
+ scrollKey: PropTypes.string.isRequired,
statusIds: ImmutablePropTypes.list.isRequired,
onScrollToBottom: PropTypes.func,
onScrollToTop: PropTypes.func,
onScroll: PropTypes.func,
- trackScroll: PropTypes.bool,
+ shouldUpdateScroll: PropTypes.func,
isLoading: PropTypes.bool,
isUnread: PropTypes.bool,
hasMore: PropTypes.bool,
diff --git a/app/assets/javascripts/components/containers/mastodon.jsx b/app/assets/javascripts/components/containers/mastodon.jsx
index e2b91e5dd..c85a353ee 100644
--- a/app/assets/javascripts/components/containers/mastodon.jsx
+++ b/app/assets/javascripts/components/containers/mastodon.jsx
@@ -99,6 +99,125 @@ addLocaleData([
...id,
]);
+const getTopWhenReplacing = (previous, { location }) => location && location.action === 'REPLACE' && [0, 0];
+
+const hiddenColumnContainerStyle = {
+ position: 'absolute',
+ left: '0',
+ top: '0',
+ visibility: 'hidden'
+};
+
+class Container extends React.PureComponent {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ renderedPersistents: [],
+ unrenderedPersistents: [],
+ };
+ }
+
+ componentWillMount () {
+ this.unlistenHistory = null;
+
+ this.setState(() => {
+ return {
+ mountImpersistent: false,
+ renderedPersistents: [],
+ unrenderedPersistents: [
+ {pathname: '/timelines/home', component: HomeTimeline},
+ {pathname: '/timelines/public', component: PublicTimeline},
+ {pathname: '/timelines/public/local', component: CommunityTimeline},
+
+ {pathname: '/notifications', component: Notifications},
+ {pathname: '/favourites', component: FavouritedStatuses}
+ ],
+ };
+ }, () => {
+ if (this.unlistenHistory) {
+ return;
+ }
+
+ this.unlistenHistory = browserHistory.listen(location => {
+ const pathname = location.pathname.replace(/\/$/, '').toLowerCase();
+
+ this.setState(oldState => {
+ let persistentMatched = false;
+
+ const newState = {
+ renderedPersistents: oldState.renderedPersistents.map(persistent => {
+ const givenMatched = persistent.pathname === pathname;
+
+ if (givenMatched) {
+ persistentMatched = true;
+ }
+
+ return {
+ hidden: !givenMatched,
+ pathname: persistent.pathname,
+ component: persistent.component
+ };
+ }),
+ };
+
+ if (!persistentMatched) {
+ newState.unrenderedPersistents = [];
+
+ oldState.unrenderedPersistents.forEach(persistent => {
+ if (persistent.pathname === pathname) {
+ persistentMatched = true;
+
+ newState.renderedPersistents.push({
+ hidden: false,
+ pathname: persistent.pathname,
+ component: persistent.component
+ });
+ } else {
+ newState.unrenderedPersistents.push(persistent);
+ }
+ });
+ }
+
+ newState.mountImpersistent = !persistentMatched;
+
+ return newState;
+ });
+ });
+ });
+ }
+
+ componentWillUnmount () {
+ if (this.unlistenHistory) {
+ this.unlistenHistory();
+ }
+
+ this.unlistenHistory = "done";
+ }
+
+ render () {
+ // Hide some components rather than unmounting them to allow to show again
+ // quickly and keep the view state such as the scrolled offset.
+ const persistentsView = this.state.renderedPersistents.map((persistent) =>
+
+ );
+
+ return (
+
+ {this.state.mountImpersistent && this.props.children}
+ {persistentsView}
+
+ );
+ }
+}
+
+Container.propTypes = {
+ children: PropTypes.node,
+};
+
class Mastodon extends React.Component {
componentDidMount() {
@@ -160,18 +279,12 @@ class Mastodon extends React.Component {
-
+
-
-
-
-
-
-
diff --git a/app/assets/javascripts/components/features/account_timeline/index.jsx b/app/assets/javascripts/components/features/account_timeline/index.jsx
index 4987a2364..a06de3d21 100644
--- a/app/assets/javascripts/components/features/account_timeline/index.jsx
+++ b/app/assets/javascripts/components/features/account_timeline/index.jsx
@@ -62,6 +62,7 @@ class AccountTimeline extends React.PureComponent {
}
+ scrollKey='account_timeline'
statusIds={statusIds}
isLoading={isLoading}
hasMore={hasMore}
diff --git a/app/assets/javascripts/components/features/community_timeline/index.jsx b/app/assets/javascripts/components/features/community_timeline/index.jsx
index c2d8bf2ed..3877888ba 100644
--- a/app/assets/javascripts/components/features/community_timeline/index.jsx
+++ b/app/assets/javascripts/components/features/community_timeline/index.jsx
@@ -77,7 +77,7 @@ class CommunityTimeline extends React.PureComponent {
return (
- } />
+ } />
);
}
diff --git a/app/assets/javascripts/components/features/favourited_statuses/index.jsx b/app/assets/javascripts/components/features/favourited_statuses/index.jsx
index d6f53bf33..bc45ace51 100644
--- a/app/assets/javascripts/components/features/favourited_statuses/index.jsx
+++ b/app/assets/javascripts/components/features/favourited_statuses/index.jsx
@@ -47,7 +47,7 @@ class Favourites extends React.PureComponent {
return (
-
+
);
}
diff --git a/app/assets/javascripts/components/features/hashtag_timeline/index.jsx b/app/assets/javascripts/components/features/hashtag_timeline/index.jsx
index 5c091e17f..0575e9214 100644
--- a/app/assets/javascripts/components/features/hashtag_timeline/index.jsx
+++ b/app/assets/javascripts/components/features/hashtag_timeline/index.jsx
@@ -71,7 +71,7 @@ class HashtagTimeline extends React.PureComponent {
return (
- } />
+ } />
);
}
diff --git a/app/assets/javascripts/components/features/home_timeline/index.jsx b/app/assets/javascripts/components/features/home_timeline/index.jsx
index 6b986171e..52b94690d 100644
--- a/app/assets/javascripts/components/features/home_timeline/index.jsx
+++ b/app/assets/javascripts/components/features/home_timeline/index.jsx
@@ -22,7 +22,7 @@ class HomeTimeline extends React.PureComponent {
return (
- }} />} />
+ }} />} />
);
}
diff --git a/app/assets/javascripts/components/features/notifications/index.jsx b/app/assets/javascripts/components/features/notifications/index.jsx
index 14c00b9ce..da3ce2f62 100644
--- a/app/assets/javascripts/components/features/notifications/index.jsx
+++ b/app/assets/javascripts/components/features/notifications/index.jsx
@@ -80,7 +80,7 @@ class Notifications extends React.PureComponent {
}
render () {
- const { intl, notifications, trackScroll, isLoading, isUnread } = this.props;
+ const { intl, notifications, shouldUpdateScroll, isLoading, isUnread } = this.props;
let loadMore = '';
let scrollableArea = '';
@@ -113,25 +113,15 @@ class Notifications extends React.PureComponent {
);
}
- if (trackScroll) {
- return (
-
-
-
-
- {scrollableArea}
-
-
- );
- } else {
- return (
-
-
-
+ return (
+
+
+
+
{scrollableArea}
-
- );
- }
+
+
+ );
}
}
@@ -139,7 +129,7 @@ class Notifications extends React.PureComponent {
Notifications.propTypes = {
notifications: ImmutablePropTypes.list.isRequired,
dispatch: PropTypes.func.isRequired,
- trackScroll: PropTypes.bool,
+ shouldUpdateScroll: PropTypes.func,
intl: PropTypes.object.isRequired,
isLoading: PropTypes.bool,
isUnread: PropTypes.bool
diff --git a/app/assets/javascripts/components/features/public_timeline/index.jsx b/app/assets/javascripts/components/features/public_timeline/index.jsx
index fa7a2db8e..53be13686 100644
--- a/app/assets/javascripts/components/features/public_timeline/index.jsx
+++ b/app/assets/javascripts/components/features/public_timeline/index.jsx
@@ -77,7 +77,7 @@ class PublicTimeline extends React.PureComponent {
return (
- } />
+ } />
);
}
diff --git a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx
index 4c33f2b61..1599000b5 100644
--- a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx
+++ b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx
@@ -40,6 +40,8 @@ const makeMapStateToProps = () => {
const getStatusIds = makeGetStatusIds();
const mapStateToProps = (state, props) => ({
+ scrollKey: props.scrollKey,
+ shouldUpdateScroll: props.shouldUpdateScroll,
statusIds: getStatusIds(state, props),
isLoading: state.getIn(['timelines', props.type, 'isLoading'], true),
isUnread: state.getIn(['timelines', props.type, 'unread']) > 0,
diff --git a/app/assets/javascripts/components/features/ui/index.jsx b/app/assets/javascripts/components/features/ui/index.jsx
index 1f35842d9..c92b9751b 100644
--- a/app/assets/javascripts/components/features/ui/index.jsx
+++ b/app/assets/javascripts/components/features/ui/index.jsx
@@ -127,9 +127,9 @@ class UI extends React.PureComponent {
mountedColumns = (
-
-
- {children}
+ false} />
+ false} />
+ {children}
);
}
diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss
index feab81366..0c8379be4 100644
--- a/app/assets/stylesheets/components.scss
+++ b/app/assets/stylesheets/components.scss
@@ -89,11 +89,11 @@
border: none;
background: transparent;
cursor: pointer;
- transition: all 100ms ease-in;
+ transition: color 100ms ease-in;
&:hover, &:active, &:focus {
color: lighten($color1, 33%);
- transition: all 200ms ease-out;
+ transition: color 200ms ease-out;
}
&.disabled {
@@ -152,11 +152,11 @@
padding: 0 3px;
line-height: 27px;
outline: 0;
- transition: all 100ms ease-in;
+ transition: color 100ms ease-in;
&:hover, &:active, &:focus {
color: lighten($color1, 26%);
- transition: all 200ms ease-out;
+ transition: color 200ms ease-out;
}
&.disabled {
@@ -1100,6 +1100,7 @@ a.status__content__spoiler-link {
flex-direction: row;
justify-content: flex-start;
overflow-x: auto;
+ position: relative;
}
@media screen and (min-width: 360px) {
@@ -1257,11 +1258,11 @@ a.status__content__spoiler-link {
flex-direction: row;
a {
- transition: all 100ms ease-in;
+ transition: background 100ms ease-in;
&:hover {
background: lighten($color1, 3%);
- transition: all 200ms ease-out;
+ transition: background 200ms ease-out;
}
}
}
diff --git a/app/assets/stylesheets/containers.scss b/app/assets/stylesheets/containers.scss
index 43705b19c..6f339f998 100644
--- a/app/assets/stylesheets/containers.scss
+++ b/app/assets/stylesheets/containers.scss
@@ -9,6 +9,16 @@
}
}
+.mastodon-column-container {
+ display: flex;
+ height: 100%;
+ width: 100%;
+
+ // 707568 - height 100% doesn't work on child of a flex item - chromium - Monorail
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=707568
+ flex: 1 1 auto;
+}
+
.logo-container {
max-width: 400px;
margin: 100px auto;
@@ -40,7 +50,7 @@
img {
opacity: 0.8;
- transition: all 0.8s ease;
+ transition: opacity 0.8s ease;
}
&:hover {