Skip to content

feat: add code block word wrap - #8915

Open
ocp1006 wants to merge 3 commits into
AppFlowy-IO:mainfrom
ocp1006:codex/code-block-word-wrap
Open

ocp1006 wants to merge 3 commits into
AppFlowy-IO:mainfrom
ocp1006:codex/code-block-word-wrap

Conversation

@ocp1006

@ocp1006 ocp1006 commented Aug 3, 2026

Copy link
Copy Markdown

Fixes #8914

Adds an opt-in, per-block Wrap code toggle for document code blocks on desktop and web. Existing and new blocks remain unwrapped by default.

  • Added integration coverage
  • Flutter analysis passes
  • Windows code-block tests pass (2/2)
  • Windows debug build passes
word-wrap

Summary by Sourcery

Add per-code-block word wrap support for document code blocks on desktop and web, including persistence of wrap state and integration into the existing code block component.

New Features:

  • Introduce a wrap toggle action for individual code blocks on desktop and web that lets users switch between wrapped and unwrapped long lines.
  • Persist the wrap state per code block node so that wrapping choices are retained across document navigation and reloads.

Enhancements:

  • Wrap the base code block component in an AppFlowy-specific builder to apply per-node style overrides such as line wrapping and line-number visibility.
  • Update editor configuration to use the new AppFlowy-specific code block component builder and export it through the plugins barrel file.
  • Add a shared initialization helper for desktop code block integration tests to ensure the workspace is fully loaded before running scenarios.

Documentation:

  • Add localized tooltip text for the new code wrap control across all supported languages.

Tests:

  • Extend desktop integration tests to cover independent code block wrapping behavior, visual size changes, and persistence of wrap state across documents.

@CLAassistant

CLAassistant commented Aug 3, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@sourcery-ai

sourcery-ai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Implements an opt-in, per-code-block line-wrapping feature on desktop/web by extending the code block component, wiring a new "Wrap code" toggle into the copy button actions, persisting the wrap state on the node, and adding integration coverage and translations for the new tooltip.

Sequence diagram for toggling code block wrap and re-rendering

sequenceDiagram
  actor User
  participant WrapCodeButton
  participant EditorState
  participant Node
  participant AppFlowyCodeBlockComponentBuilder
  participant CodeBlockComponentWidget

  User->>WrapCodeButton: tap FlowyIconButton.onPressed
  WrapCodeButton->>Node: read codeBlockWrapLines
  WrapCodeButton->>EditorState: transaction.updateNode(node, {wrap_lines: !codeBlockWrapLines})
  WrapCodeButton->>EditorState: apply(transaction)

  User->>AppFlowyCodeBlockComponentBuilder: trigger build(node)
  AppFlowyCodeBlockComponentBuilder->>Node: read codeBlockWrapLines
  AppFlowyCodeBlockComponentBuilder->>AppFlowyCodeBlockComponentBuilder: styleBuilder()
  AppFlowyCodeBlockComponentBuilder->>CodeBlockComponentWidget: create with CodeBlockStyle(wrapLines, showLineNumbers)
Loading

File-Level Changes

Change Details Files
Introduce an AppFlowy-specific code block component that supports per-node wrap-lines styling and configuration.
  • Add AppFlowyCodeBlockKeys with a wrap_lines attribute and a Node extension for reading the wrap state.
  • Implement AppFlowyCodeBlockComponentBuilder that decorates the base CodeBlockComponentBuilder and applies wrapLines and showLineNumbers overrides to CodeBlockStyle based on the node attribute.
  • Expose the new code block component via the plugins barrel export for use across the editor.
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart
Wire the new AppFlowy code block component and wrap toggle into the existing editor configuration and code block actions.
  • Change the code block component builder type in editor_configuration.dart to AppFlowyCodeBlockComponentBuilder and construct it with existing style, configuration, padding, language picker, and copy button builders.
  • Update the code block copy button builder to return a Row containing an optional desktop/web-only wrap toggle button and the existing copy button.
  • Implement _WrapCodeButton as a stateful action that toggles the node's wrap_lines attribute via an editor transaction while updating visual state (selected, colors, tooltip, semantics).
  • Introduce a ValueKey for the wrap button for easier testing and interaction.
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_configuration.dart
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_copy_button.dart
Add integration coverage to verify per-block wrap behavior, persistence, and defaults in the desktop editor.
  • Refactor common desktop code block test initialization into a shared _initializeCodeBlockTest helper that waits for the Getting Started page to load.
  • Update the existing code block language selector test setup to use the new initializer and editor helpers.
  • Add a new integration test that creates two code blocks with long lines, verifies default unwrapped state and scroll behavior, toggles wrapping on one block and asserts per-block styling and height changes, then navigates away and back to confirm persistence and ability to toggle off.
  • Use the wrap button key and CodeBlockComponentWidget to locate widgets and assert node attributes, styles, tooltips, and button selection state.
