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

Flat render #503

Closed
wants to merge 1,682 commits into from
Closed

Flat render #503

wants to merge 1,682 commits into from

Conversation

shresthabijay
Copy link
Contributor

@shresthabijay shresthabijay commented Apr 3, 2020

Issue: #188

@raineorshine This is a draft PR for the first iteration of flat rendering implementation. There are many challenges as we move forward to create recreate smooth animations and styles. We may need to create custom HOC to tackle some of the animation challenges. Please test the current implementation. It is far from being complete and lacks many details rn but still we are making good progress.

I have used right split pane to render the FlatTreeRenderer . You can open the split view and see the renderer in action while playing around with current recursive implementation on the left side of the split view.

Copy link
Contributor

@raineorshine raineorshine left a comment

Choose a reason for hiding this comment

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

How much overlap is there between getFlatArray and expandThoughts? Do you plan on consolidating those functions?

@shresthabijay
Copy link
Contributor Author

@raineorshine I tried your suggested solution of passing onExit prop but it didn't work as expected. I have just pushed a small change to address unmount animation delay issue. I have checked the condition and set exit style to have display property set to none instead of setting opacity to 0. I feel like it works much better than before. But I can't decide on my own if that is an improvement. Would you please pull the latest code and test it ? Just create few thoughts and populate one of them with at least 5 to 10 subthoughts and see if direct unmount (without animation) happens without any significant delay as before.

@raineorshine
Copy link
Contributor

3470495 is doing the same thing it was doing before; subthoughts fade out and overlap distant cousins.

https://youtu.be/DI5w9kJSrb0

I tried your suggested solution of passing onExit prop but it didn't work as expected.

In what way? Was it targeting the wrong thoughts, or was the technique not working?

@shresthabijay
Copy link
Contributor Author

3470495 is doing the same thing it was doing before; subthoughts fade out and overlap distant cousins.

https://youtu.be/DI5w9kJSrb0

I tried your suggested solution of passing onExit prop but it didn't work as expected.

In what way? Was it targeting the wrong thoughts, or was the technique not working?

@raineorshine Your observation is absolutely correct. The logic to differentiate unmounting nodes which should animate is still in progress. The issues I wanted to address was that the nodes which directly unmounts without animation still had some delay and lagged.

captured (4)

You can see in the above gif that when cursor is set from thought k to thought a , all the subthoughts of k directly unmounts without any animation. That is the correct behavior but the issue is that they have certain delay before unmount. It is causing visual choppiness as you can see in the gif.

But the problem seems to be solved if we set display to none when node starts exiting.

@shresthabijay
Copy link
Contributor Author

shresthabijay commented Apr 6, 2020

@raineorshine I have pushed latest changes. I have have refactored getFlatArray and completed unmount animation. I have written in detail about the implementation #188 (comment)

There are several cases to achieve unmount animation perfectly. I implemented all of them except case 3. Please read the implementation detail. #188 (comment)

3470495 is doing the same thing it was doing before; subthoughts fade out and overlap distant cousins.

The issue you mentioned above is exactly the third case. With this PR I used very hacky solution to solve it. But I need you to take a look and tell me what you think about it.

Please review it thanks!

@raineorshine
Copy link
Contributor

Ah, that it explains it. I tried the one case that you hadn't implemented yet! I now am trying a different case and it is working.

With this PR I used very hacky solution to solve it.

I'm not sure it solved it. Here's a case that does not work:

  • apple
    • banana
      • clementine [cursor]
  • durian

Activate cursorDown from clementine and the subthoughts of apple incorrectly fade out.

But I need you to take a look and tell me what you think about it.

Will do!

@shresthabijay
Copy link
Contributor Author

shresthabijay commented Apr 6, 2020

I'm not sure it solved it. Here's a case that does not work:

  • apple

    • banana

      • clementine [cursor]
  • durian

Activate cursorDown from clementine and the subthoughts of apple incorrectly fade out.

