Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text selection and Text-to-speech #267

Closed
MarcVanDaele90 opened this issue Dec 6, 2024 · 2 comments
Closed

Text selection and Text-to-speech #267

MarcVanDaele90 opened this issue Dec 6, 2024 · 2 comments

Comments

@MarcVanDaele90
Copy link

Hi,

I'm using your package on web and, apart from issue #235 , text selections works pretty well.
Now, I want to be able to read aloud the selected text (eg using the read aloud chrome extension).

Typically, when text is selected inside other, non-pdf, SelectionAreas, I can right click and see the "read aloud selected text" action in the context menu. This does not happen when I select text in pdfrx.

Right now, I do the following : this works fine but there might be better/cleaner approaches?

                      onTextSelectionChange: (selection) {
                        selectText(selection.map((e)=>"${e.text}").join(" "));
                        ...
                      },

with

          html.DivElement? reusableDiv;
          void selectText(String text) {
            if (reusableDiv == null) {
              // Create a single hidden div
              reusableDiv = html.DivElement()
                ..id = 'text-to-select'
                ..style.display = 'block'
                ..style.position = 'absolute'
                ..style.opacity = '0'; // Make it invisible but still selectable
              html.document.body?.append(reusableDiv!);
            }
        
            // Add the div to the body
            html.document.body?.append(reusableDiv!);
        
            // Select the text programmatically
            final range = html.document.createRange();
            range.selectNodeContents(reusableDiv!);
            final selection = html.window.getSelection();
            selection?.removeAllRanges();
            selection?.addRange(range);
          }
@MarcVanDaele90
Copy link
Author

An alternative, and probably cleaner, approach is to add the following TTSTextWidget to the tree like
TTSTextWidget(text: _selectedText.map((e)=>"${e.text}").join(" "))
where _selectedText is set in the onTextSelectionChange

class TTSTextWidget extends StatefulWidget {
  final String text;

  const TTSTextWidget({Key? key, required this.text}) : super(key: key);

  @override
  _TTSTextWidgetState createState() => _TTSTextWidgetState();
}

class _TTSTextWidgetState extends State<TTSTextWidget> {
  late TextEditingController _controller;

  @override
  void initState() {
    super.initState();
    // Initialize the controller with the provided text
    _controller = TextEditingController(text: widget.text);
    // Select all text programmatically after the widget is built
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _controller.selection = TextSelection(baseOffset: 0, extentOffset: widget.text.length);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Offstage(
      offstage: true, // Hides the widget visually but keeps it in the widget tree
      child: SizedBox.shrink(
        child: TextField(
          controller: _controller,
          readOnly: true,
          decoration: const InputDecoration(border: InputBorder.none),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

Feel free to integrate this in pdfrx if you think this is useful!

@espresso3389
Copy link
Owner

Your approach seems good enough for me.
PDF's extracted text is sometimes inconsistent and breaks some words between lines but it's not fixable.........

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

No branches or pull requests

2 participants