Commit Graph

702 Commits

Author SHA1 Message Date
akumatus
ee337a16af feat(core): support collection search for ai chat (#10987)
Close [BS-2787](https://linear.app/affine-design/issue/BS-2787).
Close [BS-2788](https://linear.app/affine-design/issue/BS-2788).

![截屏2025-03-19 14.15.54.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/573450f9-791b-4cd9-9c75-df93bf9966b4.png)
2025-03-20 00:34:12 +00:00
akumatus
47206b8d47 feat(core): support tag search for ai chat (#10965)
Close [BS-2785](https://linear.app/affine-design/issue/BS-2785).
Close [BS-2786](https://linear.app/affine-design/issue/BS-2786).

![截屏2025-03-18 21.22.34.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/sJGviKxfE3Ap685cl5bj/fae7216a-0402-4f14-a63c-b89f5223fc72.png)
2025-03-19 04:22:11 +00:00
pengx17
6b73e8ebb5 fix(core): allow unused blobs to preview in new tab (#10874)
fix AF-2330
2025-03-19 02:40:06 +00:00
JimmFly
70fe521300 fix(core): copy link should not have mode (#10904) 2025-03-19 01:50:34 +00:00
zzj3720
3939cc1c52 feat(editor): support file column and member column for database block (#10932)
close: BS-2630, BS-2631, BS-2629, BS-2632, BS-2635
2025-03-18 14:51:45 +00:00
CatsJuice
ff8c3d1cee feat(core): intilize integration module and basic readwise impl (#10726)
close AF-2257, AF-2261, AF-2260, AF-2259

### Feat

- New `Integration` Module
- Basic Readwise integration
  - connect
  - import
  - disconnect
- Common Integration UI
- Common Integration Writer  (Transform markdown to AFFiNE Doc)

### Not Implemented

>  will be implemented in down-stack
- delete docs when disconnect
- readwise settiing UI
- integration property rendering
2025-03-18 08:13:58 +00:00
EYHN
b401012d85 feat(core): user service loading state (#10922) 2025-03-17 09:28:25 +00:00
Saul-Mirone
26285f7dcb feat(editor): unify block props api (#10888)
Closes: [BS-2707](https://linear.app/affine-design/issue/BS-2707/统一使用props获取和更新block-prop)
2025-03-16 05:48:34 +00:00
EYHN
05200ad7b7 feat(nbstore): add blob sync storage (#10752) 2025-03-14 18:05:54 +08:00
EYHN
a2eb3fe1b2 feat(core): add notification service (#10855) 2025-03-14 09:32:10 +00:00
EYHN
f3ef9c4415 feat(nbstore): rename SyncStorage to DocSyncStorage (#10751) 2025-03-14 06:25:26 +00:00
JimmFly
0c9591f08e feat(core): add an entry for admin panel (#10813)
![CleanShot 2025-03-13 at 13 02 25@2x](https://github.com/user-attachments/assets/82f50a5b-f079-4c64-a3fa-6554735bea82)
2025-03-13 10:46:26 +00:00
forehalo
7100d87efe chore(core): doc role telemetry (#10822) 2025-03-13 08:15:46 +00:00
Saul-Mirone
250f3f1efd feat(editor): add isLocal flag in blockUpdated subject (#10799) 2025-03-13 05:33:06 +00:00
donteatfriedrice
d2c62602a4 feat(editor): support embed iframe block (#10740)
To close:
[BS-2660](https://linear.app/affine-design/issue/BS-2660/slash-menu-支持-iframe-embed)
[BS-2661](https://linear.app/affine-design/issue/BS-2661/iframe-embed-block-model-and-block-component)
[BS-2662](https://linear.app/affine-design/issue/BS-2662/iframe-embed-block-toolbar)
[BS-2768](https://linear.app/affine-design/issue/BS-2768/iframe-embed-block-loading-和-error-态)
[BS-2670](https://linear.app/affine-design/issue/BS-2670/iframe-embed-block-导出)

# PR Description

# Add Embed Iframe Block Support

## Overview

This PR introduces a new `EmbedIframeBlock` to enhance content embedding capabilities within our editor. This block allows users to seamlessly embed external content from various providers (Google Drive, Spotify, etc.) directly into their docs.

## New Blocks

### EmbedIframeBlock

The core block that renders embedded iframe content. This block:

* Displays external content within a secure iframe
* Handles loading states with visual feedback
* Provides error handling with edit and retry options
* Supports customization of width, height, and other iframe attributes

### Supporting Components

* **EmbedIframeCreateModal**: Modal interface for creating new iframe embeds
* **EmbedIframeLinkEditPopup**: UI for editing existing embed links
* **EmbedIframeLoadingCard**: Visual feedback during content loading
* **EmbedIframeErrorCard**: Error handling with retry functionality

## New Store Extensions

### EmbedIframeConfigExtension

This extension provides configuration for different embed providers:

```typescript
/**
 * The options for the iframe
 * @example
 * {
 *   defaultWidth: '100%',
 *   defaultHeight: '152px',
 *   style: 'border-radius: 8px;',
 *   allow: 'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture',
 * }
 * =>
 * <iframe
 *   width="100%"
 *   height="152px"
 *   style="border-radius: 8px;"
 *   allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
 * ></iframe>
 */
export type IframeOptions = {
  defaultWidth?: string;
  defaultHeight?: string;
  style?: string;
  referrerpolicy?: string;
  scrolling?: boolean;
  allow?: string;
  allowFullscreen?: boolean;
};

/**
 * Define the config of an embed iframe block provider
 */
export type EmbedIframeConfig = {
  /**
   * The name of the embed iframe block provider
   */
  name: string;
  /**
   * The function to match the url
   */
  match: (url: string) => boolean;
  /**
   * The function to build the oEmbed URL for fetching embed data
   */
  buildOEmbedUrl: (url: string) => string | undefined;
  /**
   * Use oEmbed URL directly as iframe src without fetching oEmbed data
   */
  useOEmbedUrlDirectly: boolean;
  /**
   * The options for the iframe
   */
  options?: IframeOptions;
};

export const EmbedIframeConfigIdentifier =
  createIdentifier<EmbedIframeConfig>('EmbedIframeConfig');

export function EmbedIframeConfigExtension(
  config: EmbedIframeConfig
): ExtensionType & {
  identifier: ServiceIdentifier<EmbedIframeConfig>;
} {
  const identifier = EmbedIframeConfigIdentifier(config.name);
  return {
    setup: di => {
      di.addImpl(identifier, () => config);
    },
    identifier,
  };
}
```

**example:**

```typescript
//  blocksuite/affine/blocks/block-embed/src/embed-iframe-block/configs/providers/spotify.ts

const SPOTIFY_DEFAULT_WIDTH = '100%';
const SPOTIFY_DEFAULT_HEIGHT = '152px';

// https://developer.spotify.com/documentation/embeds/reference/oembed
const spotifyEndpoint = 'https://open.spotify.com/oembed';

const spotifyUrlValidationOptions: EmbedIframeUrlValidationOptions = {
  protocols: ['https:'],
  hostnames: ['open.spotify.com', 'spotify.link'],
};

const spotifyConfig = {
  name: 'spotify',
  match: (url: string) =>
    validateEmbedIframeUrl(url, spotifyUrlValidationOptions),
  buildOEmbedUrl: (url: string) => {
    const match = validateEmbedIframeUrl(url, spotifyUrlValidationOptions);
    if (!match) {
      return undefined;
    }
    const encodedUrl = encodeURIComponent(url);
    const oEmbedUrl = `${spotifyEndpoint}?url=${encodedUrl}`;
    return oEmbedUrl;
  },
  useOEmbedUrlDirectly: false,
  options: {
    defaultWidth: SPOTIFY_DEFAULT_WIDTH,
    defaultHeight: SPOTIFY_DEFAULT_HEIGHT,
    allow:
      'autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture',
    style: 'border-radius: 12px;',
    allowFullscreen: true,
  },
};

// add the config extension to store
export const SpotifyEmbedConfig = EmbedIframeConfigExtension(spotifyConfig);
```

**Key features:**

* Provider registration and discovery
* URL pattern matching
* Provider-specific embed options (width, height, features)

### EmbedIframeService

This service provides abilities to handle URL validation, data fetching, and block creation

**Type:**

```typescript
/**
 * Service for handling embeddable URLs
 */
export interface EmbedIframeProvider {
  /**
   * Check if a URL can be embedded
   * @param url URL to check
   * @returns true if the URL can be embedded, false otherwise
   */
  canEmbed: (url: string) => boolean;

  /**
   * Build a API URL for fetching embed data
   * @param url URL to build API URL
   * @returns API URL if the URL can be embedded, undefined otherwise
   */
  buildOEmbedUrl: (url: string) => string | undefined;

  /**
   * Get the embed iframe config
   * @param url URL to get embed iframe config
   * @returns Embed iframe config if the URL can be embedded, undefined otherwise
   */
  getConfig: (url: string) => EmbedIframeConfig | undefined;

  /**
   * Get embed iframe data
   * @param url URL to get embed iframe data
   * @returns Embed iframe data if the URL can be embedded, undefined otherwise
   */
  getEmbedIframeData: (url: string) => Promise<EmbedIframeData | null>;

  /**
   * Parse an embeddable URL and add an EmbedIframeBlock to doc
   * @param url Original url to embed
   * @param parentId Parent block ID
   * @param index Optional index to insert at
   * @returns Created block id if successful, undefined if the URL cannot be embedded
   */
  addEmbedIframeBlock: (
    props: Partial<EmbedIframeBlockProps>,
    parentId: string,
    index?: number
  ) => string | undefined;
}
```

**Implemetation:**

```typescript
export class EmbedIframeService
  extends StoreExtension
  implements EmbedIframeProvider
{
  static override key = 'embed-iframe-service';

  private readonly _configs: EmbedIframeConfig[];

  constructor(store: Store) {
    super(store);
    this._configs = Array.from(
      store.provider.getAll(EmbedIframeConfigIdentifier).values()
    );
  }

  canEmbed = (url: string): boolean => {
    return this._configs.some(config => config.match(url));
  };

  buildOEmbedUrl = (url: string): string | undefined => {
    return this._configs.find(config => config.match(url))?.buildOEmbedUrl(url);
  };

  getConfig = (url: string): EmbedIframeConfig | undefined => {
    return this._configs.find(config => config.match(url));
  };

  getEmbedIframeData = async (
    url: string,
    signal?: AbortSignal
  ): Promise<EmbedIframeData | null> => {
    try {
      const config = this._configs.find(config => config.match(url));
      if (!config) {
        return null;
      }

      const oEmbedUrl = config.buildOEmbedUrl(url);
      if (!oEmbedUrl) {
        return null;
      }

      // if the config useOEmbedUrlDirectly is true, return the url directly as iframe_url
      if (config.useOEmbedUrlDirectly) {
        return {
          iframe_url: oEmbedUrl,
        };
      }

      // otherwise, fetch the oEmbed data
      const response = await fetch(oEmbedUrl, { signal });
      if (!response.ok) {
        console.warn(
          `Failed to fetch oEmbed data: ${response.status} ${response.statusText}`
        );
        return null;
      }

      const data = await response.json();
      return data as EmbedIframeData;
    } catch (error) {
      if (error instanceof Error && error.name !== 'AbortError') {
        console.error('Error fetching embed iframe data:', error);
      }
      return null;
    }
  };

  addEmbedIframeBlock = (
    props: Partial<EmbedIframeBlockProps>,
    parentId: string,
    index?: number
  ): string | undefined => {
    const blockId = this.store.addBlock(
      'affine:embed-iframe',
      props,
      parentId,
      index
    );
    return blockId;
  };
}
```

**Usage:**

```typescript
// Usage example
const embedIframeService = this.std.get(EmbedIframeService);

// Check if a URL can be embedded
const canEmbed = embedIframeService.canEmbed(url);

// Get embed data for a URL
const embedData = await embedIframeService.getEmbedIframeData(url);

// Add an embed iframe block to the document
const block = embedIframeService.addEmbedIframeBlock({
  url,
  iframeUrl: embedData.iframe_url,
  title: embedData.title,
  description: embedData.description
}, parentId, index);
```

**Key features:**

* URL validation and transformation
* Provider-specific data fetching
* Block creation and management

## Adaptations

### Toolbar Integration

Added toolbar actions for embedded content:

* Copy link
* Edit embed title and description
* Toggle between inline/card views
* Add caption
* And more

### Slash Menu Integration

Added a new slash menu option for embedding content:

* Embed item for inserting embed iframe block
* Conditional rendering based on feature flags

### Adapters

Implemented adapters for various formats:

* **HTML Adapter**: Exports embed original urls as html links
* **Markdown Adapter**: Exports embed original urls as markdown links
* **Plain Text Adapter**: Exports embed original urls as link text

## To Be Continued:
- [ ] **UI Optimization**
- [ ] **Edgeless Mode Support**
- [ ] **Mobile Support**
2025-03-13 04:11:46 +00:00
EYHN
86729fb447 feat(core): adjust web clipper page (#10779) 2025-03-13 10:59:50 +08:00
fengmk2
3417cc5dc1 fix(core): handle Content-Type with charset in fetch error handling (#10777) 2025-03-12 09:56:41 +00:00
fengmk2
43712839fd refactor(server): improve magic link login flow (#10736) 2025-03-12 15:27:36 +08:00
fengmk2
867ae7933f refactor(server): improve oauth login flow (#10648)
close CLOUD-145
2025-03-12 15:27:36 +08:00
EYHN
4b5d1de206 feat(core): add blocksuite writer info service (#10754) 2025-03-12 05:02:04 +00:00
Mirone
cd63e0ed8b feat(editor): replace slot with rxjs subject (#10768) 2025-03-12 11:29:24 +09:00
EYHN
ea07aa8607 feat(core): add notification list (#10480) 2025-03-11 06:23:33 +00:00
Saul-Mirone
ec709925ee refactor(editor): orgnize exports (#10709) 2025-03-10 02:04:01 +00:00
Saul-Mirone
12bc142809 refactor(editor): remove blocks package (#10708) 2025-03-09 05:44:26 +00:00
EYHN
4677049b5c feat(core): add public user service (#10695) 2025-03-07 08:00:27 +00:00
forehalo
e02fb4fa94 refactor(core): standardize frontend error handling (#10667) 2025-03-06 13:10:18 +00:00
Saul-Mirone
84e2dda3f8 refactor(editor): separate lit and slot in global (#10666) 2025-03-06 10:24:59 +00:00
EYHN
5c8b81581c feat(core): doc level awareness (#10646) 2025-03-06 06:05:45 +00:00
liuyi
7e61a0b2fc refactor(graphql): codegen (#10626) 2025-03-06 12:06:19 +08:00
CatsJuice
6b08e3f5d4 feat(core): support create new template in starter-bar (#10570) 2025-03-06 02:05:29 +00:00
EYHN
0015bfbaf2 refactor(core): adjust sentry config (#10631) 2025-03-05 11:18:06 +00:00
JimmFly
bb4240f6ef fix(core): add missing control of modifyDocDefaultRole track event (#10625) 2025-03-05 11:02:45 +00:00
Saul-Mirone
7e39893aac refactor(editor): remove assert functions (#10629) 2025-03-05 10:20:02 +00:00
EYHN
201c3438ba feat(core): add user list service for blocksuite (#10627) 2025-03-05 10:06:14 +00:00
pengx17
47d01f5f66 fix(core): db backlink infinite query issue (#10628)
fix AF-2301
2025-03-05 09:43:05 +00:00
Flrande
bd62634a76 feat(editor): add callout block (#10563)
- Add `CalloutBlockModel `
- Implement `CalloutBlockComponent `
- Integrate with slash menu (/)
2025-03-05 09:28:51 +00:00
EYHN
61635aa77a feat(core): add clipper import interface (#10619) 2025-03-05 04:22:03 +00:00
EYHN
4daa763c95 fix(core): fix table text content search (#10488) 2025-03-05 04:06:44 +00:00
Saul-Mirone
b8ecfbdae6 refactor(editor): remove assertExists (#10615) 2025-03-05 00:13:08 +00:00
Saul-Mirone
66d9d576e0 refactor(editor): add gfx entry in bs global package (#10612) 2025-03-04 12:46:50 +00:00
doodlewind
c418e89fb9 chore(editor): add feature flag entry for testing turbo renderer (#10581)
The debug pane will be displayed once the `enable_turbo_renderer` feature flag is enabled.

![image.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/lEGcysB4lFTEbCwZ8jMv/c1ba558a-2d84-403c-aa81-864b0338c861.png)
2025-03-04 05:38:44 +00:00
Saul-Mirone
fdde818ddd feat(editor): add block meta feature flag (#10548) 2025-03-03 01:45:33 +00:00
Saul-Mirone
f23f29610c refactor(editor): remove stable feature flags (#10547) 2025-03-02 08:41:12 +00:00
renovate
7227b7f8f6 chore: bump up oxlint version to v0.15.12 (#10206)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [oxlint](https://oxc.rs) ([source](https://redirect.github.com/oxc-project/oxc/tree/HEAD/npm/oxlint)) | [`0.15.10` -> `0.15.12`](https://renovatebot.com/diffs/npm/oxlint/0.15.10/0.15.12) | [![age](https://developer.mend.io/api/mc/badges/age/npm/oxlint/0.15.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/oxlint/0.15.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/oxlint/0.15.10/0.15.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/oxlint/0.15.10/0.15.12?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>oxc-project/oxc (oxlint)</summary>

### [`v0.15.12`](https://redirect.github.com/oxc-project/oxc/releases/tag/oxlint_v0.15.12): oxlint v0.15.12

[Compare Source](https://redirect.github.com/oxc-project/oxc/compare/oxlint_v0.15.11...oxlint_v0.15.12)

#### \[0.15.12] - 2025-02-24

##### Features

-   [`914dd46`](https://redirect.github.com/oxc-project/oxc/commit/914dd46) linter: Add eslint/max-depth ([#&#8203;9173](https://redirect.github.com/oxc-project/oxc/issues/9173)) (ikkz)
-   [`0b08159`](https://redirect.github.com/oxc-project/oxc/commit/0b08159) linter: Add eslint/max-lines-per-function ([#&#8203;9161](https://redirect.github.com/oxc-project/oxc/issues/9161)) (ikkz)
-   [`cc8dd48`](https://redirect.github.com/oxc-project/oxc/commit/cc8dd48) linter: Add unicorn/no-invalid-fetch-options rule ([#&#8203;9212](https://redirect.github.com/oxc-project/oxc/issues/9212)) (Mikhail Baev)
-   [`af13b1b`](https://redirect.github.com/oxc-project/oxc/commit/af13b1b) linter: Promote `eslint/no-eval` to `correctness` ([#&#8203;9231](https://redirect.github.com/oxc-project/oxc/issues/9231)) (dalaoshu)
-   [`542bbd7`](https://redirect.github.com/oxc-project/oxc/commit/542bbd7) linter: Support `import-x` plugin name ([#&#8203;9074](https://redirect.github.com/oxc-project/oxc/issues/9074)) (Sysix)
-   [`d266c29`](https://redirect.github.com/oxc-project/oxc/commit/d266c29) linter: Add eslint/max-nested-callbacks ([#&#8203;9172](https://redirect.github.com/oxc-project/oxc/issues/9172)) (ikkz)
-   [`86795d0`](https://redirect.github.com/oxc-project/oxc/commit/86795d0) linter: Implement grouped-accessor-pairs ([#&#8203;9065](https://redirect.github.com/oxc-project/oxc/issues/9065)) (yefan)
-   [`d70bad3`](https://redirect.github.com/oxc-project/oxc/commit/d70bad3) linter: Add eslint/no-unneeded-ternary rule ([#&#8203;9160](https://redirect.github.com/oxc-project/oxc/issues/9160)) (Cédric DIRAND)
-   [`4bd86e6`](https://redirect.github.com/oxc-project/oxc/commit/4bd86e6) linter: Add `fixer` for `unicorn/catch-error-name` ([#&#8203;9165](https://redirect.github.com/oxc-project/oxc/issues/9165)) (dalaoshu)

##### Bug Fixes

-   [`94bd2d8`](https://redirect.github.com/oxc-project/oxc/commit/94bd2d8) language_server: Fix `clippy::significant_drop_in_scrutinee` warning ([#&#8203;9234](https://redirect.github.com/oxc-project/oxc/issues/9234)) (Boshen)
-   [`69091c0`](https://redirect.github.com/oxc-project/oxc/commit/69091c0) linter: Correct default for `eslint/no-eval` ([#&#8203;9312](https://redirect.github.com/oxc-project/oxc/issues/9312)) (dalaoshu)
-   [`3031845`](https://redirect.github.com/oxc-project/oxc/commit/3031845) linter: Add option "allowTypeImports" for rule "no-restricted-imports" ([#&#8203;7894](https://redirect.github.com/oxc-project/oxc/issues/7894)) (Alexander S.)

##### Documentation

-   [`6c0f006`](https://redirect.github.com/oxc-project/oxc/commit/6c0f006) linter: Improve the documentation of eslint/no-useless-concat ([#&#8203;9179](https://redirect.github.com/oxc-project/oxc/issues/9179)) (Tom)
-   [`3414824`](https://redirect.github.com/oxc-project/oxc/commit/3414824) oxc: Enable `clippy::too_long_first_doc_paragraph` ([#&#8203;9237](https://redirect.github.com/oxc-project/oxc/issues/9237)) (Boshen)

##### Refactor

-   [`fb7df52`](https://redirect.github.com/oxc-project/oxc/commit/fb7df52) linter: Allow indirect `eval` by default for `eslint/no-eval` ([#&#8203;9302](https://redirect.github.com/oxc-project/oxc/issues/9302)) (dalaoshu)
-   [`b6fc0f6`](https://redirect.github.com/oxc-project/oxc/commit/b6fc0f6) linter: Improve `unicorn/consistent-function-scoping` ([#&#8203;9163](https://redirect.github.com/oxc-project/oxc/issues/9163)) (dalaoshu)

### [`v0.15.11`](https://redirect.github.com/oxc-project/oxc/blob/HEAD/npm/oxlint/CHANGELOG.md#01511---2025-02-16)

[Compare Source](https://redirect.github.com/oxc-project/oxc/compare/oxlint_v0.15.10...oxlint_v0.15.11)

##### Features

-   [`5d508a4`](https://redirect.github.com/oxc-project/oxc/commit/5d508a4) linter: Support `env` and `globals` in `overrides` configuration ([#&#8203;8915](https://redirect.github.com/oxc-project/oxc/issues/8915)) (Sysix)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNjcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
2025-02-28 10:43:57 +00:00
L-Sun
d476d3b1df fix(editor): android keyboard can not be opened (#10502)
Close [BS-2674](https://linear.app/affine-design/issue/BS-2674/[android]-%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%8C%BA%E5%9F%9F%E7%82%B9%E5%87%BB%E5%90%8E%E6%97%A0%E6%B3%95%E6%BF%80%E6%B4%BB%E9%94%AE%E7%9B%98) [BS-2609](https://linear.app/affine-design/issue/BS-2609/[android]-%E8%BE%93%E5%85%A5%E7%9A%84-toolbar-%E6%B2%A1%E6%9C%89%E4%BA%86)
2025-02-28 08:23:26 +00:00
pengx17
cd0bec5d31 fix(core): at menu ux (#10485)
fix AF-2285

1. loading icon will be rendered to the group name
2. make the focused item more stable
2025-02-28 02:34:29 +00:00
Saul-Mirone
4c736bc190 feat(editor): type safe draft model and transformer (#10486) 2025-02-27 09:19:49 +00:00
Saul-Mirone
ce87dcf58e feat(editor): schema extension (#10447)
1. **Major Architectural Change: Schema Management**
   - Moved from `workspace.schema` to `store.schema` throughout the codebase
   - Removed schema property from Workspace and Doc interfaces
   - Added `BlockSchemaExtension` pattern across multiple block types

2. **Block Schema Extensions Added**
   - Added new `BlockSchemaExtension` to numerous block types including:
     - DataView, Surface, Attachment, Bookmark, Code
     - Database, Divider, EdgelessText, Embed blocks (Figma, Github, HTML, etc.)
     - Frame, Image, Latex, List, Note, Paragraph
     - Root, Surface Reference, Table blocks

3. **Import/Export System Updates**
   - Updated import functions to accept `schema` parameter:
     - `importHTMLToDoc`
     - `importHTMLZip`
     - `importMarkdownToDoc`
     - `importMarkdownZip`
     - `importNotionZip`
   - Modified export functions to use new schema pattern

4. **Test Infrastructure Updates**
   - Updated test files to use new schema extensions
   - Modified test document creation to include schema extensions
   - Removed direct schema registration in favor of extensions

5. **Service Layer Changes**
   - Updated various services to use `getAFFiNEWorkspaceSchema()`
   - Modified transformer initialization to use document schema
   - Updated collection initialization patterns

6. **Version Management**
   - Removed version-related properties and methods from:
     - `WorkspaceMetaImpl`
     - `TestMeta`
     - `DocImpl`
   - Removed `blockVersions` and `workspaceVersion/pageVersion`

7. **Store and Extension Updates**
   - Added new store extensions and adapters
   - Updated store initialization patterns
   - Added new schema-related functionality in store extension

This PR represents a significant architectural shift in how schemas are managed, moving from a workspace-centric to a store-centric approach, while introducing a more extensible block schema system through `BlockSchemaExtension`. The changes touch multiple layers of the application including core functionality, services, testing infrastructure, and import/export capabilities.
2025-02-26 11:31:29 +00:00
fundon
866b096304 fix(core): fix doc url parsing with custom domain names (#10444)
Closes: [AF-2279](https://affine-pro.slack.com/archives/C06CTBH5L4R/p1740552397245649?thread_ts=1740547457.278239&cid=C06CTBH5L4R)
2025-02-26 07:35:25 +00:00
donteatfriedrice
d63f16da5e fix(editor): affine preview root style (#10420)
Fix [BS-2677](https://linear.app/affine-design/issue/BS-2677/linked-doc-embed-view样式错误)

1. Only show the border of embed synced doc block (in note) when hover.
2. Fix affine preview root padding style, set padding only when affine preview root in embed synced doc block (in surface).
3. Only add the footnote config extension to the chat panel and chat block center peek. For footnotes in other page preview scenarios, such as footnote nodes within embed synced doc blocks or embed linked doc blocks, the hover effect should be maintained.
2025-02-26 04:25:24 +00:00