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(core): peek view api enhancements #7288

Merged
merged 1 commit into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/frontend/component/src/lit-react/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { createComponent as createReactComponentFromLit } from './create-component';
export * from './lit-portal';
export { toReactNode } from './to-react-node';
35 changes: 35 additions & 0 deletions packages/frontend/component/src/lit-react/to-react-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { LitElement, type TemplateResult } from 'lit';
import React, { createElement, type ReactNode } from 'react';

import { createComponent } from './create-component';

export class LitTemplateWrapper extends LitElement {
static override get properties() {
return {
template: { type: Object },
};
}
template: TemplateResult | null = null;
// do not enable shadow root
override createRenderRoot() {
return this;
}

override render() {
return this.template;
}
}

window.customElements.define('affine-lit-template-wrapper', LitTemplateWrapper);

const TemplateWrapper = createComponent({
elementClass: LitTemplateWrapper,
react: React,
});

export const toReactNode = (template?: TemplateResult | string): ReactNode => {
if (!template) return null;
return typeof template === 'string'
? template
: createElement(TemplateWrapper, { template });
};
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function AffinePageReference({
if (e.shiftKey && ref.current) {
e.preventDefault();
e.stopPropagation();
peekView.open(ref.current);
peekView.open(ref.current).catch(console.error);
return false; // means this click is handled
}
if (isInPeekView) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {
createReactComponentFromLit,
type ElementOrFactory,
Input,
notify,
toast,
type ToastOptions,
toReactNode,
type useConfirmModal,
} from '@affine/component';
import type {
Expand All @@ -27,47 +27,15 @@ import {
type RootService,
} from '@blocksuite/blocks';
import type { DocMode, DocService, DocsService } from '@toeverything/infra';
import { html, LitElement, type TemplateResult } from 'lit';
import { html, type TemplateResult } from 'lit';
import { customElement } from 'lit/decorators.js';
import { literal } from 'lit/static-html.js';
import React, { createElement, type ReactNode } from 'react';

const logger = new DebugLogger('affine::spec-patchers');

export type ReferenceReactRenderer = (
reference: AffineReference
) => React.ReactElement;

export class LitTemplateWrapper extends LitElement {
static override get properties() {
return {
template: { type: Object },
};
}
template: TemplateResult | null = null;
// do not enable shadow root
override createRenderRoot() {
return this;
}

override render() {
return this.template;
}
}

window.customElements.define('affine-lit-template-wrapper', LitTemplateWrapper);

const TemplateWrapper = createReactComponentFromLit({
elementClass: LitTemplateWrapper,
react: React,
});

const toReactNode = (template?: TemplateResult | string): ReactNode => {
if (!template) return null;
return typeof template === 'string'
? template
: createElement(TemplateWrapper, { template });
};
const logger = new DebugLogger('affine::spec-patchers');

function patchSpecService<Spec extends BlockSpec>(
spec: Spec,
Expand Down Expand Up @@ -274,10 +242,9 @@ export function patchPeekViewService(

patchSpecService(rootSpec, pageService => {
pageService.peekViewService = {
peek: (target: ActivePeekView['target']) => {
logger.debug('center peek', target);
service.peekView.open(target);
return Promise.resolve();
peek: (target: ActivePeekView['target'], template?: TemplateResult) => {
logger.debug('center peek', target, template);
return service.peekView.open(target, template);
},
};
});
Expand Down
35 changes: 18 additions & 17 deletions packages/frontend/core/src/modules/peek-view/entities/peek-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import {
type SurfaceRefBlockComponent,
type SurfaceRefBlockModel,
} from '@blocksuite/blocks';
import type { BlockModel } from '@blocksuite/store';
import { type DocMode, Entity, LiveData } from '@toeverything/infra';
import type { TemplateResult } from 'lit';
import { firstValueFrom, map, race } from 'rxjs';

import { resolveLinkToDoc } from '../../navigation';

export type PeekViewTarget =
| HTMLElement
Expand All @@ -24,13 +29,10 @@ export type DocPeekViewInfo = {

export type ActivePeekView = {
target: PeekViewTarget;
info: DocPeekViewInfo;
info?: DocPeekViewInfo;
template?: TemplateResult;
};

import type { BlockModel } from '@blocksuite/store';

import { resolveLinkToDoc } from '../../navigation';

const EMBED_DOC_FLAVOURS = [
'affine:embed-linked-doc',
'affine:embed-synced-doc',
Expand All @@ -50,8 +52,8 @@ const isSurfaceRefModel = (

function resolvePeekInfoFromPeekTarget(
peekTarget?: PeekViewTarget
): DocPeekViewInfo | null {
if (!peekTarget) return null;
): DocPeekViewInfo | undefined {
if (!peekTarget) return;
if (peekTarget instanceof AffineReference) {
if (peekTarget.refMeta) {
return {
Expand Down Expand Up @@ -91,14 +93,10 @@ function resolvePeekInfoFromPeekTarget(
blockId: peekTarget.blockId,
};
}
return null;
return;
}

export class PeekViewEntity extends Entity {
constructor() {
super();
}

private readonly _active$ = new LiveData<ActivePeekView | null>(null);
private readonly _show$ = new LiveData<boolean>(false);

Expand All @@ -108,14 +106,17 @@ export class PeekViewEntity extends Entity {
.distinctUntilChanged();

// return true if the peek view will be handled
open = (target: ActivePeekView['target']) => {
open = async (
target: ActivePeekView['target'],
template?: TemplateResult
) => {
const resolvedInfo = resolvePeekInfoFromPeekTarget(target);
if (!resolvedInfo) {
return false;
if (!resolvedInfo && !template) {
return;
}
this._active$.next({ target, info: resolvedInfo });
this._active$.next({ target, info: resolvedInfo, template });
this._show$.next(true);
return true;
return firstValueFrom(race(this._active$, this.show$).pipe(map(() => {})));
};

close = () => {
Expand Down
Loading
Loading