fix(editor): fix color of the circle on loading icon (#12092)

* Unified loading icon
* Removed loading icon on image block
* Fixed color of circle on loading icon

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

- **New Features**
  - Icons in image fallback and loading states now automatically adapt to the current theme (light or dark mode) for a more consistent visual experience.

- **Style**
  - Updated loading, success, and error icons to support theming and improved their color assignments for better visibility in different themes.

- **Refactor**
  - Replaced static icon usage across several components with dynamic, theme-aware icons to ensure consistent appearance throughout the app.
  - Removed static SVG icon exports and replaced them with theme-aware icon functions for improved maintainability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fundon
2025-04-30 10:21:28 +00:00
parent bcb0e80a75
commit 8938da4c24
9 changed files with 38 additions and 96 deletions

View File

@@ -1,14 +1,14 @@
import type { ImageBlockModel } from '@blocksuite/affine-model';
import { getLoadingIconWith } from '@blocksuite/affine-components/icons';
import type { ColorScheme, ImageBlockModel } from '@blocksuite/affine-model';
import { humanFileSize } from '@blocksuite/affine-shared/utils';
import { WithDisposable } from '@blocksuite/global/lit';
import { BrokenImageIcon, ImageIcon } from '@blocksuite/icons/lit';
import { modelContext, ShadowlessElement } from '@blocksuite/std';
import { consume } from '@lit/context';
import { css, html } from 'lit';
import { property } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { FailedImageIcon, LoadedImageIcon, LoadingIcon } from '../styles.js';
export const SURFACE_IMAGE_CARD_WIDTH = 220;
export const SURFACE_IMAGE_CARD_HEIGHT = 122;
export const NOTE_IMAGE_CARD_WIDTH = 752;
@@ -62,7 +62,7 @@ export class ImageBlockFallbackCard extends WithDisposable(ShadowlessElement) {
`;
override render() {
const { mode, loading, error, model } = this;
const { theme, mode, loading, error, model } = this;
const isEdgeless = mode === 'edgeless';
const width = isEdgeless
@@ -82,10 +82,10 @@ export class ImageBlockFallbackCard extends WithDisposable(ShadowlessElement) {
});
const titleIcon = loading
? LoadingIcon
? getLoadingIconWith(theme)
: error
? FailedImageIcon
: LoadedImageIcon;
? BrokenImageIcon()
: ImageIcon();
const titleText = loading
? 'Loading image...'
@@ -125,6 +125,9 @@ export class ImageBlockFallbackCard extends WithDisposable(ShadowlessElement) {
@property({ attribute: false })
accessor mode!: 'page' | 'edgeless';
@property({ attribute: false })
accessor theme!: ColorScheme;
@consume({ context: modelContext })
accessor model!: ImageBlockModel;
}

View File

@@ -2,7 +2,10 @@ import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
import { whenHover } from '@blocksuite/affine-components/hover';
import { Peekable } from '@blocksuite/affine-components/peek';
import type { ImageBlockModel } from '@blocksuite/affine-model';
import { ToolbarRegistryIdentifier } from '@blocksuite/affine-shared/services';
import {
ThemeProvider,
ToolbarRegistryIdentifier,
} from '@blocksuite/affine-shared/services';
import { IS_MOBILE } from '@blocksuite/global/env';
import { BlockSelection } from '@blocksuite/std';
import { html } from 'lit';
@@ -111,6 +114,7 @@ export class ImageBlockComponent extends CaptionedBlockComponent<ImageBlockModel
position: 'relative',
width: '100%',
});
const theme = this.std.get(ThemeProvider).theme$.value;
return html`
<div class="affine-image-container" style=${containerStyleMap}>
@@ -120,7 +124,8 @@ export class ImageBlockComponent extends CaptionedBlockComponent<ImageBlockModel
html`<affine-image-fallback-card
.error=${this.error}
.loading=${this.loading}
.mode=${'page'}
.mode="${'page'}"
.theme=${theme}
></affine-image-fallback-card>`,
() => html`<affine-page-image .block=${this}></affine-page-image>`
)}

