Skip to content

Commit e3a99d0

Browse files
authored
Fix text alignment issue (#63)
* Fix text alignment issue * remove unused file * added background color discloser row * fix text alignment is not updading span properly * Fix init with json was not ablle to add all style
1 parent 0675992 commit e3a99d0

21 files changed

+162
-501
lines changed

RichEditorDemo/RichEditorDemo/ContentView.swift

+45-39
Original file line numberDiff line numberDiff line change
@@ -92,59 +92,65 @@ struct ContentView: View {
9292

9393
var toolBarGroup: some View {
9494
return Group {
95-
RichTextExportMenu.init(
96-
formatAction: { format in
97-
exportFormat = format
98-
},
99-
otherOptionAction: { format in
100-
otherExportFormat = format
101-
}
102-
)
103-
#if !os(macOS)
95+
RichTextExportMenu.init(
96+
formatAction: { format in
97+
exportFormat = format
98+
},
99+
otherOptionAction: { format in
100+
otherExportFormat = format
101+
}
102+
)
103+
#if !os(macOS)
104104
.frame(width: 25, alignment: .center)
105105
#endif
106-
Button(
107-
action: {
108-
print("Exported JSON == \(state.outputAsString())")
109-
},
110-
label: {
111-
Image(systemName: "printer.inverse")
112-
}
113-
)
114-
#if !os(macOS)
115-
.frame(width: 25, alignment: .center)
116-
#endif
117-
Toggle(isOn: $isInspectorPresented) {
118-
Image.richTextFormatBrush
119-
.resizable()
120-
.aspectRatio(1, contentMode: .fit)
106+
Button(
107+
action: {
108+
print("Exported JSON == \(state.outputAsString())")
109+
},
110+
label: {
111+
Image(systemName: "printer.inverse")
121112
}
122-
#if !os(macOS)
113+
)
114+
#if !os(macOS)
123115
.frame(width: 25, alignment: .center)
124-
#endif
116+
#endif
117+
Toggle(isOn: $isInspectorPresented) {
118+
Image.richTextFormatBrush
119+
.resizable()
120+
.aspectRatio(1, contentMode: .fit)
125121
}
122+
#if !os(macOS)
123+
.frame(width: 25, alignment: .center)
124+
#endif
125+
}
126126
}
127127

128128
func getBindingAlert() -> Binding<Bool> {
129-
.init(get: { exportFormat != nil || otherExportFormat != nil }, set: { newValue in
130-
exportFormat = nil
131-
otherExportFormat = nil
132-
})
129+
.init(
130+
get: { exportFormat != nil || otherExportFormat != nil },
131+
set: { newValue in
132+
exportFormat = nil
133+
otherExportFormat = nil
134+
})
133135
}
134136

135137
func submit() {
136138
guard !fileName.isEmpty else { return }
137139
var path: URL?
138140

139141
if let exportFormat {
140-
path = try? exportService.generateExportFile(withName: fileName, content: state.attributedString, format: exportFormat)
142+
path = try? exportService.generateExportFile(
143+
withName: fileName, content: state.attributedString,
144+
format: exportFormat)
141145
}
142146
if let otherExportFormat {
143147
switch otherExportFormat {
144148
case .pdf:
145-
path = try? exportService.generatePdfExportFile(withName: fileName, content: state.attributedString)
149+
path = try? exportService.generatePdfExportFile(
150+
withName: fileName, content: state.attributedString)
146151
case .json:
147-
path = try? exportService.generateJsonExportFile(withName: fileName, content: state.richText)
152+
path = try? exportService.generateJsonExportFile(
153+
withName: fileName, content: state.richText)
148154
}
149155
}
150156
if let path {
@@ -153,14 +159,14 @@ struct ContentView: View {
153159
}
154160
}
155161

156-
private extension ContentView {
162+
extension ContentView {
157163

158164
var isMac: Bool {
159-
#if os(macOS)
160-
true
161-
#else
162-
false
163-
#endif
165+
#if os(macOS)
166+
true
167+
#else
168+
false
169+
#endif
164170
}
165171

166172
var colorPickers: [RichTextColor] {

Sources/RichEditorSwiftUI/Alignment/RichTextAlignment.swift

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ public enum RichTextAlignment: String, CaseIterable, Codable, Equatable, Identif
4242
case right
4343
}
4444

45+
public extension RichTextAlignment {
46+
func getTextSpanStyle() -> RichTextSpanStyle {
47+
return .align(self)
48+
}
49+
}
50+
4551
public extension Collection where Element == RichTextAlignment {
4652

4753
static var all: [Element] { RichTextAlignment.allCases }

Sources/RichEditorSwiftUI/BaseFoundation/RichTextCoordinator.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ open class RichTextCoordinator: NSObject {
7676
super.init()
7777
self.textView.delegate = self
7878
subscribeToUserActions()
79-
80-
// observerAttributes()
8179
}
8280
#if canImport(UIKit)
8381

@@ -237,6 +235,8 @@ extension RichTextCoordinator {
237235
sync(&context.fontName, with: font.fontName)
238236
sync(&context.fontSize, with: font.pointSize)
239237
sync(&context.isEditingText, with: textView.isFirstResponder)
238+
sync(&context.paragraphStyle, with: textView.richTextParagraphStyle ?? .default)
239+
sync(&context.textAlignment, with: textView.richTextAlignment ?? .left)
240240

241241
let styles = textView.richTextStyles
242242
RichTextStyle.allCases.forEach {

Sources/RichEditorSwiftUI/Components/RichTextViewComponent+Alignment.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public extension RichTextViewComponent {
2323

2424
/// Set the text alignment.
2525
func setRichTextAlignment(_ alignment: RichTextAlignment) {
26-
if richTextAlignment == alignment { return }
26+
// if richTextAlignment == alignment { return }
2727
let style = NSMutableParagraphStyle(
2828
from: richTextParagraphStyle,
2929
alignment: alignment

Sources/RichEditorSwiftUI/Data/Models/RichAttributes+RichTextAttributes.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ extension RichAttributes {
3131
}
3232

3333
if let fontName = self.font {
34-
font = font.updateFontName(with: fontName)
34+
let size = font.pointSize
35+
let newFont = FontRepresentable(name: fontName, size: size)
36+
if let newFont {
37+
font = newFont
38+
}
3539
}
3640

3741
// Apply bold and italic styles

Sources/RichEditorSwiftUI/Data/Models/RichAttributes.swift

+33-33
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ extension RichAttributes {
212212
styles.append(.background(.init(hex: background)))
213213
}
214214
if let align = align {
215-
styles.append(.align(align))
215+
styles.append(align.getTextSpanStyle())
216216
}
217217
return styles
218218
}
@@ -250,7 +250,7 @@ extension RichAttributes {
250250
styles.insert(.background(Color(hex: background)))
251251
}
252252
if let align = align {
253-
styles.insert(.align(align))
253+
styles.insert(align.getTextSpanStyle())
254254
}
255255
return styles
256256
}
@@ -318,38 +318,38 @@ internal func getRichAttributesFor(styles: [RichTextSpanStyle]) -> RichAttribute
318318

319319
for style in styles {
320320
switch style {
321-
case .bold:
322-
bold = true
323-
case .italic:
324-
italic = true
325-
case .underline:
326-
underline = true
327-
case .strikethrough:
328-
strike = true
329-
case .h1:
330-
header = .h1
331-
case .h2:
332-
header = .h2
333-
case .h3:
334-
header = .h3
335-
case .h4:
336-
header = .h4
337-
case .h5:
338-
header = .h5
339-
case .h6:
340-
header = .h6
341-
case .bullet(let indentIndex):
342-
list = .bullet(indentIndex)
343-
indent = indentIndex
344-
case .default:
345-
header = .default
346-
case .size(let fontSize):
347-
size = fontSize
348-
case .font(let name):
349-
font = name
350-
case .color(let textColor):
321+
case .bold:
322+
bold = true
323+
case .italic:
324+
italic = true
325+
case .underline:
326+
underline = true
327+
case .strikethrough:
328+
strike = true
329+
case .h1:
330+
header = .h1
331+
case .h2:
332+
header = .h2
333+
case .h3:
334+
header = .h3
335+
case .h4:
336+
header = .h4
337+
case .h5:
338+
header = .h5
339+
case .h6:
340+
header = .h6
341+
case .bullet(let indentIndex):
342+
list = .bullet(indentIndex)
343+
indent = indentIndex
344+
case .default:
345+
header = .default
346+
case .size(let fontSize):
347+
size = fontSize
348+
case .font(let name):
349+
font = name
350+
case .color(let textColor):
351351
color = textColor?.hexString
352-
case .background(let backgroundColor):
352+
case .background(let backgroundColor):
353353
background = backgroundColor?.hexString
354354
case .align(let alignment):
355355
align = alignment

Sources/RichEditorSwiftUI/Format/RichTextFormat+Sidebar.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,13 @@ public extension RichTextFormat {
6767
Spacer()
6868
fontSizePicker(for: context)
6969
}
70+
headerPicker(context: context)
7071
}
7172

7273
Divider()
7374

7475
SidebarSection {
75-
alignmentPicker(value: $context.textAlignment)
76+
alignmentPicker(context: context)
7677
.onChangeBackPort(of: context.textAlignment) { newValue in
7778
context.updateStyle(style: .align(newValue))
7879
}

Sources/RichEditorSwiftUI/Format/RichTextFormat+Toolbar.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private extension RichTextFormat.Toolbar {
133133
#if !macOS
134134
headerPicker(context: context)
135135
#endif
136-
alignmentPicker(value: $context.textAlignment)
136+
alignmentPicker(context: context)
137137
// superscriptButtons(for: context, greedy: false)
138138
// indentButtons(for: context, greedy: false)
139139
}

Sources/RichEditorSwiftUI/Format/RichTextFormat+ToolbarConfig.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ public extension RichTextFormat {
1717
headers: [HeaderType] = .all,
1818
alignments: [RichTextAlignment] = .all,
1919
colorPickers: [RichTextColor] = [.foreground],
20-
colorPickersDisclosed: [RichTextColor] = [.background],
20+
colorPickersDisclosed: [RichTextColor] = [],
2121
fontPicker: Bool = true,
2222
fontSizePicker: Bool = true,
2323
indentButtons: Bool = true,
2424
lineSpacingPicker: Bool = false,
25-
styles: [RichTextStyle] = [.bold, .italic, .underline, .strikethrough],
25+
styles: [RichTextStyle] = .all,
2626
superscriptButtons: Bool = true
2727
) {
2828
self.headers = headers

Sources/RichEditorSwiftUI/Format/RichTextFormatToolbarBase.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ extension RichTextFormatToolbarBase {
2929

3030
@ViewBuilder
3131
func alignmentPicker(
32-
value: Binding<RichTextAlignment>
32+
context: RichEditorState
3333
) -> some View {
3434
if !config.alignments.isEmpty {
3535
RichTextAlignment.Picker(
36-
selection: value,
36+
selection: context.textAlignmentBinding(),
3737
values: config.alignments
3838
)
3939
.pickerStyle(.segmented)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// RichEditorState+TextAlignment.swift
3+
// RichEditorSwiftUI
4+
//
5+
// Created by Divyesh Vekariya on 29/12/24.
6+
//
7+
8+
import SwiftUI
9+
10+
public extension RichEditorState {
11+
12+
/// Get a binding for a certain TextAlignment style.
13+
func textAlignmentBinding() -> Binding<RichTextAlignment> {
14+
Binding(
15+
get: { self.currentTextAlignment() },
16+
set: { self.setTextAlignmentStyle($0) }
17+
)
18+
}
19+
20+
/// Check whether or not the context has a certain TextAlignment style.
21+
func currentTextAlignment() -> RichTextAlignment {
22+
return textAlignment
23+
}
24+
25+
/// Set whether or not the context has a certain TextAlignment style.
26+
func setTextAlignmentStyle(
27+
_ alignment: RichTextAlignment
28+
) {
29+
guard alignment != textAlignment else { return }
30+
updateStyle(style: alignment.getTextSpanStyle())
31+
setTextAlignmentInternal(alignment: alignment)
32+
}
33+
34+
func setTextAlignmentInternal(
35+
alignment: RichTextAlignment
36+
) {
37+
guard alignment != textAlignment else { return }
38+
textAlignment = alignment
39+
}
40+
}
41+

0 commit comments

Comments
 (0)