Ah, I forgot to consider that we can set cursor to thoughts that are not visible too. I will look at it.

@shresthabijay shresthabijay force-pushed the flat-render branch 2 times, most recently from e56379b to d23b965 Compare April 16, 2020 12:24
@shresthabijay
Copy link
Contributor Author

@raineorshine With this latest change you can now test the flat rendered tree with cursor action. I have recreated UI to match current implementation to make comparison easier. There are still many challenges to overcome before we reach our goal. I want you to review this to be sure that we are moving ahead in the right direction.

@shresthabijay
Copy link
Contributor Author

shresthabijay commented Apr 21, 2020

Updates

  • Hide meta thoughts and nodes with =hidden attribute.
  • Show all hidden and meta thoughts if showHiddenThoughts is true.
  • Calculate the number of descendant visible nodes that a thought can render if expanded. Use that number to show either or icon.
  • Refactored flatToArray to get recursive updates from children to reduce redundant logic and iteration of children array within a parent scope.

Copy link
Contributor

@raineorshine raineorshine left a comment

Choose a reason for hiding this comment

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

Very pleased with the result so far! The animation looks quite good. It's a little choppy on mobile Safari, but we can address that separately, or worst case disable the height animation on mobile. I don't see any of the major rendering issues we were having earlier. Thank you.

I took a more in-depth look at the code this time. It's looking very good. The component is quite small, and getFlatArray mostly consists of expansion logic, which is expected. I didn't go over the expansion logic in detail, but focused on the recursion and overall architecture. Questions are below.

I renamed some variables and made a couple small refactors. Make sure to pull my changes into your branch.

Thank you!

})
}

export const treeToFlatArray = (cursor, showHiddenThoughts) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We have a convention to name the file the same as the function when there is a single export.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@raineorshine Sure I will change the name.

@shresthabijay
Copy link
Contributor Author

Table View Update

@raineorshine This is the first iteration of table view with flat renderer. Following goals have been achieved:

  • Recreated 1st column and 2nd column layout without nested nodes. It looks exactly like current recursive implementation.
  • Collapse 2nd column nodes even if they have single children.
  • Proper animation.

Here are some clips showcasing the update

Table view toggle

https://drive.google.com/file/d/1LQCcGARD1WH9Ov3mQOiolOm0D8BrqDcl/view?usp=sharing

Table view toggle with meta =pinChildren

https://drive.google.com/file/d/1LLu4X97f6G_tqnrLisZaJd-J7gFYpn80/view?usp=sharing

Navigating with table view ON

https://drive.google.com/file/d/1LNLIL8SlYvXiFnaF45foffvOad-v2ZvU/view?usp=sharing

There are still many things to work on this before it is fully functional. Will keep you updated!

@raineorshine
Copy link
Contributor

Table View Update

@raineorshine This is the first iteration of table view with flat renderer. Following goals have been achieved:

  • Recreated 1st column and 2nd column layout without nested nodes. It looks exactly like current recursive implementation.
  • Collapse 2nd column nodes even if they have single children.
  • Proper animation.

Awesome!!! That is fantastic. Excellent work!

Here are some clips showcasing the update

Table view toggle

https://drive.google.com/file/d/1LQCcGARD1WH9Ov3mQOiolOm0D8BrqDcl/view?usp=sharing

Nice! This looks great. There is a slight modification needed for information design reasons. Take a look at this screenshot of the middle of the animation:

Screen Shot 2020-05-05 at 10 38 30 AM

The way column 2 animates in results in a misalignment between thoughts and subthoughts. ii is a child of c, ty, and ola are subthoughts of td, etc, yet the "rows" have been broken and subthoughts are not lining up horizontally until the animation completes. Maintaining the rows is an important design invariant. To do this, we will need the subthoughts to start at the correct vertical level and fade in and translate from left-to-right.

It may be trickier to maintain the row when there are multiple subthoughts in column 2. In this case, the vertical height will be animating to fit the subthoughts. During that time, we have to make sure the subthoughts are animated in at a similar pace so that they do not overlap the row of their uncle in column 1. Not sure how much this requirement will be met by default, or if it will require a lot of custom logic.

Table view toggle with meta =pinChildren

https://drive.google.com/file/d/1LLu4X97f6G_tqnrLisZaJd-J7gFYpn80/view?usp=sharing

WOW. I am stunned by this animation. It looks SO GOOD!!! I am so excited. I'm praying we can get it to run smoothly on all platforms, because this is exactly what we want.

Navigating with table view ON

https://drive.google.com/file/d/1LNLIL8SlYvXiFnaF45foffvOad-v2ZvU/view?usp=sharing

Again this looks absolutely amazing.

There are still many things to work on this before it is fully functional. Will keep you updated!

I haven't looked at the code yet since you're still working on it, but let me know whenever it's ready for a code review, or if you want my advice on any architectural decisions!

Keep up the great work!

@shresthabijay
Copy link
Contributor Author

TABLE VIEW SECOND UPDATE

@raineorshine With this update the table view is now functional to be tested. We have achieved following goals:

  • Table View second column left to right xOffset and opacity transition on component enter and vice versa on component leave.
  • Prevent Table View second column yOffset animation on enter.
  • Allow multiple table view to open.
  • Adjust nodes at deeper depth to adjust their xOffset according to the number of open table views above them.
  • Allow changing offset values of first column and second column whenever needed.
  • Properly grouped and commented logic for code readability.

Table view toggle with left to right xOffset transform and opacity transition.

captured (1)

Table view toggle with one of the children pinned open.

captured (2)

Multiple table views open

captured (3)

Multiple table views with hidden thoughts on

captured (4)

Please review the code and let me know about your thoughts on the progress.

@shresthabijay
Copy link
Contributor Author

shresthabijay commented May 11, 2020

TO DO

  • Since second column uses yOffset transform to be at the same vertical place as first column, it trades off height animation. So when both first column and second column animates out, all second column thoughts align at same position.
  • The current implementation gives first column a fixed width. So we need to handle text wrap. Right now longer text just spans out of the div.

@raineorshine
Copy link
Contributor

raineorshine commented May 11, 2020

The screenshots really speak for themselves. Wow. I think this is going to blow people away. I mean, is there any outliner out there with animations like this?!? It's just incredible.

The table view is looking great and there are more cases than I can name in which animations are working perfectly. We may want to tweak the animations for certain actions, like existingThoughtMove, but we can and should defer that to a future task if it's working adequately as-is.

The only issue I'm noticing is when the cursor moves to column 2 of a table, it reverts to normal view. Instead, it should continue to render column 1 and column 2 as a table, just translated to the left (as in dev).

Unrelated to tables, there's a couple core pieces of functionality that need to be restored, as you may be aware of:

  1. editing
  2. ThoughtAnnotation (with Superscript)
  3. Drag and Drop

  • Since second column uses yOffset transform to be at the same vertical place as first column, it trades off height animation. So when both first column and second column animates out, all second column thoughts align at same position.

Do you have steps to reproduce? I'm not seeing the issue.

  • The current implementation gives first column a fixed width. So we need to handle text wrap. Right now longer text just spans out of the div.

Yes, the cells should also be vertically aligned top:

Screen Shot 2020-05-11 at 2 10 43 PM

Separate component for drop end

convert treeToFlatArray and FlatTreeRenderer to tsx
fix DND root context drop bug
change showContexts to showContextsParent

add id to ranked root

fix glitch related to no children context component
remove layout animation due to width change issue

bind height change to the wrapper div to allow drop end height to cause height animation

remove homelink from thought annotation
@shresthabijay
Copy link
Contributor Author

  • cursorUp is not working. I'm not sure why this is the case, since this reducer shouldn't be affected by rendering.

It has not been working for me in dev for quite a while. I have not been able to find the cause of it.

@shresthabijay
Copy link
Contributor Author

  • moveThoughtUp/Down is not animated. Wasn't this previously solved by framer-motion?

Yes. It was working. It didn't work well when changing width of the thought for first column width in table view. I have disabled it for now. I will be working on solving that issue.

rebase to dev

split and merge content editable behavior fixed
@raineorshine
Copy link
Contributor

  • cursorUp is not working. I'm not sure why this is the case, since this reducer shouldn't be affected by rendering.

It has not been working for me in dev for quite a while. I have not been able to find the cause of it.

cursorUp is working for me in dev. The cursorUp reducer tests are passing in this PR, so maybe the issue is in the action-creator or shortcut.

  • moveThoughtUp/Down is not animated. Wasn't this previously solved by framer-motion?

Yes. It was working. It didn't work well when changing width of the thought for first column width in table view. I have disabled it for now. I will be working on solving that issue.

Sounds good.

@raineorshine
Copy link
Contributor

Fixing the unit tests should probably be the top priority.

use react-use-measure instead of custom hook

cancel debounced height callback function on unmount

set cursor offset
add id to the cursor on new thought

add id to cursor on exisitingThoughtChange

find editable using key of the node
add blue overlay on bullet when drag is active

update ContentEditable for proper split behavior
@shresthabijay
Copy link
Contributor Author

Fixing the unit tests should probably be the top priority.

@raineorshine I have fixed all the tests. But I ran into problems with drag and drop tests. Turns out testing DND with useDrag and useDrop hooks has not been addressed yet. react-dnd/react-dnd#1540 . We should either use HOC like before or create mock for these hooks. Ideally we shouldn't need to mock these hooks. What do you think ?

@shresthabijay
Copy link
Contributor Author

cursorUp is working for me in dev. The cursorUp reducer tests are passing in this PR, so maybe the issue is in the action-creator or shortcut.

There is a extra white space after px in this file. This is causing split to not return the intended result. Removing that white space fixes cursorUp behavior. Can you confirm that the extra white space is not intended ?

/** Gets the padding of an element as an array of numbers. */
export const getElementPaddings = (element: HTMLElement): number[] =>
window
.getComputedStyle(element, null)
.getPropertyValue('padding')
.split('px ')

@raineorshine
Copy link
Contributor

@raineorshine I have fixed all the tests. But I ran into problems with drag and drop tests. Turns out testing DND with useDrag and useDrop hooks has not been addressed yet. react-dnd/react-dnd#1540 . We should either use HOC like before or create mock for these hooks. Ideally we shouldn't need to mock these hooks. What do you think ?

That's a bummer. Does their latest version support HOC, or would we have to decrease the version we are using? I think HOC with tests is probably better than hooks without tests if we had to choose.

There is a extra white space after px in this file. This is causing split to not return the intended result. Removing that white space fixes cursorUp behavior. Can you confirm that the extra white space is not intended ?

Assuming the padding value is 5px 10px for example, then .split('px ') will correctly return ['5px', '10px']. Maybe it's not the whitespace that's the problem, but the way it handles a certain padding value, or no value?

@shresthabijay
Copy link
Contributor Author

Assuming the padding value is 5px 10px for example, then .split('px ') will correctly return ['5px', '10px']. Maybe it's not the whitespace that's the problem, but the way it handles a certain padding value, or no value?

Sometimes padding value can return just 5px. At this case split('px ') will fail. This logic is used for getting padding top inside ContentEditable. Instead of getting padding we can get padding-top which will always be returned with a single value.

update drag and drop tests

update component tests

fix move thought up

add id to the cursor
@raineorshine
Copy link
Contributor

@shresthabijay Should we close this and reconstruct it at a later point? It seems too far behind to use this PR.

@shresthabijay
Copy link
Contributor Author

@shresthabijay Should we close this and reconstruct it at a later point? It seems too far behind to use this PR.

Yes. This PR is too far behind. We can use it as a reference later if we need it.

@raineorshine raineorshine mentioned this pull request Oct 26, 2022
19 tasks
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.

4 participants