mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-05-08 13:57:34 +08:00
canary
11231 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5813e7dd77 | chore: update i18n v2026.5.7-canary.951 | ||
|
|
ac37d07e74 |
feat(editor): add Bear backup import and markdown zip folder hierarchy (#14599)
## Summary
- Add Bear `.bear2bk` backup importer (TextBundle-based zip format)
- Enhance markdown zip import to preserve folder structure from zip
paths
- Add colored highlight (`<mark data-color="...">`) support to HTML
adapter
### Bear Import Details
Bear backups are zip archives of TextBundle directories. The importer:
- Parses Bear-specific markdown (highlights `==text==`, callouts `>
[!NOTE]`, inline tags `#tag`)
- Extracts creation/modification dates from `info.json` metadata
- Filters out trashed notes
- Converts Bear tags to AFFiNE tags (consolidated by root segment)
- Builds folder hierarchy from nested tag paths (e.g.,
`#work/projects/alpha`)
- Uses JSZip for lazy decompression to handle large backups without OOM
### Markdown Zip Folder Hierarchy
`importMarkdownZip` now returns `{ docIds, folderHierarchy }` instead of
just `docIds[]`, enabling the UI to recreate the zip's directory
structure as AFFiNE folders.
## Related Issues
- Implements the TextBundle-based import approach suggested in #14115 /
Discussion #14142
- Addresses folder structure preservation requested in #10003
- Partially addresses frontmatter metadata import from #11286
## Test Plan
- [ ] Import a Bear `.bear2bk` backup file via the import dialog
- [ ] Verify tags are created and assigned to documents
- [ ] Verify folder hierarchy matches Bear's nested tag structure
- [ ] Verify creation/modification dates are preserved
- [ ] Verify highlighted text and callouts render correctly
- [ ] Verify images and attachments are imported
- [ ] Import a markdown zip with nested folders, verify folder structure
is recreated
- [ ] Verify trashed Bear notes are excluded
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Bear (.bear2bk) backup import: bulk import notes, convert/dedupe tags,
create nested folders, and return imported doc IDs plus folder
hierarchy; UI import option and progress integrated.
* Markdown ZIP import now returns an optional folder hierarchy alongside
created doc IDs.
* **Bug Fixes / Improvements**
* Highlighting: mark elements validate color names, default safely, and
apply consistent background styling.
* **Chores**
* Added runtime dependency for ZIP handling.
* **Documentation**
* Added localization strings and i18n accessors for Bear import UI.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
|
||
|
|
429e7f495d |
chore: bump up link-preview-js version to v4.0.1 [SECURITY] (#14917)
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
|
[link-preview-js](https://redirect.github.com/OP-Engineering/link-preview-js)
| [`4.0.0` →
`4.0.1`](https://renovatebot.com/diffs/npm/link-preview-js/4.0.0/4.0.1)
|

|

|
---
### link-preview-js vulnerable to IPv6 and internal loopback attacks
[CVE-2026-43897](https://nvd.nist.gov/vuln/detail/CVE-2026-43897) /
[GHSA-4gp8-rjrq-ch6q](https://redirect.github.com/advisories/GHSA-4gp8-rjrq-ch6q)
<details>
<summary>More information</summary>
#### Details
##### Impact
The library did not check for IPv6 loopback attacks. There was also a
DNS attack, where an address could be resolved into an internal IP. This
could cause internal data leaks.
##### Patches
Problem has been patched in version 4.0.1. However, it cannot be
completely solved by the package alone. The regex used for validation
has been tightened for IPv6 addresses.
The DNS resolving, however, is more difficult. The regex has been
tightened to prohibit .internal, .local, .nip.io and .sslip.io
addresses, however there can be other services not on the list,
therefore it is imperative that users use the resolveDNSHost option to
do DNS resolution before fetching content. To that regard a (scary)
error message has been added when the option is not set.
##### Workarounds
Users can do their own validation before fetching content.
Reported by https://github.com/Andrew-most-likely
#### Severity
- CVSS Score: 8.7 / 10 (High)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`
#### References
-
[https://github.com/OP-Engineering/link-preview-js/security/advisories/GHSA-4gp8-rjrq-ch6q](https://redirect.github.com/OP-Engineering/link-preview-js/security/advisories/GHSA-4gp8-rjrq-ch6q)
-
[https://github.com/OP-Engineering/link-preview-js/pull/179](https://redirect.github.com/OP-Engineering/link-preview-js/pull/179)
-
[
|
||
|
|
339f89220a | fix(core): prevent navigation panel from reordering while typing (#14831) | ||
|
|
440ff0c342 |
fix(editor): resolve UX inconsistencies in the AI chat interface (#14850)
# Closes #14189. Fixes the three UX issues reported in the original bug report, plus one small adjacent polish on the right-sidebar toggle that was requested during review. Each concern in the issue is addressed end-to-end, with the same treatment applied to both places the AI chat panel lives: the **sidebar chat panel** (right panel on a doc page) and the **standalone `/chat` page**. --- ## 1. `+` button → persistent multi-session tabs (issue point 1) **Before:** clicking `+` called `createFreshSession()` (standalone) or `newSession()` (sidebar), both of which tore down the current chat content and replaced it in place. There was no way to keep two chats open at once. **After:** a browser/IDE-style tab strip lives above the chat content. Each open session gets its own tab with a close `×`; the active tab is highlighted; `+` now adds a tab rather than replacing the chat. ### Details - New Lit component `ai-chat-tabs` ([packages/frontend/core/src/blocksuite/ai/components/ai-chat-toolbar/ai-chat-tabs.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-toolbar/ai-chat-tabs.ts)). - Tab title is derived from `session.title` → first user message → `"New chat"`. - Horizontal scroll when tabs overflow, with a `wheel` handler that converts mouse wheel / trackpad vertical swipe into horizontal scroll (native horizontal trackpad swipes also work natively via `overflow-x: auto`). - Auto `scrollIntoView({ inline: 'nearest' })` on active tab change, so a newly created or newly selected tab slides into view instead of staying hidden behind the toolbar. - Close `×` removes the tab from the strip but leaves the session on the server (matches the existing **Chat history** dropdown semantics — the session is still reachable there). Closing the active tab switches to an adjacent one; closing the last tab starts a fresh session. - Persistence: open session IDs are saved per-workspace in `localStorage` under `ai-chat-open-tabs:{workspaceId}`. On mount, the React pages hydrate those IDs via `AIProvider.session.getSession` / `CopilotClient.getSession` — no new backend or schema work. - Wiring: identical effects on both variants ([chat.tsx (sidebar)](packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx) and [chat/index.tsx (standalone)](packages/frontend/core/src/desktop/pages/workspace/chat/index.tsx)) — hydrate → sync active session into tabs → persist. - The tab strip sits on the same row as the existing toolbar icons (pin / history / `+`), separated by `flex: 1` + `min-width: 0` so the tabs scroll cleanly up to the toolbar boundary. - The `ShadowlessElement` base class injects its static CSS globally, and the `:host` selector does not match in a React-rooted DOM — the component uses tag-selector CSS (`ai-chat-tabs { display: flex; … }`) instead. ## 2. Drag-and-drop attachments (issue point 2) **Before:** the chat input accepted no DnD. Attaching anything required the `+` → file-picker flow. **After:** the chat input accepts OS files via native HTML5 DnD and AFFiNE documents via the repo's existing pragmatic-drag-and-drop infrastructure. ### Details - Native handlers (`dragenter/over/leave/drop`) on [ai-chat-input.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/ai-chat-input.ts) accept OS files: images go into the image preview grid, other files become attachment chips, with the same 50 MB per-file cap as the `+` picker. - Internal AFFiNE document drags from the nav panel land as doc chips, handled via `dropTargetForElements` from `@atlaskit/pragmatic-drag-and-drop` (same library the rest of the app already uses for internal DnD). - A "Drop to attach" overlay appears during drag, reusing the existing focused-border token (`--affine-v2-layer-insideBorder-primaryBorder`) for visual consistency with the focused state. - The image/file routing logic that previously lived inline in `add-popover.ts` was factored into a shared helper [attachment-utils.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/attachment-utils.ts) (`addFilesToChat`), so the `+` picker and the drop handler stay in lockstep. - Analytics: extended the `addEmbeddingDoc.control` union in [events.ts](packages/frontend/track/src/events.ts) with `'dragDrop'` so drag-originated attachments are distinguishable from button-initiated ones in telemetry. - `@atlaskit/pragmatic-drag-and-drop` is promoted from a transitive dependency (via `@affine/component`) to a direct dependency of `@affine/core` and `yarn.lock` is refreshed accordingly. ## 3. Chat-history tooltip + icon (issue point 3) **Before:** hovering the chat-history button showed a tooltip whose background did not invert for dark theme (`--affine-tooltip` is not theme-aware), and the icon was `ArrowDownSmallIcon` — a chevron that does not convey "history." **After:** the tooltip primitive itself is theme-aware (every tooltip in the app benefits, not just the chat one), and the icon is the semantically-clear `HistoryIcon`. ### Details - [tooltip.ts](blocksuite/affine/components/src/tooltip/tooltip.ts) now uses `var(--affine-v2-tooltips-background, var(--affine-tooltip))` and `var(--affine-v2-tooltips-foreground, var(--affine-white))`. The V2 tokens auto-invert with theme; the old vars remain as fallbacks so components that override via the existing `tooltipStyle` escape hatch continue to work. - Triangle arrow colors updated to use the same V2 token. - [ai-chat-toolbar.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-toolbar/ai-chat-toolbar.ts): `ArrowDownSmallIcon` → `HistoryIcon`; added `data-testid="ai-panel-chat-history"` for future e2e coverage. ## 4. Right-sidebar toggle: tooltips + open-state icon *(adjacent polish)* Not part of the original issue, but surfaced while testing the tab strip — neither of the two right-sidebar toggle buttons had hover affordance, and both used the same icon regardless of the sidebar's state. - Added `tooltip="Open sidebar"` on the route-container button shown when the sidebar is hidden. - Added `tooltip="Close sidebar"` on the sidebar-header button shown when the sidebar is expanded. - The close button now renders a small inline `RightSidebarOpenIcon` variant: same outline as `RightSidebarIcon`, but with the right panel filled in the AFFiNE accent color to convey the open state. Icon shape change is self-contained — no new icon asset added to `@blocksuite/icons`. --- ## Commits - `2adc0c7` — fix(ai-chat): theme-aware tooltip + semantic chat-history icon *(2 files)* - `bf26974` — feat(ai-chat): drag-and-drop file and doc attachments in chat input *(7 files)* - `fca29c8` — feat(ai-chat): persistent multi-session tab strip *(8 files)* - `7d5dffe` — feat(workbench): tooltips and open-state icon for the right-sidebar toggle *(2 files)* Kept ordered smallest → largest blast radius so the history is easy to bisect. --- ## Test plan Verified locally against a fresh server stack (postgres / redis / mailpit via compose, migrations run) signed in as `dev@affine.pro`, in both `/chat` and the sidebar chat on a doc page, in light and dark themes: - [x] Tooltip: hover the chat-history icon in dark mode → tooltip is dark-on-light; toggle to light mode → tooltip is light-on-dark. Existing tooltips on other surfaces (slash menu, edgeless, linked-doc) still render correctly. - [x] Icon: chat-history button renders the history glyph (clock), not a chevron. - [x] Drag-and-drop (OS file): drop a PDF / PNG / TXT onto the input → overlay shows → chips/images appear; file > 50 MB → rejected silently (same as `+` picker). - [x] Drag-and-drop (internal doc): drag an AFFiNE doc from the nav panel → becomes a doc chip. - [x] Pin-picker, `+` picker, paste-image — all unchanged. - [x] Tab strip: first chat auto-becomes a tab on first message; `+` adds tab; click tab switches chat; `×` removes tab and switches to adjacent; close last tab → new fresh tab spawns. - [x] Reload browser → tab strip rehydrates from localStorage with the same sessions. - [x] Tab overflow: 12+ tabs → horizontal scroll via trackpad vertical swipe, trackpad horizontal swipe, and mouse wheel; active tab auto-scrolls into view on `+` click. - [x] Right-sidebar: hover both toggle buttons → tooltips appear; open the sidebar → close button shows the filled right-panel icon. - [x] `yarn lint:ox` and lint-staged both clean on every commit. Not verified locally (no local model key configured): the assistant actually streams a response. Drop/chip flow is independent of that path. ## Out of scope / follow-ups - No new unit or Playwright tests — the fixes are visually verifiable and reuse existing reducer / state paths. Happy to add tests if reviewers prefer. - `@affine/native` is not required for the web dev stack; I only built `@affine/server-native`. Irrelevant to the PR diff. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Multi-tab chat UI with a tabs component, open/close/switch actions, and per-workspace persistence/restoration. * Drag-and-drop attachments into chat input (files and docs). * **UI/UX** * Tooltip theming moved to v2 variables (includes arrow color). * Sidebar toggle/close buttons now show tooltips. * “Drop to attach” overlay and updated history icon. * **Behavior** * Unified attachment handling with 50MB validation and toast notices. * **Analytics** * Attachment events record drag-and-drop as a control method. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> |
||
|
|
eb9cc22502 | feat(server): refactor for byok (#14911) | ||
|
|
4e169ea5c7 |
fix(editor): cross browser test stability (#14897)
#### PR Dependency Tree * **PR #14897** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved reliability of shape and connector detection by forcing full DOM renders during waits. * Fixed race conditions in code-block theme loading and cleanup when components unmount. * Refined viewport element discovery to correctly handle rotated/canvas-layer elements and avoid stale DOM removal. * **Tests** * Increased polling timeouts and retries to reduce flakiness. * Disabled per-file parallelism and ensured test setup performs full cleanup before starting; extended test timeout. <!-- end of auto-generated comment: release notes by coderabbit.ai -->v2026.5.6-canary.947 |
||
|
|
9e412f58ec |
feat(editor): add collapse/expand functionality to code block component (#14884)
This PR fixes #14040 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Code blocks can be collapsed and expanded via a toolbar toggle (visible when the document is editable). * Collapsed code blocks show a limited preview (~8 lines) with a bottom fade overlay and reduced padding. * Toolbar button updates icon and tooltip to reflect collapsed/expanded state. * Collapse state is preserved on the block so its current collapsed/expanded setting is retained. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5d234ad6a8 |
fix(editor): single-letter tags in select/multi-select table cell (#14808)
### Summary of Changes Resolves #14715 and #14280. When a user types into a **Select/Multi-Select** table cell to create/choose a tag, that character is stashed on the cell container (setTagDraft) instead of going through valueSetFromString. Opening the tag picker reads it via consumeTagDraftFromTableCellHost. ### Verification - Added unit test to check that single-character input doesn't immediately call valueSetFromString. https://github.com/user-attachments/assets/432b2693-52f9-4ab4-a694-8440aea007a3 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Tag selection popups now initialize with draft text from keypresses in tag columns, improving user experience when editing tags. * **Tests** * Added comprehensive hotkey tests for single-select and multi-select tag column behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1ad088398f | fix(server): test & schema | ||
|
|
74d5ebad13 |
fix(editor): stretch latex preview content (#14857)
### Summary of Changes Resolves #13340. Change align-items to stretch to full width to avoid tag/label from overlapping with equation. ### Screenshot Verification **Before** <img width="661" height="256" alt="Screenshot 2026-04-19 at 5 58 03 PM" src="https://github.com/user-attachments/assets/a99d0138-838f-4f91-bd63-cbd07710484c" /> **After** <img width="614" height="275" alt="Screenshot 2026-04-19 at 5 58 16 PM" src="https://github.com/user-attachments/assets/7e62ab09-f290-4b6e-9cd6-d20b8f990da3" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Improved the vertical alignment of LaTeX block content to better utilize container space. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a1800cf8b2 |
feat(editor): remove max-height restriction from mermaid preview container (#14882)
This PR fixes #14874 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Removed height limitation on Mermaid diagram previews in code blocks, allowing larger diagrams to render at their full size without being constrained by a fixed maximum height. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
fa66139230 |
feat(server): add flag for calendar enable (#14896)
#### PR Dependency Tree * **PR #14896** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added configuration option to manage Google Calendar account linking access. Administrators can now disable new account connections to control calendar service integrations. When disabled, the Google provider is hidden from available options and new linking attempts are blocked, while existing accounts remain fully functional. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
027d163921 |
fix(server): add embedding table repair (#14895)
fix #14894 #### PR Dependency Tree * **PR #14895** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Improved database initialization for self-hosted deployments with automatic creation and repair of embedding tables and indexes, applied only when related base tables and extensions are present. * Updated pre-deploy process to run Prisma migrations, perform embedding-table maintenance, and execute additional data migrations as part of setup. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
39abb936b8 |
fix(core): prevent Alt+Key shortcuts from hijacking macOS Option-key input (#14866)
Fixes #14519 ## Summary On macOS, the Option key combined with a letter produces locale input characters (e.g. Polish layout: Option+S → `ś`, Option+L → `ł`). The AFFiNE command registry registers shortcuts like `Alt+KeyS` (used for Page ↔ Edgeless mode switch) via `tinykeys`, which matches on `event.code` (the physical key) — so it fires even when the user was actually typing a non-ASCII character. Reported in #14519: Polish users cannot type `ś` inside AFFiNE because Option+S triggers the mode switch instead. ## Fix In the command registry handler ([registry.ts](packages/frontend/core/src/commands/registry/registry.ts)), skip the command when Alt is the only modifier **and** the key produced a non-ASCII character — the user intends to type the character, not invoke the shortcut. Matches the existing handling in blocksuite's `keymap.ts` (added for the same class of issue in #14059). ## Demo https://github.com/user-attachments/assets/eb6d2e69-39bf-4236-a886-9e2bde425626 ## Verified locally (macOS) - Switched input source to Polish - Typed `właśnie` in an AFFiNE doc — all characters including `ś` (Option+S), `ł` (Option+L) now produce the correct output - Previously Option+S would toggle edgeless mode - US layout (Option+S → `ß`) and other locale chars (ą, ń, ę) also now pass through correctly - Regular Cmd-based shortcuts (Cmd+K, Cmd+S, etc.) unaffected because the guard excludes `metaKey` ## Test plan - [x] On macOS, add Polish input source (System Settings → Keyboard → Input Sources → +) - [x] Switch to Polish layout - [x] In any AFFiNE doc, type Option+S → `ś` appears (not mode switch) - [x] Confirm other shortcuts (Cmd+K, Cmd+Enter, etc.) still work - [x] Confirm on US layout that Option+S produces `ß` (OS default) without firing the mode switch <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed keyboard event handling with Alt key and non-ASCII characters to prevent unintended command execution. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9751cab16c |
fix(editor): native table column resize broken in edgeless mode (#14824)
Fixes #14717 ## Summary When a native `affine:table` block is placed in a note on the edgeless canvas, dragging the column resize handle (or the column/row drag handles) causes the canvas to pan instead of triggering the resize/drag, because the edgeless `DragController` listens at the `pointerdown` level — earlier than `SelectionController`'s existing `mousedown` handler. ## Fix Two interception layers added to `blocksuite/affine/blocks/table/src/selection-controller.ts`, matching the working pattern in `affine:database`'s `database-header-column.ts`: 1. **DOM-level `pointerdown` `stopPropagation()`** in `dragListener()` — prevents the edgeless `DragController` from capturing the event before BlockSuite's event system sees it. 2. **`handleEvent('dragStart', ...)`** in `hostConnected()` — returns `true` when the target is a resize/drag handle, so the BlockSuite event dispatcher doesn't route to the edgeless tool controller. Selectors guarded: `[data-width-adjust-column-id]`, `[data-drag-column-id]`, `[data-drag-row-id]`. Mobile and readonly states preserved (matching existing `dragListener()` guards). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved drag-and-drop interaction handling for table operations, including column width adjustment and row/column dragging. Enhanced event handling to prevent unintended drag actions and ensure proper behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5e97e67ecd |
fix(editor): prevent connector label from breaking after click + move in empty label editor (#14830)
### Problem ●In edgeless mode, after clicking and moving in a connector's label editor, if the label editor has empty content at the end of the editing, the label editor for that connector can not be triggered again. ●The following video demonstrates this issue: https://github.com/user-attachments/assets/8d300720-5ed8-4f9c-90fa-fbf059417ff8 ### Root Cause **Direct cause** ●The `labelOffset` property is **stashed** at drag-start, but is **not properly popped** afterward. As a result, when `mountConnectorLabelEditor()` is called the second time (`packages/affine/gfx/connector/src/text/edgeless-connector-label-editor.ts`), `connector.labelOffset` returns `undefined` instead of the default value provided by the `@field` decorator. **Why moving after clicking incorrectly triggers a drag-start** ●The root issue lies in the interaction between click and drag event handling. Here's the actual flow: 1.`dispatcher.add('click', () => true)` is registered in `EdgelessConnectorLabelEditor`. 2.On pointer-down, both `ClickController` and `DragController` receive the event. 3.On pointer-up, `ClickController` fires a **synthetic click**. The handler from step 1 returns `true`, triggering `context.get('defaultState').event.stopPropagation()`. 4.This prevents the native pointer-up from bubbling to `DragController`. However, a subsequent pointer-move still causes `DragController` to **incorrectly synthesize a drag-start + drag-move**. **Fundamental root cause** ●The line `context.get('defaultState').event.stopPropagation()` in `UIEventDispatcher::run()` stops **both** synthetic and native event bubbling. It should only stop synthetic event propagation. ●The synthetic event bubbling stopping is already properly handled by the immediate `return` statement on the next line, because the runners are prepared in strict order (current → parent → grandparent → ... → global) by `UIEventDispatcher::_getEventScope()` and then **executed sequentially** in `UIEventDispatcher::run()`. ### Fix ●Since I cannot rule out that other (current or future) event handlers may rely on this native event bubbling stopping behavior, I chose not to remove the `context.get('defaultState').event.stopPropagation()` line completely. Instead, I added a new constant and now skip `stopPropagation()` **only** for the following synthetic events: ```ts const syntheticEventNames = new Set(['click', 'doubleClick', 'tripleClick']); ``` These currently represent all known synthetic click events triggered from pointer-up. ### After ●The video below shows the behavior after this fix. https://github.com/user-attachments/assets/65b8a3ce-0767-4d80-986b-8bc6081ddd4c |
||
|
|
7046ad7bf4 |
fix(editor): align selection/handle/remote/text overlays with blocks (#14862)
# Closes #14855. ## The bug When an `affine:embed-synced-doc` is placed on an edgeless canvas and resized which sets `model.props.scale` to a value ≠ 1 - the block-selection frame rendered **inside** that embedded editor is drawn offset from the actual block boundary. The reporter hit this in Safari, but the root cause is platform-independent.  ## Root cause `affine-embed-edgeless-synced-doc-block` applies `transform: scale(modelScale)` to its `.affine-embed-synced-doc-container` so the embedded editor visually fits inside its edgeless xywh ([embed-edgeless-synced-doc-block.ts#L48-L58](https://github.com/toeverything/AFFiNE/blob/canary/blocksuite/affine/blocks/embed-doc/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts#L48-L58)). The inner `Viewport` exposes that outer scale as `viewScale = boundingClientRect.width / offsetWidth`. PR #14015 and PR #14074 already taught the surface canvas and `GfxBlockComponent.getCSSTransform` to compensate by dividing by `viewScale`. But several selection-related overlays that render inside the same scaled container were **not** updated in those PRs. They either: - read `viewport.toViewCoord(x, y)` - which returns `(x - viewportX) * zoom * viewScale` and drop the result into CSS `left` / `top` inside the scaled container, or - hand-build a `translate(translateX, translateY) scale(zoom)` transform without `viewScale` compensation. The outer CSS `scale(viewScale)` then re-applies the scale, leaving the overlays one factor of `viewScale` away from their blocks. That's exactly the misalignment in the screenshot - the rect's size looks right but its position is offset. ## The fix Mirror the pattern shipped in #14074 everywhere the inner overlays are placed: - position: `(model - viewportX) * zoom / viewScale` - transform scale: `zoom / viewScale` - translate: `translateX / viewScale, translateY / viewScale` This keeps the overlays in the same reference frame as `GfxBlockComponent.getCSSTransform` so they line up with the block they're framing. When `viewScale === 1` (normal edgeless canvas, outside any embed) every `/ viewScale` is a no-op and behaviour is unchanged. ## Why this is safe - When `viewScale === 1` - every existing caller outside `embed-edgeless-synced-doc` - the math reduces to the original expression byte-for-byte. - The fix strictly mirrors the invariant already adopted by `GfxBlockComponent.getCSSTransform` in #14074. It's the same division by `viewScale` applied in the same place. - No public API, type, or DOM structure changed. ## Scope / known limitations - The `Viewport._cachedBoundingClientRect` cache is only invalidated by its own `ResizeObserver` ([viewport.ts#L500-L505](https://github.com/toeverything/AFFiNE/blob/canary/blocksuite/framework/std/src/gfx/viewport.ts#L500-L505)). A CSS-transform change on an ancestor (e.g. the user panning/zooming the outer edgeless canvas) does not fire it, so in theory `viewScale` can go stale between outer-viewport updates. In practice this hasn't come up in repro - the inner viewport's shell is observed and fires whenever layout shifts. If it turns out to matter I'm happy to add a `viewport.onResize()` refresh hook off the existing `GfxViewportInitializer` in a follow-up. - No integration test added - the existing `blocksuite/integration-test/edgeless/` suite has no `embed-synced-doc` harness. Adding one is a larger scope; can follow up if requested. ## Test plan - [x] `yarn typecheck` - passes - [x] `yarn lint:ox` - `0 warnings, 0 errors` - [x] `yarn prettier --write` on the 5 touched files - no changes - [ ] Manual: on canary, create an edgeless canvas, drop an embed-synced-doc, resize with `Shift` held so `model.props.scale` ≠ 1, select any block inside, and verify the blue selection frame sits flush with the block's boundary (confirm on Safari, Chrome, Firefox). - [ ] Regression check: on a normal edgeless canvas (no embed), verify element selection, drag handle, and text/shape inline editors still render correctly (these code paths hit `viewScale === 1` and should be unchanged). ## Related PRs - #14015 - fixed surface canvas at non-1 `viewScale`. - #14074 - fixed `GfxBlockComponent.getCSSTransform` at non-1 `viewScale`. This PR completes that series by covering the selection overlays. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed positioning and scaling of inline text editors, selection rectangles, drag handles, and remote cursors so overlays and editors remain correctly aligned and sized when the viewport uses an additional outer scale/transform during zooming and panning. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e90e3e537c | fix(server): lint | ||
|
|
d64f368623 |
feat(server): refactor copilot (#14892)
#### PR Dependency Tree * **PR #14892** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) |
||
|
|
fa8f1a096c |
fix(server): allow custom R2 jurisdictional endpoint (#14848)
## Summary This PR fixes `cloudflare-r2` storage configuration so jurisdictional R2 endpoints (for example EU buckets) work correctly. Closes #14847 ## Problem `cloudflare-r2` currently ignores `config.endpoint` and always uses: `https://<accountId>.r2.cloudflarestorage.com` That breaks uploads for jurisdictional buckets that require endpoints like: `https://<accountId>.eu.r2.cloudflarestorage.com` ## Changes - Updated `R2StorageProvider` endpoint resolution: - use `config.endpoint` when provided - otherwise fall back to `https://${accountId}.r2.cloudflarestorage.com` - Kept `forcePathStyle: true` behavior unchanged - Updated validation to require `accountId` **or** `endpoint` - Improved storage schema descriptions to mention jurisdiction endpoints - Added focused unit tests for: - default account endpoint behavior - custom jurisdiction endpoint behavior ## Backward Compatibility - Existing R2 configs that only provide `accountId` continue to work exactly as before. - New behavior only applies when a custom `config.endpoint` is explicitly set. ## Tests - Added: `packages/backend/server/src/base/storage/__tests__/r2.spec.ts` - Verifies both default and custom endpoint selection paths. _Disclaimer: parts of this PR were implemented with AI assistance._ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Cloudflare R2 config adds an optional "jurisdiction" (EU) option and consistent endpoint derivation for S3-compatible providers. * **Documentation** * Storage configuration schemas clarified: S3 endpoint is optional/derived from region; R2 endpoint removed from schema and jurisdiction documented. * **Tests** * Added tests validating R2 endpoint selection for default, EU-jurisdiction, undefined-jurisdiction, and missing-account scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> |
||
|
|
fb6291cb15 | fix: deps dedup | ||
|
|
694158eea3 |
feat(playground): export Y.Doc from debug menu (#14893)
## Summary - add an Export Y.Doc debug menu item - encode the active store spaceDoc with Y.encodeStateAsUpdate - download the update as a binary ydoc-update file ## Test - yarn workspace @blocksuite/playground build <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Y.Doc export functionality to the debug menu, enabling users to download the current space document state as a binary update file through the "Test Operations" → "Export" menu. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
207bd9387e | fix(docs): redirect links | ||
|
|
78a9942f19 | fix: ci | ||
|
|
0ccfacbc29 | feat(docs): migrate bs docs | ||
|
|
bf6fc66943 |
chore: bump up postcss version to v8.5.10 [SECURITY] (#14877)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [postcss](https://postcss.org/) ([source](https://redirect.github.com/postcss/postcss)) | [`8.5.6` → `8.5.10`](https://renovatebot.com/diffs/npm/postcss/8.5.6/8.5.10) |  |  | --- ### PostCSS has XSS via Unescaped </style> in its CSS Stringify Output [CVE-2026-41305](https://nvd.nist.gov/vuln/detail/CVE-2026-41305) / [GHSA-qx2v-qp2m-jg93](https://redirect.github.com/advisories/GHSA-qx2v-qp2m-jg93) <details> <summary>More information</summary> #### Details ##### PostCSS: XSS via Unescaped `</style>` in CSS Stringify Output ##### Summary PostCSS v8.5.5 (latest) does not escape `</style>` sequences when stringifying CSS ASTs. When user-submitted CSS is parsed and re-stringified for embedding in HTML `<style>` tags, `</style>` in CSS values breaks out of the style context, enabling XSS. ##### Proof of Concept ```javascript const postcss = require('postcss'); // Parse user CSS and re-stringify for page embedding const userCSS = 'body { content: "</style><script>alert(1)</script><style>"; }'; const ast = postcss.parse(userCSS); const output = ast.toResult().css; const html = `<style>${output}</style>`; console.log(html); // <style>body { content: "</style><script>alert(1)</script><style>"; }</style> // // Browser: </style> closes the style tag, <script> executes ``` **Tested output** (Node.js v22, postcss v8.5.5): ``` Input: body { content: "</style><script>alert(1)</script><style>"; } Output: body { content: "</style><script>alert(1)</script><style>"; } Contains </style>: true ``` ##### Impact Impact non-bundler use cases since bundlers for XSS on their own. Requires some PostCSS plugin to have malware code, which can inject XSS to website. ##### Suggested Fix Escape `</style` in all stringified output values: ```javascript output = output.replace(/<\/(style)/gi, '<\\/$1'); ``` ##### Credits Discovered and reported by [Sunil Kumar](https://tharvid.in) ([@​TharVid](https://redirect.github.com/TharVid)) #### Severity - CVSS Score: 6.1 / 10 (Medium) - Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N` #### References - [https://github.com/postcss/postcss/security/advisories/GHSA-qx2v-qp2m-jg93](https://redirect.github.com/postcss/postcss/security/advisories/GHSA-qx2v-qp2m-jg93) - [https://nvd.nist.gov/vuln/detail/CVE-2026-41305](https://nvd.nist.gov/vuln/detail/CVE-2026-41305) - [https://github.com/postcss/postcss/releases/tag/8.5.10](https://redirect.github.com/postcss/postcss/releases/tag/8.5.10) - [https://github.com/advisories/GHSA-qx2v-qp2m-jg93](https://redirect.github.com/advisories/GHSA-qx2v-qp2m-jg93) This data is provided by the [GitHub Advisory Database](https://redirect.github.com/advisories/GHSA-qx2v-qp2m-jg93) ([CC-BY 4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)). </details> --- ### Release Notes <details> <summary>postcss/postcss (postcss)</summary> ### [`v8.5.10`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#8510) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.9...8.5.10) - Fixed XSS via unescaped `</style>` in non-bundler cases (by [@​TharVid](https://redirect.github.com/TharVid)). ### [`v8.5.9`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#859) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.8...8.5.9) - Speed up source map encoding paring in case of the error. ### [`v8.5.8`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#858) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.7...8.5.8) - Fixed `Processor#version`. ### [`v8.5.7`](https://redirect.github.com/postcss/postcss/blob/HEAD/CHANGELOG.md#857) [Compare Source](https://redirect.github.com/postcss/postcss/compare/8.5.6...8.5.7) - Improved source map annotation cleaning performance (by CodeAnt AI). </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - "" - 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:eyJjcmVhdGVkSW5WZXIiOiI0My4xNDEuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE0MS4zIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
df482c9cf2 |
chore: bump up uuid version to v14 [SECURITY] (#14870)
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [uuid](https://redirect.github.com/uuidjs/uuid) | [`^13.0.0` →
`^14.0.0`](https://renovatebot.com/diffs/npm/uuid/13.0.0/14.0.0) |

|

|
---
### uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided
[GHSA-w5hq-g745-h8pq](https://redirect.github.com/advisories/GHSA-w5hq-g745-h8pq)
<details>
<summary>More information</summary>
#### Details
##### Summary
`v3`, `v5`, and `v6` accept external output buffers but do not reject
out-of-range writes (small `buf` or large `offset`).
By contrast, `v4`, `v1`, and `v7` explicitly throw `RangeError` on
invalid bounds.
This inconsistency allows **silent partial writes** into caller-provided
buffers.
##### Affected code
- `src/v35.ts` (`v3`/`v5` path) writes `buf[offset + i]` without bounds
validation.
- `src/v6.ts` writes `buf[offset + i]` without bounds validation.
##### Reproducible PoC
```bash
cd /home/StrawHat/uuid
npm ci
npm run build
node --input-type=module -e "
import {v4,v5,v6} from './dist-node/index.js';
const ns='6ba7b810-9dad-11d1-80b4-00c04fd430c8';
for (const [name,fn] of [
['v4',()=>v4({},new Uint8Array(8),4)],
['v5',()=>v5('x',ns,new Uint8Array(8),4)],
['v6',()=>v6({},new Uint8Array(8),4)],
]) {
try { fn(); console.log(name,'NO_THROW'); }
catch(e){ console.log(name,'THREW',e.name); }
}"
```
Observed:
- `v4 THREW RangeError`
- `v5 NO_THROW`
- `v6 NO_THROW`
Example partial overwrite evidence captured during audit:
```text
same true buf [
170, 170, 170, 170,
75, 224, 100, 63
]
v6 [
187, 187, 187, 187,
31, 19, 185, 64
]
```
##### Security impact
- **Primary**: integrity/robustness issue (silent partial output).
- If an application assumes full UUID writes into preallocated buffers,
this can produce malformed/truncated/partially stale identifiers without
error.
- In systems where caller-controlled offsets/buffer sizes are exposed
indirectly, this may become a security-relevant logic flaw.
##### Suggested fix
Add the same guard used by `v4`/`v1`/`v7`:
```ts
if (offset < 0 || offset + 16 > buf.length) {
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
}
```
Apply to:
- `src/v35.ts` (covers `v3` and `v5`)
- `src/v6.ts`
#### Severity
- CVSS Score: 6.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N`
#### References
-
[https://github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pq](https://redirect.github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pq)
-
[
|
||
|
|
2caf3c86f8 |
fix(editor): prevent popMenu overflow on constrained viewports (#14827)
Fixes #14722 ## Summary `popMenu()` in `blocksuite/affine/components/src/context-menu/menu-renderer.ts` uses `autoPlacement` + `offset` in its default middleware, but no `shift()` — so when `autoPlacement` picks a placement that would overflow the viewport (e.g. database column menu opening near the top of a short viewport), the menu stays overflowing and top items get clipped above the viewport. ## Fix Add `shift({ padding: 8 })` to the default middleware chain. This matches the behavior of the sibling helper `createPopup()` in the same file, which already includes `shift()` in its defaults. ## Reproducing (as reported in #14722) Viewport ~879×461 (Chrome, macOS). Create a database block near the top of the viewport → click a column name → menu opens upward and the top items ("Rename", "Filter") get clipped above the viewport. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Enhanced context menu positioning on desktop to provide better alignment and spacing adjustments near screen boundaries. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
557b1e4dfc |
chore: bump up eslint-plugin-oxlint version to v1.60.0 (#14853)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [eslint-plugin-oxlint](https://redirect.github.com/oxc-project/eslint-plugin-oxlint) | [`1.58.0` → `1.60.0`](https://renovatebot.com/diffs/npm/eslint-plugin-oxlint/1.58.0/1.60.0) |  |  | --- ### Release Notes <details> <summary>oxc-project/eslint-plugin-oxlint (eslint-plugin-oxlint)</summary> ### [`v1.60.0`](https://redirect.github.com/oxc-project/eslint-plugin-oxlint/releases/tag/v1.60.0) [Compare Source](https://redirect.github.com/oxc-project/eslint-plugin-oxlint/compare/v1.59.0...v1.60.0) *No significant changes* ##### [View changes on GitHub](https://redirect.github.com/oxc-project/eslint-plugin-oxlint/compare/v1.59.0...v1.60.0) ### [`v1.59.0`](https://redirect.github.com/oxc-project/eslint-plugin-oxlint/releases/tag/v1.59.0) [Compare Source](https://redirect.github.com/oxc-project/eslint-plugin-oxlint/compare/v1.58.0...v1.59.0) *No significant changes* ##### [View changes on GitHub](https://redirect.github.com/oxc-project/eslint-plugin-oxlint/compare/v1.58.0...v1.59.0) </details> --- ### Configuration 📅 **Schedule**: (UTC) - 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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjMuOCIsInVwZGF0ZWRJblZlciI6IjQzLjEyMy44IiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
cc79fa3c6d |
chore: bump up opentelemetry (#14844)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@opentelemetry/api](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/api) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`1.9.0` → `1.9.1`](https://renovatebot.com/diffs/npm/@opentelemetry%2fapi/1.9.0/1.9.1) |  |  | | [@opentelemetry/core](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-core) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`2.6.0` → `2.7.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fcore/2.6.0/2.7.0) |  |  | | [@opentelemetry/exporter-prometheus](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-exporter-prometheus) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.213.0` → `^0.215.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fexporter-prometheus/0.213.0/0.215.0) |  |  | | [@opentelemetry/exporter-zipkin](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-exporter-zipkin) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`2.6.0` → `2.7.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fexporter-zipkin/2.6.0/2.7.0) |  |  | | [@opentelemetry/instrumentation](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.213.0` → `^0.215.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation/0.213.0/0.215.0) |  |  | | [@opentelemetry/instrumentation-graphql](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-graphql#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/HEAD/packages/instrumentation-graphql)) | [`^0.61.0` → `^0.63.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-graphql/0.61.0/0.63.0) |  |  | | [@opentelemetry/instrumentation-http](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-instrumentation-http) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.213.0` → `^0.215.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-http/0.213.0/0.215.0) |  |  | | [@opentelemetry/instrumentation-ioredis](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-ioredis#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/HEAD/packages/instrumentation-ioredis)) | [`^0.61.0` → `^0.63.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-ioredis/0.61.0/0.63.0) |  |  | | [@opentelemetry/instrumentation-nestjs-core](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-nestjs-core#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/HEAD/packages/instrumentation-nestjs-core)) | [`^0.59.0` → `^0.61.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-nestjs-core/0.59.0/0.61.0) |  |  | | [@opentelemetry/instrumentation-socket.io](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/instrumentation-socket.io#readme) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/tree/HEAD/packages/instrumentation-socket.io)) | [`^0.60.0` → `^0.62.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2finstrumentation-socket.io/0.60.0/0.62.0) |  |  | | [@opentelemetry/resources](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-resources) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`2.6.0` → `2.7.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fresources/2.6.0/2.7.0) |  |  | | [@opentelemetry/sdk-metrics](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/sdk-metrics) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`2.6.0` → `2.7.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-metrics/2.6.0/2.7.0) |  |  | | [@opentelemetry/sdk-node](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/experimental/packages/opentelemetry-sdk-node) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`^0.213.0` → `^0.215.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-node/0.213.0/0.215.0) |  |  | | [@opentelemetry/sdk-trace-node](https://redirect.github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) ([source](https://redirect.github.com/open-telemetry/opentelemetry-js)) | [`2.6.0` → `2.7.0`](https://renovatebot.com/diffs/npm/@opentelemetry%2fsdk-trace-node/2.6.0/2.7.0) |  |  | --- ### Release Notes <details> <summary>open-telemetry/opentelemetry-js (@​opentelemetry/api)</summary> ### [`v1.9.1`](https://redirect.github.com/open-telemetry/opentelemetry-js/blob/HEAD/CHANGELOG.md#191) [Compare Source](https://redirect.github.com/open-telemetry/opentelemetry-js/compare/v1.9.0...v1.9.1) ##### 🐛 (Bug Fix) - fix: avoid grpc types dependency [#​3551](https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3551) [@​flarna](https://redirect.github.com/flarna) - fix(otlp-proto-exporter-base): Match Accept header with Content-Type in the proto exporter [#​3562](https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3562) [@​scheler](https://redirect.github.com/scheler) - fix: include tracestate in export [#​3569](https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3569) [@​flarna](https://redirect.github.com/flarna) ##### 🏠 (Internal) - chore: fix cross project links and missing implicitly exported types [#​3533](https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3533) [@​legendecas](https://redirect.github.com/legendecas) - feat(sdk-metrics): add exponential histogram mapping functions [#​3504](https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3504) [@​mwear](https://redirect.github.com/mwear) </details> <details> <summary>open-telemetry/opentelemetry-js-contrib (@​opentelemetry/instrumentation-graphql)</summary> ### [`v0.63.0`](https://redirect.github.com/open-telemetry/opentelemetry-js-contrib/blob/HEAD/packages/instrumentation-graphql/CHANGELOG.md#0630-2026-04-17) [Compare Source]( |
||
|
|
3428ac478e |
chore: split i18n and bs-docs dirty checks in typecheck workflow (#14849)
## Summary Split generated-file validation in the `typecheck` workflow so i18n outputs and BS docs outputs are checked separately. This fixes a misleading CI failure message: previously, CI could fail due to i18n-generated changes like `packages/frontend/i18n/src/i18n.gen.ts`, but only suggested running `yarn typecheck && yarn affine bs-docs build`, which does not regenerate those files. ## Changes - validate i18n-generated changes immediately after `yarn affine @affine/i18n build` - keep ignoring `packages/frontend/i18n/src/i18n-completenesses.json` in CI as before - leave `yarn typecheck` as a separate step - make the BS docs step only check for changes introduced by `yarn affine bs-docs build` ## Result CI now gives the correct remediation command depending on which generated files are out of date: - i18n issues: `yarn affine @affine/i18n build` - docs/typecheck issues: `yarn typecheck && yarn affine bs-docs build` ## Testing - verified the updated workflow YAML parses successfully <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Enhanced build validation for internationalization code generation to ensure generated changes are properly committed before proceeding. The validation now occurs immediately after code generation runs, providing faster feedback during the build process. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0009f91d2a |
feat(editor): add "Copy as Markdown" option in context & export menus (#14705)
- Allow users to select text and copy it as Markdown via the context menu - Add "Copy as Markdown" under Export menu to copy entire document to clipboard Fixes #12983 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added "Copy as Markdown" to the toolbar clipboard More menu for selected content. * Added "Copy as Markdown" to the page export menu to copy entire pages as Markdown. * **Behavior** * Export flow now returns success/failure so the UI shows a dedicated success or error notification for clipboard exports. * **Localization** * Added strings for "Copy as Markdown" and "Copied as Markdown". <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Whitewater <me@waterwater.moe> Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com> |
||
|
|
f7d0f1d5ae |
chore: bump up Node.js to v22.22.2 (#14836)
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [node](https://nodejs.org) ([source](https://redirect.github.com/nodejs/node)) | patch | `22.22.1` → `22.22.2` | --- ### Release Notes <details> <summary>nodejs/node (node)</summary> ### [`v22.22.2`](https://redirect.github.com/nodejs/node/compare/v22.22.1...v22.22.2) [Compare Source](https://redirect.github.com/nodejs/node/compare/v22.22.1...v22.22.2) </details> --- ### Configuration 📅 **Schedule**: (UTC) - 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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjMuOCIsInVwZGF0ZWRJblZlciI6IjQzLjEyMy44IiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
0849b342fa |
chore: bump up dompurify version to v3.4.0 [SECURITY] (#14833)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [dompurify](https://redirect.github.com/cure53/DOMPurify) | [`3.3.3` → `3.4.0`](https://renovatebot.com/diffs/npm/dompurify/3.3.3/3.4.0) |  |  | ### GitHub Vulnerability Alerts #### [GHSA-39q2-94rc-95cp](https://redirect.github.com/cure53/DOMPurify/security/advisories/GHSA-39q2-94rc-95cp) ## Summary In `src/purify.ts:1117-1123`, `ADD_TAGS` as a function (via `EXTRA_ELEMENT_HANDLING.tagCheck`) bypasses `FORBID_TAGS` due to short-circuit evaluation. The condition: ``` !(tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) ``` When `tagCheck(tagName)` returns `true`, the entire condition is `false` and the element is kept — `FORBID_TAGS[tagName]` is never evaluated. ## Inconsistency This contradicts the attribute-side pattern at line 1214 where `FORBID_ATTR` explicitly wins first: ``` if (FORBID_ATTR[lcName]) { continue; } ``` For tags, FORBID should also take precedence over ADD. ## Impact Applications using both `ADD_TAGS` as a function and `FORBID_TAGS` simultaneously get unexpected behavior — forbidden tags are allowed through. Config-dependent but a genuine logic inconsistency. ## Suggested Fix Check `FORBID_TAGS` before `tagCheck`: ``` if (FORBID_TAGS[tagName]) { /* remove */ } else if (tagCheck(tagName) || ALLOWED_TAGS[tagName]) { /* keep */ } ``` ## Affected Version v3.3.3 (commit 883ac15) ##### Severity - CVSS Score: 5.3 / 10 (Medium) - Vector String: `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N` --- ### Release Notes <details> <summary>cure53/DOMPurify (dompurify)</summary> ### [`v3.4.0`](https://redirect.github.com/cure53/DOMPurify/releases/tag/3.4.0): DOMPurify 3.4.0 [Compare Source](https://redirect.github.com/cure53/DOMPurify/compare/3.3.3...3.4.0) **Most relevant changes:** - Fixed a problem with `FORBID_TAGS` not winning over `ADD_TAGS`, thanks [@​kodareef5](https://redirect.github.com/kodareef5) - Fixed several minor problems and typos regarding MathML attributes, thanks [@​DavidOliver](https://redirect.github.com/DavidOliver) - Fixed `ADD_ATTR`/`ADD_TAGS` function leaking into subsequent array-based calls, thanks [@​1Jesper1](https://redirect.github.com/1Jesper1) - Fixed a missing `SAFE_FOR_TEMPLATES` scrub in `RETURN_DOM` path, thanks [@​bencalif](https://redirect.github.com/bencalif) - Fixed a prototype pollution via `CUSTOM_ELEMENT_HANDLING`, thanks [@​trace37labs](https://redirect.github.com/trace37labs) - Fixed an issue with `ADD_TAGS` function form bypassing `FORBID_TAGS`, thanks [@​eddieran](https://redirect.github.com/eddieran) - Fixed an issue with `ADD_ATTR` predicates skipping URI validation, thanks [@​christos-eth](https://redirect.github.com/christos-eth) - Fixed an issue with `USE_PROFILES` prototype pollution, thanks [@​christos-eth](https://redirect.github.com/christos-eth) - Fixed an issue leading to possible mXSS via Re-Contextualization, thanks [@​researchatfluidattacks](https://redirect.github.com/researchatfluidattacks) and others - Fixed a problem with the type dentition patcher after Node version bump - Fixed freezing BS runs by reducing the tested browsers array - Bumped several dependencies where possible - Added needed files for OpenSSF scorecard checks **Published Advisories are here:** <https://github.com/cure53/DOMPurify/security/advisories?state=published> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - "" - 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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjEyMC4yIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
dc3b95c886 |
chore: bump up Rust crate rand to v0.9.3 [SECURITY] (#14832)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [rand](https://rust-random.github.io/book) ([source](https://redirect.github.com/rust-random/rand)) | dependencies | patch | `0.9.1` → `0.9.3` | | [rand](https://rust-random.github.io/book) ([source](https://redirect.github.com/rust-random/rand)) | workspace.dependencies | patch | `0.9.2` → `0.9.3` | ### GitHub Vulnerability Alerts #### [GHSA-cq8v-f236-94qc](https://redirect.github.com/rust-random/rand/pull/1763) It has been reported (by @​lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met: - The `log` and `thread_rng` features are enabled - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng` - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data) - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict. Affected versions of `rand` are `>= 0.7, < 0.9.3` and `0.10.0`. ##### Severity Low --- ### Release Notes <details> <summary>rust-random/rand (rand)</summary> ### [`v0.9.3`](https://redirect.github.com/rust-random/rand/compare/0.9.2...0.9.3) [Compare Source](https://redirect.github.com/rust-random/rand/compare/0.9.2...0.9.3) ### [`v0.9.2`](https://redirect.github.com/rust-random/rand/blob/HEAD/CHANGELOG.md#092---2025-07-20) [Compare Source](https://redirect.github.com/rust-random/rand/compare/0.9.1...0.9.2) ##### Deprecated - Deprecate `rand::rngs::mock` module and `StepRng` generator ([#​1634](https://redirect.github.com/rust-random/rand/issues/1634)) ##### Additions - Enable `WeightedIndex<usize>` (de)serialization ([#​1646](https://redirect.github.com/rust-random/rand/issues/1646)) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - "" - 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 these updates 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:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjEyMC4yIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
1d66e7e8ca |
fix(editor): allow hyperlink clicks in locked edgeless text blocks (#14829)
Fixes #14673 ## Summary When an edgeless text block is locked, `pointer-events: none` on the inner content div (`edgeless-text-block.ts:308`) blocks all mouse interaction — including clicking hyperlinks. Locking is intended to prevent accidental edits, not to block navigation, so links should remain clickable. ## Fix Apply a `locked-content` class on the inner div when the block is locked and not being edited, and add a targeted CSS rule restoring `pointer-events: auto` on anchor elements within locked content. ## Context Re-implements the fix from PR #14692 (authored by @moktamd, reverted per @darkskygit's comment on #14673 because the original contributor had not signed the CLA). The CLA is signed for this PR. ## Test plan - [ ] On edgeless canvas, create a text block with a hyperlink (e.g. `[link](https://affine.pro)`) - [ ] Lock the block via the shape toolbar - [ ] Hover the link → cursor shows pointer - [ ] Click the link → navigation occurs - [ ] Unlock and confirm editing still works as before <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Links within locked text blocks are now interactive and clickable with proper visual cursor feedback. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c5b0057778 |
fix(core): resolve remaining untranslated doc title case in detail page header (#14820)
fix #14735 This PR fixes a remaining desktop case related to #14467. The previous fix resolved incorrect translation in navigation panels, but the detail page header tab title was still passing custom document titles through `i18n.t()`, causing user-defined titles to be unexpectedly translated. ### Results https://github.com/user-attachments/assets/4abad3b9-d5d7-442f-b643-6d9ea63fa741 After: <img width="2100" height="1722" alt="After" src="https://github.com/user-attachments/assets/0770eae2-e5c5-4816-8d53-e40a4b52800c" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Updated page title retrieval mechanism in workspace detail page headers. The title is now sourced directly from the document display metadata service instead of using the previous derivation method. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a109f069b0 | chore: bump deps v2026.4.10-canary.928 | ||
|
|
0b4d25f332 | chore: improve test stability v2026.4.9-canary.928 | ||
|
|
c6a99eb9cb |
chore: bump deps (#14810)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated developer tooling dependencies used for local testing to newer patch versions for improved stability. * Bumped backend framework and related packages to newer patch releases to address fixes and maintain compatibility. * No functional or public API changes; updates are non-breaking dependency version bumps. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
77657a697b | feat(mobile): improve notify for login failed | ||
|
|
eb953c0565 |
fix(android): route OAuth deep link to correct server's AuthService (#14809)
Porting over iOS fix for self-hosted SSO to Android from #11563. Fixes #12819 Tested on own instance using Authentik. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Android authentication now supports an optional server parameter in the callback URL, enabling sign-in against different server instances. * If the specified server cannot be found, the authentication attempt is halted and an error is reported. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
77c0b2ef47 |
fix: prevent IME preedit overflow in mind map node editor (#14520)
## Summary Update the edgeless shape text editor to resize mind map node text bounds while IME composition is in progress. ## Changes - listen to `compositionupdate` on the inline editor container - trigger `_updateElementWH()` on `compositionupdate` and `compositionend` - keep text box dimensions in sync before composition is committed ## Testing - Not run locally: `pnpm` is not available in this environment, so package build/tests could not be executed here. Fixes #11515 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Editor mounting tolerates missing/null elements and validates input to avoid errors. * Text creation/update consistently targets the refreshed element to prevent mismatches. * Inline editor listens for IME composition events and schedules layout/size recalculation (with proper cleanup) so sizing stays in sync. * **Tests** * Added an integration test verifying layout/size updates during IME composition events. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> Co-authored-by: DarkSky <darksky2048@gmail.com> |
||
|
|
7138fea9db | fix: test stability | ||
|
|
156cfc7e76 |
fix(core): improve table header sorting logic in processTable function (#14797)
Bug Resolved #14795 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Made row and column sorting deterministic when items share the same order value, reducing unexpected cell shifts. * Adjusted comparator behavior to preserve tied-order grouping, which may change displayed column/row sequence in edge cases. * Improved consistency of table rendering and cell placement across refreshes and edits. <!-- end of auto-generated comment: release notes by coderabbit.ai -->v2026.4.7-canary.925 |
||
|
|
2ca4973167 |
fix(editor): make repeated "Cancel line number" clicks work in code blocks (#14804)
Fixes #13555 https://github.com/user-attachments/assets/12e55c21-080c-4c69-9780-893ccad25b45 ## Summary - make the code block More popup reactive to `wrap` and `lineNumber` prop updates - read the latest toggle state at click time so same-menu double toggles do not reuse stale closures - add e2e coverage for wrap and line number toggling twice without closing the More menu ## Bug Reason - the code block More popup was rendered as a static portal, so it stayed open without re-rendering after the first toggle - the `Cancel line number` and `Wrap` menu actions captured render-time state in their click handlers - after the first click updated the model, a second click in the same open menu reused stale state and wrote the same value again, so nothing changed visually ## Testing - yarn workspace @affine-test/blocksuite test e2e/code/crud.spec.ts <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Menu toggles now read and update the current wrap and line-number states reliably. * **Refactor** * Replaced inline popup rendering with a dedicated more-menu component for the code toolbar. * **Style** * Prevented text selection on menu action elements for smoother interaction. * **Tests** * Added e2e tests for wrap and line-number toggle flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a1ae7d11a3 | feat(core): add integration panel test | ||
|
|
f41bc2d5c3 |
fix(editor): restore grouped manual ordering for kanban and arrange (#14630)
Fixes #14531, where mannual vertical order is broken [Root Cause](https://github.com/toeverything/AFFiNE/issues/14531#issuecomment-4052422436) - Restored manual row/card sorting when building grouped kanban data. - Reapplied `sortRow(...)` to each group before rendering `group.rows`. - Fixed group/board arrange to reorder from the full group list, including hidden or empty groups. - Preserved consistent ordering between the settings panel and persisted `groupProperties`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Consolidated internal grouping and sorting logic to ensure consistent ordering across grouped views; visible behavior unchanged. * Moving groups or cards now uses a single, consistent ordering approach to avoid intermittent ordering differences. * **Tests** * Added tests to verify manual per-group card order is applied and preserved when moving cards between groups. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DarkSky <darksky2048@gmail.com> |
||
|
|
e3391c0577 |
feat: redirect account click & OAuth to Calendar settings (#14693)
### PR Description * clicking a linked calendar account now switches settings to Workspace Integrations and opens the Calendar settings directly * calendar OAuth returns now land on Workspace Integrations with the Calendar settings opened instead of the homepage * Improves UX by reducing friction when managing calendar integrations https://www.loom.com/share/49fa5c448ce049659877beb42d7bd81a <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Calendar integration settings can now be opened automatically (including from OAuth redirects) and workspace settings support a scroll-to-anchor. * Integration account rows are now clickable for quick access to settings. * **Improvements** * Enhanced visual feedback with interactive hover and focus states for integration controls. * **Tests** * Added tests covering the OAuth redirect behavior and workspace settings scroll/open handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DarkSky <darksky2048@gmail.com> |