Skip to content

Commit

Permalink
fix: bookmark should show caption and loading state
Browse files Browse the repository at this point in the history
  • Loading branch information
AyushAgrawal-A2 committed Jan 25, 2024
1 parent 3a6ab05 commit dad51ab
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ export class EmbedCardCaption extends WithDisposable(ShadowlessElement) {
@pointerup=${stopPropagation}
@click=${stopPropagation}
@dblclick=${stopPropagation}
@paste=${stopPropagation}
@cut=${stopPropagation}
@copy=${stopPropagation}
@paste=${stopPropagation}
@keydown=${stopPropagation}
@keyup=${stopPropagation}
/>`;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import '../tooltip/tooltip.js';

import type { BlockStdScope } from '@blocksuite/block-std';
import { assertExists } from '@blocksuite/global/utils';
import type { EditorHost } from '@blocksuite/lit';
Expand Down
129 changes: 103 additions & 26 deletions packages/blocks/src/bookmark-block/bookmark-block.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import './components/bookmark-card.js';
import '../_common/components/button.js';
import './doc-bookmark-block.js';
import './edgeless-bookmark-block.js';
import '../_common/components/block-selection.js';
import '../_common/components/embed-card/embed-card-caption.js';
import '../_common/components/embed-card/embed-card-toolbar.js';

import { assertExists, Slot } from '@blocksuite/global/utils';
import { assertExists } from '@blocksuite/global/utils';
import { BlockElement } from '@blocksuite/lit';
import { html, render } from 'lit';
import { flip, offset } from '@floating-ui/dom';
import { html, nothing, render } from 'lit';
import { customElement, property, query } from 'lit/decorators.js';
import { ref } from 'lit/directives/ref.js';
import { styleMap } from 'lit/directives/style-map.js';

import type { EmbedCardCaption } from '../_common/components/embed-card/embed-card-caption.js';
import { HoverController } from '../_common/components/hover/controller.js';
import { EMBED_CARD_HEIGHT, EMBED_CARD_WIDTH } from '../_common/consts.js';
import { matchFlavours } from '../_common/utils/index.js';
import type { DragHandleOption } from '../page-block/widgets/drag-handle/config.js';
Expand All @@ -27,8 +31,6 @@ import {
BookmarkBlockSchema,
} from './bookmark-model.js';
import type { BookmarkService } from './bookmark-service.js';
import type { DocBookmarkBlockComponent } from './doc-bookmark-block.js';
import type { EdgelessBookmarkBlockComponent } from './edgeless-bookmark-block.js';
import { refreshBookmarkUrlData } from './utils.js';

@customElement('affine-bookmark')
Expand All @@ -45,10 +47,8 @@ export class BookmarkBlockComponent extends BlockElement<
@property({ attribute: false })
showCaption = false;

@query('affine-edgeless-bookmark, affine-doc-bookmark')
edgelessOrDocBookmark?:
| EdgelessBookmarkBlockComponent
| DocBookmarkBlockComponent;
@query('bookmark-card')
bookmarkCard!: HTMLElement;

@query('embed-card-caption')
captionElement!: EmbedCardCaption;
Expand All @@ -59,9 +59,10 @@ export class BookmarkBlockComponent extends BlockElement<
return this._isInSurface;
}

readonly slots = {
loadingUpdated: new Slot(),
};
get edgeless() {
if (this._isInSurface) return null;
return this.host.querySelector('affine-edgeless-page');
}

private _dragHandleOption: DragHandleOption = {
flavour: BookmarkBlockSchema.model.flavour,
Expand Down Expand Up @@ -157,7 +158,7 @@ export class BookmarkBlockComponent extends BlockElement<

return convertDragPreviewDocToEdgeless({
blockComponent,
cssSelector: '.affine-bookmark-card',
cssSelector: 'bookmark-card',
width: EMBED_CARD_WIDTH[style],
height: EMBED_CARD_HEIGHT[style],
...props,
Expand Down Expand Up @@ -198,7 +199,6 @@ export class BookmarkBlockComponent extends BlockElement<

this.disposables.add(
this.model.propsUpdated.on(({ key }) => {
this.edgelessOrDocBookmark?.requestUpdate();
if (key === 'url') {
this.refreshData();
}
Expand All @@ -210,19 +210,96 @@ export class BookmarkBlockComponent extends BlockElement<
);
}

override updated(changedProperties: Map<string, unknown>) {
super.updated(changedProperties);
if (changedProperties.has('loading')) {
this.slots.loadingUpdated.emit();
private _whenHover = new HoverController(this, ({ abortController }) => {
const selection = this.host.selection;
const textSelection = selection.find('text');
if (
!!textSelection &&
(!!textSelection.to || !!textSelection.from.length)
) {
return null;
}
}

override renderBlock() {
return html`${this.isInSurface
? html`<affine-edgeless-bookmark
const blockSelections = selection.filter('block');
if (
blockSelections.length > 1 ||
(blockSelections.length === 1 && blockSelections[0].path !== this.path)
) {
return null;
}

return {
template: html`
<style>
:host {
z-index: 1;
}
</style>
<embed-card-toolbar
.model=${this.model}
.block=${this}
></affine-edgeless-bookmark>`
: html`<affine-doc-bookmark .block=${this}></affine-doc-bookmark>`} `;
.host=${this.host}
.abortController=${abortController}
.std=${this.std}
></embed-card-toolbar>
`,
computePosition: {
referenceElement: this.bookmarkCard,
placement: 'top-end',
middleware: [flip(), offset(4)],
autoUpdate: true,
},
};
});

override renderBlock() {
const { caption, style } = this.model;

let containerStyleMap = styleMap({
position: 'relative',
width: '100%',
margin: '18px 0px',
});
if (this.isInSurface) {
const width = EMBED_CARD_WIDTH[style];
const height = EMBED_CARD_HEIGHT[style];
const bound = Bound.deserialize(
(this.edgeless?.service.getElementById(this.model.id) ?? this.model)
.xywh
);
const scaleX = bound.w / width;
const scaleY = bound.h / height;
containerStyleMap = styleMap({
width: `${width}px`,
height: `${height}px`,
transform: `scale(${scaleX}, ${scaleY})`,
transformOrigin: '0 0',
});
}

return html`<div
${this.isInSurface ? null : ref(this._whenHover.setReference)}
class="affine-bookmark-container"
style=${containerStyleMap}
>
<bookmark-card
.bookmark=${this}
.loading=${this.loading}
.loadingFailed=${this.loadingFailed}
></bookmark-card>
<embed-card-caption
.block=${this}
.display=${this.showCaption}
@blur=${() => {
if (!caption) this.showCaption = false;
}}
></embed-card-caption>
${this.selected?.is('block')
? html`<affine-block-selection></affine-block-selection>`
: nothing}
</div> `;
}
}

Expand Down
41 changes: 16 additions & 25 deletions packages/blocks/src/bookmark-block/components/bookmark-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
@property({ attribute: false })
bookmark!: BookmarkBlockComponent;

@property({ attribute: false })
loading!: boolean;

@property({ attribute: false })
loadingFailed!: boolean;

@state()
private _isSelected = false;

Expand All @@ -31,10 +37,6 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
})
);

this.disposables.add(
this.bookmark.slots.loadingUpdated.on(() => this.requestUpdate())
);

this._themeObserver.observe(document.documentElement);
this._themeObserver.on(() => this.requestUpdate());
this.disposables.add(() => this._themeObserver.dispose());
Expand All @@ -56,14 +58,6 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
selectionManager.setGroup('note', [blockSelection]);
}

private _openLink() {
let link = this.bookmark.model.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
window.open(link, '_blank');
}

private _handleClick() {
if (!this.bookmark.isInSurface) {
this._selectBlock();
Expand All @@ -72,18 +66,15 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {

private _handleDoubleClick(event: MouseEvent) {
event.stopPropagation();
this._openLink();
this.bookmark.open();
}

override render() {
const { icon, title, url, description, image, style } = this.bookmark.model;

const loading = this.bookmark.loading;
const loadingFailed = this.bookmark.loadingFailed;

const cardClassMap = classMap({
loading,
'loading-failed': loadingFailed,
loading: this.loading,
'loading-failed': this.loadingFailed,
[style]: true,
selected: this._isSelected,
});
Expand All @@ -92,10 +83,10 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
/^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:/\n]+)/im
)?.[1];

const titleText = loading
const titleText = this.loading
? 'Loading...'
: !title
? loadingFailed
? this.loadingFailed
? domainName ?? 'Link card'
: ''
: title;
Expand All @@ -107,7 +98,7 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
? 'svg+xml'
: icon?.split('.').pop();

const titleIcon = loading
const titleIcon = this.loading
? LoadingIcon
: icon
? html`<object
Expand All @@ -119,16 +110,16 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
</object>`
: WebIcon16;

const descriptionText = loading
const descriptionText = this.loading
? ''
: !description
? loadingFailed
? this.loadingFailed
? 'Failed to retrieve link information.'
: url
: description ?? '';

const bannerImage =
!loading && image
!this.loading && image
? html`<object type="image/webp" data=${image} draggable="false">
${EmbedCardBannerIcon}
</object>`
Expand All @@ -148,7 +139,7 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
<div class="affine-bookmark-content-description">
${descriptionText}
</div>
<div class="affine-bookmark-content-url" @click=${this._openLink}>
<div class="affine-bookmark-content-url" @click=${this.bookmark.open}>
<span>${url}</span>
<div class="affine-bookmark-content-url-icon">${OpenIcon}</div>
</div>
Expand Down
Loading

0 comments on commit dad51ab

Please sign in to comment.