Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #3665 - Refactor timelines reducer #3686

Merged
merged 7 commits into from Jun 11, 2017

Conversation

Gargron
Copy link
Member

@Gargron Gargron commented Jun 10, 2017

Fix #3665

Before:

timelines
  home
  public
  community
  tag
  accounts_timelines
    3
    6
  accounts_media_timelines
    1
    3
    4

After:

timelines
  home
  public
  community
  hashtag:test
  hashtag:foobar
  account:3
  account:6
  account:1:media
  account:3:media
  account:4:media

Previously they all had different action creators and action signatures, e.g. FETCH_ACCOUNT_TIMELINE_SUCCESS specifically, etc. They also had special treatment in the reducer, with slightly different functions to handle each action. Also, there could be only one tag timeline, loading a new hashtag replaced the previous one.

Now everything is using the same action creators (with convenience curries) and the same action signatures e.g. TIMELINE_REFRESH_SUCCESS, and different hashtags can co-exist in the same world.

All types of timelines now have a flat structure and use the same
reducer functions and actions
@Gargron Gargron changed the title Feature refactor timelines reducer Refactor timelines reducer Jun 10, 2017
@Gargron Gargron changed the title Refactor timelines reducer Fix #3665 - Refactor timelines reducer Jun 10, 2017
Copy link
Sponsor Member

@ykzts ykzts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good.

@ykzts
Copy link
Sponsor Member

ykzts commented Jun 10, 2017

@beatrix-bitrot I will ask you to check with the production:smile:

@unarist
Copy link
Contributor

unarist commented Jun 10, 2017

I found some warnings on Chrome 58 console:

./app/javascript/mastodon/features/report/index.js
88:24-46 "export 'refreshAccountTimeline' was not found in '../../actions/accounts'
./app/javascript/mastodon/features/report/index.js
93:26-48 "export 'refreshAccountTimeline' was not found in '../../actions/accounts'

Also this patch brings back account timeline issue #3447. Second fetching (with since_id) may not return next link, so it prevents load more if save that result to the state.

@Gargron
Copy link
Member Author

Gargron commented Jun 10, 2017

@unarist expandTimeline uses max_id: ids.last(), ignoring the next path. This is because timelines can be cropped at around 40 items, and if you were using the next header, scrolling down again would bring you further and further into the past, skipping past the cropped items. Plus, as far as timelines are concerned max_id uses the primary ID

@unarist
Copy link
Contributor

unarist commented Jun 10, 2017

@Gargron next path isn't used actually, but existence of it is important, because account timeline's handleScrollToBottom() checks it as hasMore.

  handleScrollToBottom = () => {
    if (!this.props.isLoading && this.props.hasMore) {
      this.props.dispatch(expandAccountTimeline(Number(this.props.params.accountId)));
    }
  }

Did you checked the issue I mentioned is not reproduced with this patch?

@Gargron
Copy link
Member Author

Gargron commented Jun 10, 2017

@unarist You are right. Perhaps hasMore should always be true. That's how it used to be at the very start...

@clworld
Copy link
Contributor

clworld commented Jun 10, 2017

@unarist @Gargron
I deployed this on my production. (my staging environment does not have enough number of toots…)
This PR reproduces issue #3447.

@clworld
Copy link
Contributor

clworld commented Jun 10, 2017

I got some errors in Console.
timeline (Both firefox and chrome)
festseek (In chrome only)
I'm trying git fetch/assets:precompile and restart puma, re-check this error is hard (Japan is 3:30 AM now.. timeline stops..)
After re-fetch/assets:precompile and restart puma I got r.include error. I can't determine when this error happen.(It seems timeline related..)
I got e.fastSeek only one times and can not re-produce e.fastSeek….(except when I add breakpoint for r.include error and stop js execution.) It seems unrelated to this PR and ignorable.

@unarist
Copy link
Contributor

unarist commented Jun 10, 2017

actions/timelines.js:

export function updateTimeline(timeline, status) {
  return (dispatch, getState) => {
    const references = status.reblog ? getState().get('statuses').filter((item, itemId) => (itemId === status.reblog.id || item.get('reblog') === status.reblog.id)).map((_, itemId) => itemId) : [];

getState().get('statuses')... and [] have includes() method, but [] has include() method...slightly different name.

And in updateTimeline() in reducers/timelines.js...

if (status.getIn(['reblog', 'id'], null) !== null) newIds = newIds.filterNot(item => references.include(item));

It should be includes() not include() . I think this is one of the issue @clworld reported..

@Gargron
Copy link
Member Author

Gargron commented Jun 10, 2017

@unarist @clworld I have fixed the includes typo.

I am surprised if #3447 re-appears again, because expandTimeline does not use next? Let me double check

@Gargron
Copy link
Member Author

Gargron commented Jun 10, 2017

Oh wait! The problem is only because hasMore blocks the loading of more stuff, right?

@clworld
Copy link
Contributor

clworld commented Jun 10, 2017

@Gargron
I deployed fix and I checked r.include error does not happen.
unarist seems already go to sleep 1.5 hour ago.. (5:55 a.m. now in Japan)

@unarist
Copy link
Contributor

unarist commented Jun 11, 2017

@Gargron

hasMore blocks the loading of more stuff,

Right. account/:id/statuses with since_id may returns response without next link header, then it overwrites timelines.['accounts:xxx'].next with null. This means making hasMore to be false, and blocks the loading. We shouldn't overwrite that property on the loading newer statuses.

Well, maybe account/:id/statuses with since_id option should returns next link header, since we don't know existence of older status than since_id value.

@Gargron
Copy link
Member Author

Gargron commented Jun 11, 2017

@unarist Ah, I was thinking of a slightly different scenario. Same bug currently occurs in notification column too:

  1. Scroll down to load more posts, or wait until >40 posts are loaded
  2. If you are scrolled to top and a new post arrives, all posts after the 20th will be cut off
  3. Scroll down again to the bottom to load more posts.

Expected: It will load the posts after the last visible one, without gaps
Reality: It will load posts after the last invisible one, because that's where the "next" pointed already

So I think that the usage of "next" in the timelines specifically should be removed, and hasMore should always be true.

@unarist
Copy link
Contributor

unarist commented Jun 11, 2017

hasMore should always be true.

We shouldn't make hasMore always true, because it allows the user loading more statuses infinitely (#2066).

Also timelines may have "end" especially on remote account timeline. So I've changed accounts/:id:/statuses API to return next link only if needed (#3311), to reduce redundant requests. but If you think handling this is too complicated, how about to set next to true on TIMELINE_REFRESH and keep current behavior on TIMELINE_EXPAND? This allows loading more at least once even on too short timeline, but it's not a huge problem.

Well, maybe we should store boolean value for next state instead of link header value itself to prevent misuse...

@Gargron
Copy link
Member Author

Gargron commented Jun 11, 2017

@unarist Okay, I think my last commit should take care of the issue. I think I had just accidentally removed the fix that was already there, i.e. only set "next" if previous "next" wasn't set in refreshTimeline (that's the since_id case)

I also found that there was a typo in expandNotifications, which had been there for a long time, and fixed that too.

@@ -124,10 +124,9 @@ export function refreshNotificationsFail(error, skipLoading) {

export function expandNotifications() {
return (dispatch, getState) => {
const url = getState().getIn(['notifications', 'next'], null);
const lastId = getState().getIn(['notifications', 'items']).last();
Copy link
Contributor

@unarist unarist Jun 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, lastId is whole entity, not id...

@clworld
Copy link
Contributor

clworld commented Jun 11, 2017

@unarist Yes. notifications stop doing load more...

@clworld
Copy link
Contributor

clworld commented Jun 11, 2017

I found glitch reported by beatrix on Discord exists.
It happens when:

  1. open Mastodon with home timeline (scroll position is top of timeline)
  2. new toot arrived.
  3. Title indicates there is unread toots but scroll position is top of timeline already.
  4. After scrolling (scroll down and move to top), unread indicator works good.

@Gargron
Copy link
Member Author

Gargron commented Jun 11, 2017

@clworld @beatrix-bitrot @unarist Okay, fixed!

@Gargron Gargron merged commit 47bf7a8 into master Jun 11, 2017
@Gargron Gargron deleted the feature-refactor-timelines-reducer branch June 11, 2017 15:07
koteitan pushed a commit to koteitan/mastodon that referenced this pull request Jun 25, 2017
* Move ancestors/descendants out of timelines reducer

* Refactor timelines reducer

All types of timelines now have a flat structure and use the same
reducer functions and actions

* Reintroduce some missing behaviours

* Fix wrong import in reports

* Fix includes typo

* Fix issue related to "next" pagination in timelines and notifications

* Fix bug with timeline's initial state, expandNotifications
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants