|
| 1 | +# Notebook Layout |
| 2 | + |
| 3 | +The notebook editor is a virtualized list view rendered in two contexts (mainframe and webview/iframe). Since most elements' positions are absoulte and there is latency between the two frames, we have multiple optimizations to ensure smooth (we try our best) perceived user experience. The optimizations are mostly around: |
| 4 | + |
| 5 | +* Ensure the elements in curent viewport are stable when other elements dimensions update |
| 6 | +* Fewer layout messages between the main and iframe |
| 7 | +* Less flickering and forced reflow on scrolling |
| 8 | + |
| 9 | +While we continue optimizing the layout code, we need to make sure that the new optimization won't lead to regression in above three aspects. Here is a list of existing optimziations we already have and we want to make sure they still perform well when updating layout code. |
| 10 | + |
| 11 | +## Executing code cell followed by markdown cells |
| 12 | + |
| 13 | +Code cell outputs and markdown cells are both rendered in the underling webview. When executing a code cell, the list view will |
| 14 | + |
| 15 | +1. Request cell output rendering in webview |
| 16 | +2. Cell output height change |
| 17 | + 2.1 in the webview, we set `maxHeight: 0; overflow: hidden` on the output DOM node, then it won't overlap with the following markdown cells |
| 18 | + 2.2 broadcast the height change to the list view in main frame |
| 19 | +3. List view received the height update request |
| 20 | + 3.1 Send acknowledge of the output height change to webview |
| 21 | + 3.2 Push down code cells below |
| 22 | + 3.3 Webview remove `maxHeight: 0` on the output DOM node |
| 23 | + |
| 24 | +Whether users would see flickering or overlap of outputs, monaco editor and markdown cells depends on the latency between 3.2 and 3.3. |
| 25 | + |
| 26 | +## Re-executing code cell followed by markdown cells |
| 27 | + |
| 28 | +Re-exuecting code cell consists of two steps: |
| 29 | + |
| 30 | +1. Remove old outputs, which will reset the output height to 0 |
| 31 | +2. Render new outputs, which will push elements below downwards |
| 32 | + |
| 33 | +The latency between 1 and 2 will cause the UI to flicker (as cells below this code cell will move upwards then downwards in a short period of time. However a lot of the time, we just tweak the code a bit and the outputs will have the same shape and very likely same rendered height, seeing the movement of cells below it is not pleasant. |
| 34 | + |
| 35 | +For example say we have code |
| 36 | + |
| 37 | +```py |
| 38 | +print(1) |
| 39 | +``` |
| 40 | + |
| 41 | +it will generate text output `1`. Updating the code to |
| 42 | + |
| 43 | +```py |
| 44 | +print(2) |
| 45 | +``` |
| 46 | + |
| 47 | +will genrate text output `2`. The re-rendering of the output is fast and we want to ensure the UI is stable in this scenario, to archive this: |
| 48 | + |
| 49 | +1. Clear existing output `1` |
| 50 | + 1.1 Remove the output DOM node, but we reserve the height of the output |
| 51 | + 1.2 In 200ms, we will reset the output height to `0`, unless there is a new output rendered |
| 52 | +2. Received new output |
| 53 | + 2.1 Re-render the new output |
| 54 | + 2.2 Calcuate the height of the new output, update layout |
| 55 | + |
| 56 | + |
| 57 | +If the new output is rendered within 200ms, users won't see the UI movement. |
| 58 | + |
| 59 | +## Scrolling |
| 60 | + |
| 61 | +Code cell outputs and markdown cells are rendered in the webview, which are async in nature. In order to have the cell outputs and markdown previews rendered when users scroll to them, we send rendering requests of cells in the next viewport when it's idle. Thus scrolling downwards is smoother. |
| 62 | + |
| 63 | +However, we **don't** warmup the previous viewport as the cell height change of previous viewport might trigger the flickering of markdown cells in current viewport. Before we optimize this, do not do any warmup of cells before current viewport. |
| 64 | + |
| 65 | + |
0 commit comments