fix(editor): footnote and citation icon url should be built with image proxy (#12169)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Improved how bookmark and footnote icons are displayed by routing image URLs through an image proxy service for enhanced reliability and consistency.

- **Refactor**
  - Adjusted the timing of service configuration for link previews and image proxies to occur after document initialization, ensuring more robust setup during content rendering.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
donteatfriedrice
2025-05-07 08:17:43 +00:00
parent 179701f587
commit 4c56b685a1
3 changed files with 31 additions and 16 deletions
@@ -6,6 +6,7 @@ import type {
BookmarkBlockModel, BookmarkBlockModel,
LinkPreviewData, LinkPreviewData,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { ImageProxyService } from '@blocksuite/affine-shared/adapters';
import { import {
DocModeProvider, DocModeProvider,
LinkPreviewerService, LinkPreviewerService,
@@ -119,6 +120,10 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
); );
} }
get imageProxyService() {
return this.std.get(ImageProxyService);
}
handleClick = (event: MouseEvent) => { handleClick = (event: MouseEvent) => {
event.stopPropagation(); event.stopPropagation();
@@ -135,9 +140,10 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
private readonly _renderCitationView = () => { private readonly _renderCitationView = () => {
const { url, footnoteIdentifier } = this.model.props; const { url, footnoteIdentifier } = this.model.props;
const { icon, title, description } = this.linkPreview$.value; const { icon, title, description } = this.linkPreview$.value;
const iconSrc = icon ? this.imageProxyService.buildUrl(icon) : undefined;
return html` return html`
<affine-citation-card <affine-citation-card
.icon=${icon} .icon=${iconSrc}
.citationTitle=${title || url} .citationTitle=${title || url}
.citationContent=${description} .citationContent=${description}
.citationIdentifier=${footnoteIdentifier} .citationIdentifier=${footnoteIdentifier}
@@ -4,6 +4,7 @@ import {
WebIcon16, WebIcon16,
} from '@blocksuite/affine-components/icons'; } from '@blocksuite/affine-components/icons';
import type { FootNote } from '@blocksuite/affine-model'; import type { FootNote } from '@blocksuite/affine-model';
import { ImageProxyService } from '@blocksuite/affine-shared/adapters';
import { import {
DocDisplayMetaProvider, DocDisplayMetaProvider,
LinkPreviewerService, LinkPreviewerService,
@@ -80,7 +81,10 @@ export class FootNotePopup extends SignalWatcher(WithDisposable(LitElement)) {
} }
const favicon = this._linkPreview$.value?.favicon; const favicon = this._linkPreview$.value?.favicon;
return favicon ? html`<img src=${favicon} alt="favicon" />` : WebIcon16; const imageSrc = favicon
? this.imageProxyService.buildUrl(favicon)
: undefined;
return imageSrc ? html`<img src=${imageSrc} alt="favicon" />` : WebIcon16;
} }
return undefined; return undefined;
}); });
@@ -190,6 +194,10 @@ export class FootNotePopup extends SignalWatcher(WithDisposable(LitElement)) {
`; `;
} }
get imageProxyService() {
return this.std.get(ImageProxyService);
}
@property({ attribute: false }) @property({ attribute: false })
accessor footnote!: FootNote; accessor footnote!: FootNote;
@@ -273,6 +273,21 @@ export class TextRenderer extends WithDisposable(ShadowlessElement) {
this._doc.readonly = true; this._doc.readonly = true;
this.requestUpdate(); this.requestUpdate();
if (this.state !== 'generating') { if (this.state !== 'generating') {
// LinkPreviewerService & ImageProxyService config should read from host settings
const linkPreviewerService =
this.host?.std.store.get(LinkPreviewerService);
const imageProxyService =
this.host?.std.store.get(ImageProxyService);
if (linkPreviewerService) {
this._doc
?.get(LinkPreviewerService)
.setEndpoint(linkPreviewerService.endpoint);
}
if (imageProxyService) {
this._doc
?.get(ImageProxyService)
.setImageProxyURL(imageProxyService.imageProxyURL);
}
this._clearTimer(); this._clearTimer();
} }
}) })
@@ -289,20 +304,6 @@ export class TextRenderer extends WithDisposable(ShadowlessElement) {
if (this.state === 'generating') { if (this.state === 'generating') {
this._timer = setInterval(this._updateDoc, 600); this._timer = setInterval(this._updateDoc, 600);
} }
// LinkPreviewerService & ImageProxyService config should read from host settings
const linkPreviewerService = this.host?.std.store.get(LinkPreviewerService);
const imageProxyService = this.host?.std.store.get(ImageProxyService);
if (linkPreviewerService) {
this._doc
?.get(LinkPreviewerService)
.setEndpoint(linkPreviewerService.endpoint);
}
if (imageProxyService) {
this._doc
?.get(ImageProxyService)
.setImageProxyURL(imageProxyService.imageProxyURL);
}
} }
private disposeDoc() { private disposeDoc() {