AFFiNE icon indicating copy to clipboard operation
AFFiNE copied to clipboard

Support subpage and bi-directional links

Open tzhangchi opened this issue 1 year ago • 4 comments

tzhangchi avatar Mar 06 '23 02:03 tzhangchi

Updated TODOs:

  • Rich text
    • [x] New rich text node (blot-like cursor behavior)
    • [x] [[ markdown shortcuts
  • Model layer
    • [x] API (events) for receiving linked page title change
    • [x] API for querying filtered page list inside workspace
    • [ ] Import from markdown
    • [x] Export to markdown and HTML
  • UI components
    • [x] Filtered page list popup UI
  • Misc
    • [ ] Clipboard support
    • [x] Multiple page testing in BlockSuite playground

To be clarified:

  • Behavior (fallback) state when linked page is deleted

Note:

  • Cross-workspace bi-directional link support is a non-goal.

doodlewind avatar Mar 08 '23 08:03 doodlewind

@lawvs

tzhangchi avatar Mar 14 '23 02:03 tzhangchi

Some design ideas related to subpage:

Basic Principles

  • Use the field pageMeta as the data source

For example:

<page title="page1" pageMeta={["page-id-foo", "bar"]}>
  <paragraph text={<>
      <page-ref type="subpage" link-id="page-id-foo">subpage text</page-ref>
      <page-ref type="bi-directional" link-id="foo">bi-directional link text</page-ref>
    </>}
  />
</page>

Scenario 1 - Add/Delete subpage by sidebar

  • Update pageMeta
  • If page1 is opened and page-ref node rendered
    • The page-ref can receive notification, then remove itself
  • Else do nothing
  • If someone opens the readonly page, the page-ref will check page.subpages and render nothing.
  • When the page1 opens and before page-ref rendered
    • page-ref can check pageMeta and then remove itself

Scenario 2 - Add/Delete subpage by operate text node

  • Update pageMeta
  • Add/Remove page-ref node

Scenario 3 - data out of sync 1

  • pageMeta is empty, but has a subpage node
    • It's expected scenario, the page-ref will remove itself before render

Options (happens when removing an unopened subpage from sidebar):

  • Not removing subpage link from page content immediately, lazy-remove it at next render -> may lead to side effect.
  • Try removing subpage link after page tree updated -> requires loading subdoc and may fail, also more time-costly.
image
<page title="page1" pageMeta={[]}>
  <paragraph text={<>
      <page-ref type="subpage" link-id="foo">subpage text</page-ref>
      <page-ref type="bi-directional" link-id="page-id-foo">bi-directional link text</page-ref>
    </>}
  />
</page>

Scenario 4 - data out of sync 2

  • pageMeta has some pages, but no corresponding page-ref text node
    • left side would have a ghost page, once remove it manually, it will return to normal

Happens when adding new subpage from sidebar, need similar options as Scenario 3.

<page title="page1" subpages={["page-id-foo"]}>
  <paragraph text="" />
</page>

Note: All of the above names are temporary.

lawvs avatar Mar 14 '23 04:03 lawvs

We need to maintain the page tree hierarchy in pageMeta, which is a common sub-doc across the workspace. In this case, we may not need another page-level field (page.subpage in CRDT model) marking the subpage relationship, only having the sys:refs: id[] property on the paragraph/list block that contains subpage could be adequate.

TODOs:

  • API for adding/querying/removing/updating subpage link in one page
  • API for querying all bi-directional links in one page

doodlewind avatar Mar 14 '23 05:03 doodlewind