View File

@@ -1,6 +1,7 @@
import type { BlockCaptionEditor } from '@blocksuite/affine-components/caption';
import { Peekable } from '@blocksuite/affine-components/peek';
import type { ImageBlockModel } from '@blocksuite/affine-model';
import { ThemeProvider } from '@blocksuite/affine-shared/services';
import { GfxBlockComponent } from '@blocksuite/std';
import { css, html } from 'lit';
import { property, query, state } from 'lit/decorators.js';
@@ -85,6 +86,7 @@ export class ImageEdgelessBlockComponent extends GfxBlockComponent<ImageBlockMod
transform: `rotate(${rotate}deg)`,
transformOrigin: 'center',
});
const theme = this.std.get(ThemeProvider).theme$.value;
return html`
<div class="affine-image-container" style=${containerStyleMap}>
@@ -94,7 +96,8 @@ export class ImageEdgelessBlockComponent extends GfxBlockComponent<ImageBlockMod
html`<affine-image-fallback-card
.error=${this.error}
.loading=${this.loading}
.mode=${'page'}
.mode="${'edgeless'}"
.theme=${theme}
></affine-image-fallback-card>`,
() =>
html`<div class="resizable-img">

View File

@@ -5,7 +5,6 @@ export * from './image-block';
export * from './image-edgeless-block';
export * from './image-service';
export * from './image-spec';
export * from './styles';
export * from './turbo/image-layout-handler';
export * from './turbo/image-painter.worker';
export { addImages, downloadImageBlob, uploadBlobForImage } from './utils';

View File

