fleather icon indicating copy to clipboard operation
fleather copied to clipboard

After update from 1.25.1 to 1.26.0 long form is scrolled to Fleather editor on every state change

Open DmitrySikorsky opened this issue 2 months ago • 1 comments

Steps to Reproduce

  1. In my case I have a long form wrapped with SingleChildScrollView and BlocBuilder.
  2. Every time state is changed, the form is scrolled to the Fleather editor even it doesn't have focus.
  3. Adding if (!_hasFocus) return; in the beginning of void _showCaretOnScreen([bool withAnimation = true]) fixes the problem but might have undesired consequences.
  4. It works fine on 1.25.1.

Environment

  • Web, Windows.
  • Flutter version [e.g. 3.35.6]
  • Fleather version [e.g. 1.26.0]

Thank you for the great work!

DmitrySikorsky avatar Oct 27 '25 14:10 DmitrySikorsky

Can you please post a short code sample that produced the issue?

amantoux avatar Oct 29 '25 08:10 amantoux

Closing it for now but feel free to reopen if you had a minimal reproducible sample code.

Amir-P avatar Nov 20 '25 19:11 Amir-P

Hi, I found where the problem is located and prepared code that reproduces it.

import 'package:fleather/fleather.dart';
import 'package:flutter/material.dart';
import 'package:parchment/codecs.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'Fleather Bug Demo', home: const FleatherBugDemoPage());
  }
}

class FleatherBugDemoPage extends StatefulWidget {
  const FleatherBugDemoPage({super.key});

  @override
  State<FleatherBugDemoPage> createState() => _FleatherBugDemoPageState();
}

class _FleatherBugDemoPageState extends State<FleatherBugDemoPage> {
  final FleatherController _controller = FleatherController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Fleather Bug Demo')),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            FleatherToolbar.basic(controller: _controller),
            SizedBox(
              height: 400,
              child: FleatherEditor(controller: _controller, padding: const EdgeInsets.all(16.0)),
            ),
            SizedBox(height: 1000),
            Text('Scroll 1'),
            SizedBox(height: 1000),
            Text('Scroll 2'),
            SizedBox(height: 1000),
            Text('Scroll 3'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(onPressed: _onButtonPressed, child: const Icon(Icons.error)),
    );
  }

  void _onButtonPressed() {
    _controller.replaceDocument(Markdown.fromMarkdown('Hello!'));
  }
}

extension FleatherControllerExtension on FleatherController {
  void replaceDocument(ParchmentDocument newDocument) {
    Delta delta = newDocument.toDelta();
    Delta batch = Delta()..delete(document.length);

    for (Operation operation in delta.toList()) {
      batch.push(operation);
    }

    compose(batch);
  }
}

class Markdown {
  static ParchmentDocument fromMarkdown(String? markdown) {
    return ParchmentDocument.fromDelta(ParchmentMarkdownCodec().decode(markdown ?? '').toDelta());
  }
}

Steps to reproduce:

  1. Run the app.
  2. Scroll down to see the 'Scroll 3' text.
  3. Press the floating button.
  4. Result: the form is scrolled to the top.

In my case, I store the text as markdown. When it is changed AND the Fleather editor doesn't have focus, I replace the document with the new content. Before 1.26 it worked fine, but after 1.26 I get this scroll.

I believe that since I didn't call requestFocus, I do not expect changing the editor's content to have any impact on the scroll position.

@Amir-P could you reopen the issue because I do not have permission to do so.

DmitrySikorsky avatar Nov 21 '25 09:11 DmitrySikorsky