refactor(editor): unify directories naming (#11516)

**Directory Structure Changes**

- Renamed multiple block-related directories by removing the "block-" prefix:
  - `block-attachment` → `attachment`
  - `block-bookmark` → `bookmark`
  - `block-callout` → `callout`
  - `block-code` → `code`
  - `block-data-view` → `data-view`
  - `block-database` → `database`
  - `block-divider` → `divider`
  - `block-edgeless-text` → `edgeless-text`
  - `block-embed` → `embed`
This commit is contained in:
Saul-Mirone
2025-04-07 12:34:40 +00:00
parent e1bd2047c4
commit 1f45cc5dec
893 changed files with 439 additions and 460 deletions
@@ -0,0 +1,13 @@
import type { ExtensionType } from '@blocksuite/store';
import { EmbedYoutubeBlockHtmlAdapterExtension } from './html.js';
import { EmbedYoutubeMarkdownAdapterExtension } from './markdown.js';
import { EmbedYoutubeBlockNotionHtmlAdapterExtension } from './notion-html.js';
import { EmbedYoutubeBlockPlainTextAdapterExtension } from './plain-text.js';
export const EmbedYoutubeBlockAdapterExtensions: ExtensionType[] = [
EmbedYoutubeBlockHtmlAdapterExtension,
EmbedYoutubeMarkdownAdapterExtension,
EmbedYoutubeBlockPlainTextAdapterExtension,
EmbedYoutubeBlockNotionHtmlAdapterExtension,
];
@@ -0,0 +1,51 @@
import { EmbedYoutubeBlockSchema } from '@blocksuite/affine-model';
import {
BlockHtmlAdapterExtension,
HastUtils,
} from '@blocksuite/affine-shared/adapters';
import { nanoid } from '@blocksuite/store';
import { createEmbedBlockHtmlAdapterMatcher } from '../../common/adapters/html.js';
export const embedYoutubeBlockHtmlAdapterMatcher =
createEmbedBlockHtmlAdapterMatcher(EmbedYoutubeBlockSchema.model.flavour, {
toMatch: o => HastUtils.isElement(o.node) && o.node.tagName === 'iframe',
toBlockSnapshot: {
enter: (o, context) => {
if (!HastUtils.isElement(o.node)) {
return;
}
const src = o.node.properties?.src;
if (typeof src !== 'string') {
return;
}
const { walkerContext } = context;
if (src.startsWith('https://www.youtube.com/embed/')) {
const videoId = src.substring(
'https://www.youtube.com/embed/'.length,
src.indexOf('?') !== -1 ? src.indexOf('?') : undefined
);
walkerContext
.openNode(
{
type: 'block',
id: nanoid(),
flavour: 'affine:embed-youtube',
props: {
url: `https://www.youtube.com/watch?v=${videoId}`,
},
children: [],
},
'children'
)
.closeNode();
}
},
},
});
export const EmbedYoutubeBlockHtmlAdapterExtension = BlockHtmlAdapterExtension(
embedYoutubeBlockHtmlAdapterMatcher
);
@@ -0,0 +1,4 @@
export * from './html.js';
export * from './markdown.js';
export * from './notion-html.js';
export * from './plain-text.js';
@@ -0,0 +1,10 @@
import { EmbedYoutubeBlockSchema } from '@blocksuite/affine-model';
import { BlockMarkdownAdapterExtension } from '@blocksuite/affine-shared/adapters';
import { createEmbedBlockMarkdownAdapterMatcher } from '../../common/adapters/markdown.js';
export const embedYoutubeBlockMarkdownAdapterMatcher =
createEmbedBlockMarkdownAdapterMatcher(EmbedYoutubeBlockSchema.model.flavour);
export const EmbedYoutubeMarkdownAdapterExtension =
BlockMarkdownAdapterExtension(embedYoutubeBlockMarkdownAdapterMatcher);
@@ -0,0 +1,14 @@
import { EmbedYoutubeBlockSchema } from '@blocksuite/affine-model';
import { BlockNotionHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters';
import { createEmbedBlockNotionHtmlAdapterMatcher } from '../../common/adapters/notion-html.js';
import { youtubeUrlRegex } from '../embed-youtube-model.js';
export const embedYoutubeBlockNotionHtmlAdapterMatcher =
createEmbedBlockNotionHtmlAdapterMatcher(
EmbedYoutubeBlockSchema.model.flavour,
youtubeUrlRegex
);
export const EmbedYoutubeBlockNotionHtmlAdapterExtension =
BlockNotionHtmlAdapterExtension(embedYoutubeBlockNotionHtmlAdapterMatcher);
@@ -0,0 +1,12 @@
import { EmbedYoutubeBlockSchema } from '@blocksuite/affine-model';
import { BlockPlainTextAdapterExtension } from '@blocksuite/affine-shared/adapters';
import { createEmbedBlockPlainTextAdapterMatcher } from '../../common/adapters/plain-text.js';
export const embedYoutubeBlockPlainTextAdapterMatcher =
createEmbedBlockPlainTextAdapterMatcher(
EmbedYoutubeBlockSchema.model.flavour
);
export const EmbedYoutubeBlockPlainTextAdapterExtension =
BlockPlainTextAdapterExtension(embedYoutubeBlockPlainTextAdapterMatcher);
@@ -0,0 +1,39 @@
import { toggleEmbedCardCreateModal } from '@blocksuite/affine-components/embed-card-modal';
import type { SlashMenuConfig } from '@blocksuite/affine-widget-slash-menu';
import { YoutubeDuotoneIcon } from '@blocksuite/icons/lit';
import { YoutubeVideoTooltip } from './tooltips';
export const embedYoutubeSlashMenuConfig: SlashMenuConfig = {
items: [
{
name: 'YouTube',
description: 'Embed a YouTube video.',
icon: YoutubeDuotoneIcon(),
tooltip: {
figure: YoutubeVideoTooltip,
caption: 'YouTube Video',
},
group: '4_Content & Media@6',
when: ({ model }) =>
model.doc.schema.flavourSchemaMap.has('affine:embed-youtube'),
action: ({ std, model }) => {
(async () => {
const { host } = std;
const parentModel = host.doc.getParent(model);
if (!parentModel) {
return;
}
const index = parentModel.children.indexOf(model) + 1;
await toggleEmbedCardCreateModal(
host,
'YouTube',
'The added YouTube video link will be displayed as an embed view.',
{ mode: 'page', parentModel, index }
);
if (model.text?.length === 0) std.store.deleteBlock(model);
})().catch(console.error);
},
},
],
};
File diff suppressed because one or more lines are too long
@@ -0,0 +1,42 @@
import { EdgelessClipboardConfig } from '@blocksuite/affine-block-surface';
import { type BlockSnapshot } from '@blocksuite/store';
export class EdgelessClipboardEmbedYoutubeConfig extends EdgelessClipboardConfig {
static override readonly key = 'affine:embed-youtube';
override createBlock(youtubeEmbed: BlockSnapshot): string | null {
if (!this.surface) return null;
const {
xywh,
style,
url,
caption,
videoId,
image,
title,
description,
creator,
creatorUrl,
creatorImage,
} = youtubeEmbed.props;
const embedYoutubeId = this.crud.addBlock(
'affine:embed-youtube',
{
xywh,
style,
url,
caption,
videoId,
image,
title,
description,
creator,
creatorUrl,
creatorImage,
},
this.surface.model.id
);
return embedYoutubeId;
}
}
@@ -0,0 +1,6 @@
import { toEdgelessEmbedBlock } from '../common/to-edgeless-embed-block.js';
import { EmbedYoutubeBlockComponent } from './embed-youtube-block.js';
export class EmbedEdgelessYoutubeBlockComponent extends toEdgelessEmbedBlock(
EmbedYoutubeBlockComponent
) {}
@@ -0,0 +1,225 @@
import { OpenIcon } from '@blocksuite/affine-components/icons';
import type {
EmbedYoutubeModel,
EmbedYoutubeStyles,
} from '@blocksuite/affine-model';
import { ThemeProvider } from '@blocksuite/affine-shared/services';
import { BlockSelection } from '@blocksuite/std';
import { html, nothing } from 'lit';
import { property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { styleMap } from 'lit/directives/style-map.js';
import { EmbedBlockComponent } from '../common/embed-block-element.js';
import { getEmbedCardIcons } from '../common/utils.js';
import { youtubeUrlRegex } from './embed-youtube-model.js';
import type { EmbedYoutubeBlockService } from './embed-youtube-service.js';
import { styles, YoutubeIcon } from './styles.js';
import { refreshEmbedYoutubeUrlData } from './utils.js';
export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
EmbedYoutubeModel,
EmbedYoutubeBlockService
> {
static override styles = styles;
override _cardStyle: (typeof EmbedYoutubeStyles)[number] = 'video';
open = () => {
let link = this.model.props.url;
if (!link.match(/^[a-zA-Z]+:\/\//)) {
link = 'https://' + link;
}
window.open(link, '_blank');
};
refreshData = () => {
refreshEmbedYoutubeUrlData(this, this.fetchAbortController.signal).catch(
console.error
);
};
private _handleDoubleClick(event: MouseEvent) {
event.stopPropagation();
this.open();
}
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
}
protected _handleClick(event: MouseEvent) {
event.stopPropagation();
this._selectBlock();
}
override connectedCallback() {
super.connectedCallback();
this._cardStyle = this.model.props.style;
if (!this.model.props.videoId) {
this.doc.withoutTransact(() => {
const url = this.model.props.url;
const urlMatch = url.match(youtubeUrlRegex);
if (urlMatch) {
const [, videoId] = urlMatch;
this.doc.updateBlock(this.model, {
videoId,
});
}
});
}
if (!this.model.props.description && !this.model.props.title) {
this.doc.withoutTransact(() => {
this.refreshData();
});
}
this.disposables.add(
this.model.propsUpdated.subscribe(({ key }) => {
this.requestUpdate();
if (key === 'url') {
this.refreshData();
}
})
);
matchMedia('print').addEventListener('change', () => {
this._showImage = matchMedia('print').matches;
});
}
override renderBlock() {
const {
image,
title = 'YouTube',
description,
creator,
creatorImage,
videoId,
} = this.model.props;
const loading = this.loading;
const theme = this.std.get(ThemeProvider).theme;
const { LoadingIcon, EmbedCardBannerIcon } = getEmbedCardIcons(theme);
const titleIcon = loading ? LoadingIcon : YoutubeIcon;
const titleText = loading ? 'Loading...' : title;
const descriptionText = loading ? null : description;
const bannerImage =
!loading && image
? html`<object type="image/webp" data=${image} draggable="false">
${EmbedCardBannerIcon}
</object>`
: EmbedCardBannerIcon;
const creatorImageEl =
!loading && creatorImage
? html`<object
type="image/webp"
data=${creatorImage}
draggable="false"
></object>`
: nothing;
return this.renderEmbed(
() => html`
<div
class=${classMap({
'affine-embed-youtube-block': true,
loading,
selected: this.selected$.value,
})}
style=${styleMap({
transformOrigin: '0 0',
})}
@click=${this._handleClick}
@dblclick=${this._handleDoubleClick}
>
<div class="affine-embed-youtube-video">
${videoId
? html`
<div class="affine-embed-youtube-video-iframe-container">
<iframe
id="ytplayer"
type="text/html"
src=${`https://www.youtube.com/embed/${videoId}`}
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
loading="lazy"
></iframe>
<!-- overlay to prevent the iframe from capturing pointer events -->
<div
class=${classMap({
'affine-embed-youtube-video-iframe-overlay': true,
hide: !this.showOverlay$.value,
})}
></div>
<img
class=${classMap({
'affine-embed-youtube-video-iframe-overlay': true,
'media-print': true,
hide: !this._showImage,
})}
src=${`https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`}
alt="YouTube Video"
loading="lazy"
/>
</div>
`
: bannerImage}
</div>
<div class="affine-embed-youtube-content">
<div class="affine-embed-youtube-content-header">
<div class="affine-embed-youtube-content-title-icon">
${titleIcon}
</div>
<div class="affine-embed-youtube-content-title-text">
${titleText}
</div>
<div class="affine-embed-youtube-content-creator-image">
${creatorImageEl}
</div>
<div class="affine-embed-youtube-content-creator-text">
${creator}
</div>
</div>
${loading
? html`<div
class="affine-embed-youtube-content-description"
></div>`
: descriptionText
? html`<div class="affine-embed-youtube-content-description">
${descriptionText}
</div>`
: nothing}
<div class="affine-embed-youtube-content-url" @click=${this.open}>
<span>www.youtube.com</span>
<div class="affine-embed-youtube-content-url-icon">
${OpenIcon}
</div>
</div>
</div>
</div>
`
);
}
@state()
private accessor _showImage = false;
@property({ attribute: false })
accessor loading = false;
}
@@ -0,0 +1,2 @@
export const youtubeUrlRegex: RegExp =
/(?:https?:\/\/)?(?:(?:www|m)\.)?youtu\.?be(?:\.com)?\/?.*(?:watch|embed)?(?:.*v=|v\/|\/)([\w-_]+)/;
@@ -0,0 +1,35 @@
import {
EmbedYoutubeBlockSchema,
type EmbedYoutubeModel,
EmbedYoutubeStyles,
} from '@blocksuite/affine-model';
import {
EmbedOptionConfig,
LinkPreviewerService,
} from '@blocksuite/affine-shared/services';
import { BlockService } from '@blocksuite/std';
import { youtubeUrlRegex } from './embed-youtube-model.js';
import { queryEmbedYoutubeData } from './utils.js';
export class EmbedYoutubeBlockService extends BlockService {
static override readonly flavour = EmbedYoutubeBlockSchema.model.flavour;
queryUrlData = (
embedYoutubeModel: EmbedYoutubeModel,
signal?: AbortSignal
) => {
return queryEmbedYoutubeData(
embedYoutubeModel,
this.doc.get(LinkPreviewerService),
signal
);
};
}
export const EmbedYoutubeBlockOptionConfig = EmbedOptionConfig({
flavour: EmbedYoutubeBlockSchema.model.flavour,
urlRegex: youtubeUrlRegex,
styles: EmbedYoutubeStyles,
viewType: 'embed',
});
@@ -0,0 +1,30 @@
import { EmbedYoutubeBlockSchema } from '@blocksuite/affine-model';
import { SlashMenuConfigExtension } from '@blocksuite/affine-widget-slash-menu';
import { BlockViewExtension, FlavourExtension } from '@blocksuite/std';
import type { ExtensionType } from '@blocksuite/store';
import { literal } from 'lit/static-html.js';
import { createBuiltinToolbarConfigExtension } from '../configs/toolbar';
import { EmbedYoutubeBlockAdapterExtensions } from './adapters/extension';
import { embedYoutubeSlashMenuConfig } from './configs/slash-menu';
import { EmbedYoutubeBlockComponent } from './embed-youtube-block';
import {
EmbedYoutubeBlockOptionConfig,
EmbedYoutubeBlockService,
} from './embed-youtube-service';
const flavour = EmbedYoutubeBlockSchema.model.flavour;
export const EmbedYoutubeBlockSpec: ExtensionType[] = [
FlavourExtension(flavour),
EmbedYoutubeBlockService,
BlockViewExtension(flavour, model => {
return model.parent?.flavour === 'affine:surface'
? literal`affine-embed-edgeless-youtube-block`
: literal`affine-embed-youtube-block`;
}),
EmbedYoutubeBlockAdapterExtensions,
EmbedYoutubeBlockOptionConfig,
createBuiltinToolbarConfigExtension(flavour, EmbedYoutubeBlockComponent),
SlashMenuConfigExtension('affine:embed-youtube', embedYoutubeSlashMenuConfig),
].flat();
@@ -0,0 +1,7 @@
export * from './adapters/index.js';
export * from './edgeless-clipboard-config';
export * from './embed-youtube-block.js';
export * from './embed-youtube-model.js';
export * from './embed-youtube-service.js';
export * from './embed-youtube-spec.js';
export { YoutubeIcon } from './styles.js';
@@ -0,0 +1,248 @@
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
import { css, html } from 'lit';
export const styles = css`
.affine-embed-youtube-block {
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
gap: 20px;
padding: 12px;
border-radius: 8px;
border: 1px solid var(--affine-background-tertiary-color);
opacity: var(--add, 1);
background: var(--affine-background-primary-color);
user-select: none;
}
.affine-embed-youtube-video {
flex-grow: 1;
width: 100%;
opacity: var(--add, 1);
}
.affine-embed-youtube-video img,
.affine-embed-youtube-video object,
.affine-embed-youtube-video svg {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 4px 4px var(--1, 0px) var(--1, 0px);
}
.affine-embed-youtube-video-iframe-container {
position: relative;
height: 100%;
}
.affine-embed-youtube-video-iframe-container > iframe {
width: 100%;
height: 100%;
border-radius: 4px 4px var(--1, 0px) var(--1, 0px);
}
.affine-embed-youtube-video-iframe-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.affine-embed-youtube-video-iframe-overlay.hide {
display: none;
}
.affine-embed-youtube-content {
display: block;
flex-direction: column;
width: 100%;
height: fit-content;
border-radius: var(--1, 0px);
opacity: var(--add, 1);
}
.affine-embed-youtube-content-header {
display: flex;
flex-direction: row;
gap: 8px;
align-items: center;
align-self: stretch;
padding: var(--1, 0px);
border-radius: var(--1, 0px);
opacity: var(--add, 1);
}
.affine-embed-youtube-content-title-icon {
display: flex;
width: 20px;
height: 20px;
justify-content: center;
align-items: center;
}
.affine-embed-youtube-content-title-icon img,
.affine-embed-youtube-content-title-icon object,
.affine-embed-youtube-content-title-icon svg {
width: 20px;
height: 20px;
fill: var(--affine-background-primary-color);
}
.affine-embed-youtube-content-title-text {
flex: 1 0 0;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
word-break: break-word;
overflow: hidden;
text-overflow: ellipsis;
color: var(--affine-text-primary-color);
font-family: var(--affine-font-family);
font-size: var(--affine-font-sm);
font-style: normal;
font-weight: 600;
line-height: 22px;
}
.affine-embed-youtube-content-creator-image {
display: flex;
width: 16px;
height: 16px;
flex-direction: column;
align-items: flex-start;
}
.affine-embed-youtube-content-creator-image img,
.affine-embed-youtube-content-creator-image object,
.affine-embed-youtube-content-creator-image svg {
width: 16px;
height: 16px;
border-radius: 50%;
fill: var(--affine-background-primary-color);
}
.affine-embed-youtube-content-creator-text {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
color: var(--affine-text-primary-color);
text-align: justify;
font-family: var(--affine-font-family);
font-size: var(--affine-font-xs);
font-style: normal;
font-weight: 400;
line-height: 20px;
}
.affine-embed-youtube-content-description {
height: 40px;
position: relative;
word-break: break-word;
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
color: var(--affine-text-primary-color);
font-family: var(--affine-font-family);
font-size: var(--affine-font-xs);
font-style: normal;
font-weight: 400;
line-height: 20px;
}
.affine-embed-youtube-content-description::after {
content: '...';
position: absolute;
right: 0;
bottom: 0;
background-color: var(--affine-background-primary-color);
}
.affine-embed-youtube-content-url {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 4px;
width: max-content;
max-width: 100%;
cursor: pointer;
}
.affine-embed-youtube-content-url > span {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
word-break: break-all;
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
color: ${unsafeCSSVarV2('icon/primary')};
font-family: var(--affine-font-family);
font-size: var(--affine-font-xs);
font-style: normal;
font-weight: 400;
line-height: 20px;
}
.affine-embed-youtube-content-url:hover > span {
color: var(--affine-link-color);
}
.affine-embed-youtube-content-url:hover .open-icon {
fill: var(--affine-link-color);
}
.affine-embed-youtube-content-url-icon {
display: flex;
align-items: center;
justify-content: center;
width: 12px;
height: 12px;
}
.affine-embed-youtube-content-url-icon svg {
height: 12px;
width: 12px;
fill: ${unsafeCSSVarV2('icon/primary')};
}
.affine-embed-youtube-block.loading {
.affine-embed-youtube-content-title-text {
color: var(--affine-placeholder-color);
}
}
.affine-embed-youtube-block.selected {
.affine-embed-youtube-content-url > span {
color: var(--affine-link-color);
}
.affine-embed-youtube-content-url .open-icon {
fill: var(--affine-link-color);
}
}
`;
export const YoutubeIcon = html`<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.5672 5.99344C17.4763 5.64032 17.2992 5.3184 17.0533 5.05972C16.8075 4.80104 16.5015 4.61464 16.1659 4.51907C14.9372 4.1665 9.99202 4.1665 9.99202 4.1665C9.99202 4.1665 5.04662 4.17718 3.81791 4.52974C3.48228 4.62532 3.1763 4.81173 2.93045 5.07042C2.6846 5.32911 2.50744 5.65105 2.41664 6.00417C2.04498 8.30113 1.90081 11.8012 2.42684 14.0062C2.51766 14.3594 2.69482 14.6813 2.94067 14.94C3.18652 15.1986 3.49249 15.385 3.82811 15.4806C5.05683 15.8332 10.0021 15.8332 10.0021 15.8332C10.0021 15.8332 14.9473 15.8332 16.176 15.4806C16.5116 15.385 16.8176 15.1986 17.0635 14.94C17.3093 14.6813 17.4865 14.3594 17.5773 14.0062C17.9693 11.706 18.0901 8.20821 17.5672 5.9935V5.99344Z"
fill="#FF0000"
/>
<path d="M8.33325 12.5L12.4999 10L8.33325 7.5V12.5Z" fill="white" />
</svg>`;
@@ -0,0 +1,114 @@
import type {
EmbedYoutubeBlockUrlData,
EmbedYoutubeModel,
} from '@blocksuite/affine-model';
import type { LinkPreviewerService } from '@blocksuite/affine-shared/services';
import { isAbortError } from '@blocksuite/affine-shared/utils';
import type { EmbedYoutubeBlockComponent } from './embed-youtube-block.js';
export async function queryEmbedYoutubeData(
embedYoutubeModel: EmbedYoutubeModel,
linkPreviewer: LinkPreviewerService,
signal?: AbortSignal
): Promise<Partial<EmbedYoutubeBlockUrlData>> {
const url = embedYoutubeModel.props.url;
const [videoOpenGraphData, videoOEmbedData] = await Promise.all([
linkPreviewer.query(url, signal),
queryYoutubeOEmbedData(url, signal),
]);
const youtubeEmbedData: Partial<EmbedYoutubeBlockUrlData> = {
...videoOpenGraphData,
...videoOEmbedData,
};
if (youtubeEmbedData.creatorUrl) {
const creatorOpenGraphData = await linkPreviewer.query(
youtubeEmbedData.creatorUrl,
signal
);
youtubeEmbedData.creatorImage = creatorOpenGraphData.image;
}
return youtubeEmbedData;
}
export async function queryYoutubeOEmbedData(
url: string,
signal?: AbortSignal
): Promise<Partial<EmbedYoutubeBlockUrlData>> {
let youtubeOEmbedData: Partial<EmbedYoutubeBlockUrlData> = {};
const oEmbedUrl = `https://youtube.com/oembed?url=${url}&format=json`;
const oEmbedResponse = await fetch(oEmbedUrl, { signal }).catch(() => null);
if (oEmbedResponse && oEmbedResponse.ok) {
const oEmbedJson = await oEmbedResponse.json();
const { title, author_name, author_url } = oEmbedJson;
youtubeOEmbedData = {
title,
creator: author_name,
creatorUrl: author_url,
};
}
return youtubeOEmbedData;
}
export async function refreshEmbedYoutubeUrlData(
embedYoutubeElement: EmbedYoutubeBlockComponent,
signal?: AbortSignal
): Promise<void> {
let image = null,
title = null,
description = null,
creator = null,
creatorUrl = null,
creatorImage = null;
try {
embedYoutubeElement.loading = true;
// TODO(@mirone): remove service
const queryUrlData = embedYoutubeElement.service?.queryUrlData;
if (!queryUrlData) {
console.error(
`Trying to refresh youtube url data, but the queryUrlData is not found.`
);
return;
}
const youtubeUrlData = await queryUrlData(
embedYoutubeElement.model,
signal
);
({
image = null,
title = null,
description = null,
creator = null,
creatorUrl = null,
creatorImage = null,
} = youtubeUrlData);
if (signal?.aborted) return;
embedYoutubeElement.doc.updateBlock(embedYoutubeElement.model, {
image,
title,
description,
creator,
creatorUrl,
creatorImage,
});
} catch (error) {
if (signal?.aborted || isAbortError(error)) return;
throw error;
} finally {
embedYoutubeElement.loading = false;
}
}