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

feat(edgeless): add surface ref block #5013

Merged
merged 48 commits into from
Oct 31, 2023
Merged

feat(edgeless): add surface ref block #5013

merged 48 commits into from
Oct 31, 2023

Conversation

doouding
Copy link
Member

@doouding doouding commented Oct 13, 2023

Close #5010

Change

  • support edgeless content in page mode
  • add a new type of block affine:surface-ref to hold edgeless content in doc mode

Design

The affine:surface-ref block is designed to be the children of the affine:note block. The reference property is the id of the surface element/children that are expected to be displayed in doc mode.
In practice, any edgeless content can be displayed in doc mode through this block including shape, canvas text, brush, etc.

export type SurfaceRefProps = {
  reference: string;
};

export const SurfaceRefBlockSchema = defineBlockSchema({
  flavour: 'affine:surface-ref',
  props: () => ({
    reference: '',
  }),
  metadata: {
    version: 1,
    role: 'content',
    parent: ['affine:note'],
  },
});

export type SurfaceRefBlockModel = SchemaToModel<typeof SurfaceRefBlockSchema>;

Regarding the rendering implementation, the affine:surface-ref block holds a surface renderer to render surface elements and creates a portal-like renderer for the affine:note block to render notes inside a frame.
It will interpret the reference property and set the viewport according to the referenced element's XYWH property every time the frame changes.

export class SurfaceSyncBlockComponent extends BlockElement<SurfaceRefBlockModel> {
  private refreshViewport() {
    if (!this._referenceModel) {
      return;
    }

    this._surfaceRenderer.onResize();
    this._surfaceRenderer.setViewportByBound(
      Bound.fromXYWH(deserializeXYWH(this._referenceModel.xywh))
    );
  }

  override render() {
    return html`
      <div class="affine-surface-ref">
        <div class="surface-viewport">
          <div class="surface-block-portal">
            ${this._renderEdgelessNotes(notes)}
          </div>
          <div class="surface-canvas-container">
            <!-- attach surface canvas here -->
          </div>
        </div>
      </div>`;
  }
}

There are still some things need to be discuss:

  • The role of the affine:surface-ref is set to be hub, cause the content block cannot be the children of the root block. But the hub seems a little inappropriate.

Todo

  • Toolbar in doc mode
    • Caption support
    • Download/Copy as an image
  • Popup window (like image)
  • Paste surface content in doc mode
  • Toolbar in edgeless mode
    • Visible button in the toolbar
  • Fallback when content has been deleted

There are some remains:

  • Popup window should be implemented after bumping into AFFiNE
  • Copy-paste functionality will be tracked separately because the code is a bit confused
  • The surface-ref block can't be dragged using the drag-handler so far, it is necessary to consult with the designers.

@vercel
Copy link

vercel bot commented Oct 13, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
blocksuite ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 31, 2023 7:02am
1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
blocksuite-docs ⬜️ Ignored (Inspect) Visit Preview Oct 31, 2023 7:02am

@doouding
Copy link
Member Author

I just updated the design doc. Feel free to post any comments. @doodlewind

@doodlewind doodlewind changed the title feat: add surface sync block feat: add surface ref block Oct 17, 2023
@doodlewind doodlewind changed the title feat: add surface ref block feat(edgeless): add surface ref block Oct 17, 2023
@doodlewind doodlewind added the notable Major improvement worth emphasizing label Oct 17, 2023
Copy link
Member

@doodlewind doodlewind left a comment

Choose a reason for hiding this comment

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

The role of the affine:surface-ref is set to be hub, cause the content block cannot be the children of the root block. But the hub seems a little inappropriate.

@Saul-Mirone do you think we can break the previous assumption? In this case, affine:page could have both affine:note or affine:surface-ref as its direct children.

match: element => element.model.role === 'content',
match: element =>
element.model.role === 'content' ||
element.model.flavour === 'affine:surface-ref',
Copy link
Member

Choose a reason for hiding this comment

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

I think it's anti-pattern to hard-code affine related logic in the lit package. @Saul-Mirone any advice?

@@ -145,10 +145,14 @@ export class BlockElement<
return result;
}

calculatePath = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why you need to expose this method?

match: element => element.model.role === 'content',
match: element =>
element.model.role === 'content' ||
element.model.flavour === 'affine:surface-ref',
Copy link
Collaborator

Choose a reason for hiding this comment

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

We shouldn't sync this block for native selection. Consider handle the edge case in Delete keymap.

Copy link
Collaborator

@Saul-Mirone Saul-Mirone left a comment

Choose a reason for hiding this comment

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

We shouldn't hard code logic in lit and std package.

@Saul-Mirone
Copy link
Collaborator

It's okay to refactor later.

@Saul-Mirone Saul-Mirone added the housekeeping needed Contains workarounds that should be refactored label Oct 31, 2023
@doouding
Copy link
Member Author

FIXME comment has been added.

@doodlewind doodlewind merged commit 924fb68 into master Oct 31, 2023
18 checks passed
@doodlewind doodlewind deleted the feat/surface_in_doc branch October 31, 2023 08:24
@doodlewind
Copy link
Member

Thanks for the feat, looking forward to the upcoming housekeeping updates!

@doouding
Copy link
Member Author

I will add some tests later on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
housekeeping needed Contains workarounds that should be refactored notable Major improvement worth emphasizing
Projects
Archived in project
Archived in project
Development

Successfully merging this pull request may close these issues.

Support partially insert group and frame into doc mode
3 participants