frontend/appflowy_flutter/integration_test/desktop/uncategorized/code_block_language_selector_test.dart
Add localization entries for the wrap-code feature tooltip across all supported languages.
  • Introduce or update the document_codeBlock_wrapTooltip translation key in all locale JSON files so the wrap button tooltip is localized.
  • Ensure the new key aligns with existing document/code block translation structure across locales.
frontend/resources/translations/ar-SA.json
frontend/resources/translations/ca-ES.json
frontend/resources/translations/ckb-KU.json
frontend/resources/translations/cs-CZ.json
frontend/resources/translations/de-DE.json
frontend/resources/translations/en-GB.json
frontend/resources/translations/en-US.json
frontend/resources/translations/es-VE.json
frontend/resources/translations/eu-ES.json
frontend/resources/translations/fa.json
frontend/resources/translations/fr-CA.json
frontend/resources/translations/fr-FR.json
frontend/resources/translations/ga-IE.json
frontend/resources/translations/he.json
frontend/resources/translations/hu-HU.json
frontend/resources/translations/id-ID.json
frontend/resources/translations/it-IT.json
frontend/resources/translations/ja-JP.json
frontend/resources/translations/ko-KR.json
frontend/resources/translations/pl-PL.json
frontend/resources/translations/pt-BR.json
frontend/resources/translations/pt-PT.json
frontend/resources/translations/ru-RU.json
frontend/resources/translations/sv-SE.json
frontend/resources/translations/th-TH.json
frontend/resources/translations/tr-TR.json
frontend/resources/translations/uk-UA.json
frontend/resources/translations/vi-VN.json
frontend/resources/translations/vi.json
frontend/resources/translations/zh-CN.json
frontend/resources/translations/zh-TW.json

Assessment against linked issues

Issue Objective Addressed Explanation
#8914 Add an opt-in Wrap code toggle to document code blocks on desktop and web, keeping blocks unwrapped by default.
#8914 Persist the wrap/unwrapped preference per code block in the document model so that each block can wrap independently and restores its state when revisited.

Possibly linked issues

  • #FR: PR adds the per-block Wrap code toggle with persistence and default unwrapped behavior exactly as the issue requests.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

🥷 Ninja i18n – 🎉 Translations have been successfully updated

@ocp1006
ocp1006 marked this pull request as ready for review August 3, 2026 21:06

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In AppFlowyCodeBlockComponentBuilder.build, constructing a new CodeBlockStyle from scratch instead of deriving from baseStyle risks silently dropping any additional fields added to CodeBlockStyle later; if a copyWith or similar exists, consider using it and overriding only showLineNumbers/wrapLines.
  • The integration test uses hard-coded node paths like [0] and [1] to assert wrapLines; if the document structure changes, these may become brittle, so consider using a helper to locate code block nodes by type or attributes instead of fixed indices.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `AppFlowyCodeBlockComponentBuilder.build`, constructing a new `CodeBlockStyle` from scratch instead of deriving from `baseStyle` risks silently dropping any additional fields added to `CodeBlockStyle` later; if a `copyWith` or similar exists, consider using it and overriding only `showLineNumbers`/`wrapLines`.
- The integration test uses hard-coded node paths like `[0]` and `[1]` to assert `wrapLines`; if the document structure changes, these may become brittle, so consider using a helper to locate code block nodes by type or attributes instead of fixed indices.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FR] Add per-block word wrap for code blocks

2 participants