@@ -1,72 +0,0 @@
import { html } from 'lit';
export const LoadingIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<style xmlns="http://www.w3.org/2000/svg">
.spinner {
transform-origin: center;
animation: spinner_animate 0.75s infinite linear;
}
@keyframes spinner_animate {
100% {
transform: rotate(360deg);
}
}
</style>
<path
d="M14.6666 7.99992C14.6666 11.6818 11.6818 14.6666 7.99992 14.6666C4.31802 14.6666 1.33325 11.6818 1.33325 7.99992C1.33325 4.31802 4.31802 1.33325 7.99992 1.33325C11.6818 1.33325 14.6666 4.31802 14.6666 7.99992ZM3.30003 7.99992C3.30003 10.5956 5.40424 12.6998 7.99992 12.6998C10.5956 12.6998 12.6998 10.5956 12.6998 7.99992C12.6998 5.40424 10.5956 3.30003 7.99992 3.30003C5.40424 3.30003 3.30003 5.40424 3.30003 7.99992Z"
fill-opacity="0.1"
/>
<path
d="M13.6833 7.99992C14.2263 7.99992 14.674 7.55732 14.5942 7.02014C14.5142 6.48171 14.3684 5.95388 14.1591 5.4487C13.8241 4.63986 13.333 3.90493 12.714 3.28587C12.0949 2.66682 11.36 2.17575 10.5511 1.84072C10.046 1.63147 9.51812 1.48564 8.9797 1.40564C8.44251 1.32583 7.99992 1.77351 7.99992 2.31659C7.99992 2.85967 8.44486 3.28962 8.9761 3.40241C9.25681 3.46201 9.53214 3.54734 9.79853 3.65768C10.3688 3.89388 10.8869 4.24008 11.3233 4.67652C11.7598 5.11295 12.106 5.63108 12.3422 6.20131C12.4525 6.4677 12.5378 6.74303 12.5974 7.02374C12.7102 7.55498 13.1402 7.99992 13.6833 7.99992Z"
fill="#1E96EB"
class="spinner"
/>
</svg>`;
export const LoadedImageIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M4 2.16667C2.98748 2.16667 2.16667 2.98748 2.16667 4V10.6667V12C2.16667 13.0125 2.98748 13.8333 4 13.8333H12C13.0125 13.8333 13.8333 13.0125 13.8333 12V9.33333V4C13.8333 2.98748 13.0125 2.16667 12 2.16667H4ZM3.16667 12V10.8738L6.07741 7.96303C6.40285 7.63759 6.93048 7.63759 7.25592 7.96303L8.97978 9.68689L10.3131 11.0202C10.5084 11.2155 10.825 11.2155 11.0202 11.0202C11.2155 10.825 11.2155 10.5084 11.0202 10.3131L10.0404 9.33333L10.7441 8.6297C11.0695 8.30426 11.5972 8.30426 11.9226 8.6297L12.8333 9.54044V12C12.8333 12.4602 12.4602 12.8333 12 12.8333H4C3.53976 12.8333 3.16667 12.4602 3.16667 12ZM7.96303 7.25592L9.33333 8.62623L10.037 7.92259C10.7529 7.20663 11.9137 7.20663 12.6297 7.92259L12.8333 8.12623V4C12.8333 3.53976 12.4602 3.16667 12 3.16667H4C3.53976 3.16667 3.16667 3.53976 3.16667 4V9.45956L5.3703 7.25592C6.08626 6.53996 7.24707 6.53996 7.96303 7.25592ZM9.33333 6C9.70152 6 10 5.70152 10 5.33333C10 4.96514 9.70152 4.66667 9.33333 4.66667C8.96514 4.66667 8.66667 4.96514 8.66667 5.33333C8.66667 5.70152 8.96514 6 9.33333 6Z"
fill="#77757D"
/>
</svg> `;
export const FailedImageIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M2.1665 4.00008C2.1665 2.98756 2.98732 2.16675 3.99984 2.16675H11.9998C13.0124 2.16675 13.8332 2.98756 13.8332 4.00008V7.33341C13.8332 7.60956 13.6093 7.83341 13.3332 7.83341C13.057 7.83341 12.8332 7.60956 12.8332 7.33341V4.00008C12.8332 3.53984 12.4601 3.16675 11.9998 3.16675H3.99984C3.5396 3.16675 3.1665 3.53984 3.1665 4.00008V9.45964L5.37014 7.256C6.0861 6.54004 7.2469 6.54004 7.96287 7.256L8.35339 7.64653C8.54865 7.84179 8.54865 8.15837 8.35339 8.35363C8.15813 8.5489 7.84155 8.5489 7.64628 8.35363L7.25576 7.96311C6.93032 7.63767 6.40268 7.63767 6.07725 7.96311L3.1665 10.8739V12.0001C3.1665 12.4603 3.5396 12.8334 3.99984 12.8334H7.33317C7.60931 12.8334 7.83317 13.0573 7.83317 13.3334C7.83317 13.6096 7.60931 13.8334 7.33317 13.8334H3.99984C2.98732 13.8334 2.1665 13.0126 2.1665 12.0001V4.00008Z"
fill="#77757D"
fill-opacity="0.6"
/>
<path
d="M9.99984 5.33341C9.99984 5.7016 9.70136 6.00008 9.33317 6.00008C8.96498 6.00008 8.6665 5.7016 8.6665 5.33341C8.6665 4.96522 8.96498 4.66675 9.33317 4.66675C9.70136 4.66675 9.99984 4.96522 9.99984 5.33341Z"
fill="#77757D"
fill-opacity="0.6"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.97962 8.97986C9.17488 8.7846 9.49146 8.7846 9.68672 8.97986L11.3332 10.6263L12.9796 8.97986C13.1749 8.7846 13.4915 8.7846 13.6867 8.97986C13.882 9.17512 13.882 9.49171 13.6867 9.68697L12.0403 11.3334L13.6867 12.9799C13.882 13.1751 13.882 13.4917 13.6867 13.687C13.4915 13.8822 13.1749 13.8822 12.9796 13.687L11.3332 12.0405L9.68672 13.687C9.49146 13.8822 9.17488 13.8822 8.97962 13.687C8.78435 13.4917 8.78435 13.1751 8.97962 12.9799L10.6261 11.3334L8.97962 9.68697C8.78435 9.49171 8.78435 9.17512 8.97962 8.97986Z"
fill="#77757D"
fill-opacity="0.6"
/>
</svg> `;