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

Problem with the keyboard toolbar and the leading and trailing actions #187

Open
vmoscardo opened this issue Jul 11, 2024 · 3 comments
Open

Comments

@vmoscardo
Copy link

vmoscardo commented Jul 11, 2024

RichTextBooks
RichTextKitDemo
I'm an amateur iOS developer. I'm using RichTextKit framework as a rich text editor in my app, because is a very easy and good editor, but I have a problem with the keyboard toolbar and the leading and trailing actions.

Adapting and using the demo included in RichTextKit, all works properly, but including as a package to the last version 0.9.9, the richTextKit in my app, I'm not able to get the keyboard toolbar working properly.

As you can see in the attached images, the first lead and trail actions, are repeated, but in the demo app all works in the right way. Any idea about what can be the problem?.

I attach the view used in my app, quite similar the view used in the demo app.

@danielsaidi
Copy link
Owner

Hi @vmoscardo

Thank you for reporting this. I will take a look when I get time.

Please, consider wrapping the code in a ``` block and adjust the indentation to make it easier for people to read it and contribute.

@vmoscardo
Copy link
Author

import SwiftUI
import RichTextKit

struct EditorScreen: View {
    @Environment(\.presentationMode) var presentationMode
   @ObservedObject var context: RichTextContext
    #if os(iOS)
    @Environment(\.horizontalSizeClass) var sizeClass
    #endif
    @Binding var richText: NSAttributedString
    var disableAutocorrection: Bool
//
    var body: some View {
        VStack {
            editor
            keyboardToolbar
            #if os(iOS)
            if self.sizeClass != .compact {
                formatToolbar // se visualiza la barra formato para iPad
            } // end of if sizeClass
            #endif
            #if os(macOS)
            formatToolbar
            #endif
           } // end of VStack
        .richTextFormatToolbarStyle(RichTextFormatToolbar.Style(padding: 4, spacing: 4))
           .padding(10)
           .background(Color.primary.opacity(0.15))
           .environmentObject(context)
    } // end of var body
} // end of struct EditorScreen

private extension EditorScreen {
    #if os(iOS)
    var editor: some View {
        RichTextEditor(text: $richText, context: context,
                       config: .init(isScrollingEnabled: true,
                                     autocapitalizationType: .sentences,
                                     spellCheckingType: .no)) {
            $0.textContentInset = CGSize(width: 10, height: 20)
        } // end of RichTextEditor
        .autocorrectionDisabled(disableAutocorrection)
        .background(Material.regular)
        .cornerRadius(5)
        .focusedValue(\.richTextContext, context)
    } // end of var editor
    #endif
    //
    #if os(macOS)
    var editor: some View {
        RichTextEditor(text: $richText, context: context) {
            $0.textContentInset = CGSize(width: 10, height: 20)
        } // end of RichTextEditor
        .autocorrectionDisabled(disableAutocorrection)
        .background(Material.regular)
        .cornerRadius(5)
        .focusedValue(\.richTextContext, context)
    } // end of var editor
    #endif
    //
    var keyboardToolbar: some View {
        RichTextKeyboardToolbar(
            context: context,
            style: style,
            configuration: config,
            leadingActions: leadActions,
            trailingActions: trailActions,
            leadingButtons: {},
            /*
            leadingButtons: {Button(action: {
                printToolbar()},
            label: {Image(systemName: "arrowshape.turn.up.left")})},
             */
            trailingButtons: {},
            richTextFormatSheet: {
                $0.font(.body)
                } // end of closure richTextFormatSheet
        ) // end of RichTextKeyboardToolbar
    } // end of var keyboardToolbar
    //
    var style: RichTextKeyboardToolbarStyle {
        var style = RichTextKeyboardToolbarStyle()
        style.itemSpacing = 15
        style.shadowColor = Color.primary.opacity(0.15)
        return style
    } // end of var style
    //
    var config: RichTextKeyboardToolbarConfiguration {
        var config = RichTextKeyboardToolbarConfiguration()
        config.alwaysDisplayToolbar = true
        return config
    } // end of var config
    //
    var leadActions: [RichTextAction] {
        [.undo, .redo, .copy]
    } // end of var leadActions
    //
    var trailActions: [RichTextAction] {
        [.stepFontSize(points: 2),
         .stepFontSize(points: -2),
         .stepIndent(points: 20),
         .stepIndent(points: -20),
         .dismissKeyboard]
    } // end of var trailActions
    //
    var formatToolbar: some View {
        RichTextFormatToolbar(context: context,
        config: RichTextFormatToolbar.Configuration.init(
            alignments: [],
            colorPickers: [.foreground, .background],
            colorPickersDisclosed: [],
            fontPicker: false,
            fontSizePicker: false,
            indentButtons: false,
            lineSpacingPicker: false,
           styles: [],
            superscriptButtons: false
        ) // end of Configuration
        ) // end of RichTextFormatToolbar
    } // end of format
    //
    func printToolbar() {
        print("toolbar \(keyboardToolbar)")
        print("toolbar")
        print("format toolbar \(formatToolbar)")
    }
} // end of extension EditorScreen

@vmoscardo
Copy link
Author

vmoscardo commented Jul 13, 2024

RichTextEditorBooks OK
I have found a workaround analyzing the implementation of module RichTextKeyboardToolbar.swift. Using @ViewBuilder to implement leadButtons and trailButtons for every action. Using leadActions and trailActions only with a unique action. I attach the code of the view.

import SwiftUI
import RichTextKit

struct EditorScreen: View {
   @Environment(\.presentationMode) var presentationMode
   @ObservedObject var context: RichTextContext
    #if os(iOS)
    @Environment(\.horizontalSizeClass) var sizeClass
    #endif
    @Binding var richText: NSAttributedString
    var disableAutocorrection: Bool
//
    var body: some View {
        VStack {
            editor
            keyboardToolbar
            #if os(iOS)
            if self.sizeClass != .compact {
                formatToolbar // se visualiza la barra formato para iPad
            } // end of if sizeClass
            #endif
            #if os(macOS)
            formatToolbar
            #endif
           } // end of VStack
        .richTextFormatToolbarStyle(RichTextFormatToolbar.Style(padding: 4, spacing: 4))
           .padding(10)
           .background(Color.primary.opacity(0.15))
           .environmentObject(context)
 //          .viewDebug()
    } // end of var body
} // end of struct EditorScreen

private extension EditorScreen {
    #if os(iOS)
    var editor: some View {
        RichTextEditor(text: $richText, context: context,
                       config: .init(isScrollingEnabled: true,
                                     autocapitalizationType: .sentences,
                                     spellCheckingType: .no)) {
            $0.textContentInset = CGSize(width: 10, height: 20)
        } // end of RichTextEditor
        .autocorrectionDisabled(disableAutocorrection)
        .background(Material.regular)
        .cornerRadius(5)
        .focusedValue(\.richTextContext, context)
    } // end of var editor
    #endif
    //
    #if os(macOS)
    var editor: some View {
        RichTextEditor(text: $richText, context: context) {
            $0.textContentInset = CGSize(width: 10, height: 20)
        } // end of RichTextEditor
        .autocorrectionDisabled(disableAutocorrection)
        .background(Material.regular)
        .cornerRadius(5)
        .focusedValue(\.richTextContext, context)
    } // end of var editor
    #endif
    //
    var keyboardToolbar: some View {
        RichTextKeyboardToolbar(
            context: context,
            style: style,
            configuration: config,
            leadingActions: leadActions,
            trailingActions: trailActions,
            leadingButtons: {
                leadingViewUndo
                leadingViewRedo},
            trailingButtons: {
                trailingViewIncrFontsize
                trailingViewDecrFontsize
                trailingViewIncrIndent
                trailingViewDecrIndent},
            richTextFormatSheet: {
                $0.font(.body)
                } // end of closure richTextFormatSheet
        ) // end of RichTextKeyboardToolbar
    } // end of var keyboardToolbar
    //
    var style: RichTextKeyboardToolbarStyle {
        var style = RichTextKeyboardToolbarStyle()
        style.itemSpacing = 15
        style.shadowColor = Color.primary.opacity(0.15)
        return style
    } // end of var style
    //
    var config: RichTextKeyboardToolbarConfiguration {
        var config = RichTextKeyboardToolbarConfiguration()
        config.alwaysDisplayToolbar = true
        return config
    } // end of var config
    //
    @ViewBuilder
    var leadingViewUndo: some View {
        RichTextAction.ButtonStack(
            context: context,
            actions: leadActionUndo,
            spacing: style.itemSpacing
        )
    } // end of leadingViewUndo
    //
    @ViewBuilder
    var leadingViewRedo: some View {
        RichTextAction.ButtonStack(
            context: context,
            actions: leadActionRedo,
            spacing: style.itemSpacing
        )
    } // end of leadingViewRedo
    //
    var leadActionUndo: [RichTextAction] {
        [.undo]
    } // end of var leadActions
    //
    var leadActionRedo: [RichTextAction] {
        [.redo]
    } // end of var leadActions
    //
    var leadActions: [RichTextAction] {
        [.copy]
    } // end of var leadActions
    //
    var trailActions: [RichTextAction] {
        [.dismissKeyboard]
    } // end of var trailActions
    //
    var trailActionIncrFontSize: [RichTextAction] {
        [.stepFontSize(points: 2)]
    } // end of var trailActionIncrFontSize
    //
    var trailActionDecrFontSize: [RichTextAction] {
        [.stepFontSize(points: -2)]
    } // end of var trailActionDecrFontSize
    //
    var trailActionIncrIndent: [RichTextAction] {
        [.stepIndent(points: 20)]
    } // end of var trailActionIncrIndent
    //
    var trailActionDecrIndent: [RichTextAction] {
        [.stepIndent(points: -20)]
    } // end of var trailActionDecrIndent
    //
    @ViewBuilder
    var trailingViewIncrFontsize: some View {
        RichTextAction.ButtonStack(
            context: context,
            actions: trailActionIncrFontSize,
            spacing: style.itemSpacing
        )
    } // end of trailingViewIncrFontsize
    //
    @ViewBuilder
    var trailingViewDecrFontsize: some View {
        RichTextAction.ButtonStack(
            context: context,
            actions: trailActionDecrFontSize,
            spacing: style.itemSpacing
        )
    } // end of trailingViewDecrFontsize
    //
    @ViewBuilder
    var trailingViewIncrIndent: some View {
        RichTextAction.ButtonStack(
            context: context,
            actions: trailActionIncrIndent,
            spacing: style.itemSpacing
        )
    } // end of trailingViewIncrIndent
    //
    @ViewBuilder
    var trailingViewDecrIndent: some View {
        RichTextAction.ButtonStack(
            context: context,
            actions: trailActionDecrIndent,
            spacing: style.itemSpacing
        )
    } // end of trailingViewDecrIndent
    //
    var formatToolbar: some View {
        RichTextFormatToolbar(context: context,
        config: RichTextFormatToolbar.Configuration.init(
            alignments: [],
            colorPickers: [.foreground, .background],
            colorPickersDisclosed: [],
            fontPicker: false,
            fontSizePicker: false,
            indentButtons: false,
            lineSpacingPicker: false,
           styles: [],
            superscriptButtons: false
        ) // end of Configuration
        ) // end of RichTextFormatToolbar
    } // end of formatToolbar
    //
} // end of extension EditorScreen

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