Skip to content

Commit a9319e0

Browse files
committed
Fix undo redo for header, font and alignment
1 parent 63e1f54 commit a9319e0

File tree

7 files changed

+356
-149
lines changed

7 files changed

+356
-149
lines changed

Sources/RichEditorSwiftUI/UI/Context/RichEditorState+Header.swift

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,38 @@ import SwiftUI
99

1010
extension RichEditorState {
1111

12-
/// Get a binding for a certain style.
13-
public func headerBinding() -> Binding<HeaderType> {
14-
Binding(
15-
get: { self.currentHeader() },
16-
set: { self.setHeaderStyle($0) }
17-
)
18-
}
12+
/// Get a binding for a certain style.
13+
public func headerBinding() -> Binding<HeaderType> {
14+
Binding(
15+
get: { self.currentHeader() },
16+
set: { self.setStyle($0) }
17+
)
18+
}
1919

20-
/// Check whether or not the context has a certain header style.
21-
public func currentHeader() -> HeaderType {
22-
return headerType
23-
}
20+
/// Check whether or not the context has a certain header style.
21+
public func currentHeader() -> HeaderType {
22+
return headerType
23+
}
2424

25-
/// Set whether or not the context has a certain header style.
26-
public func setHeaderStyle(
27-
_ header: HeaderType
28-
) {
29-
guard header != headerType else { return }
30-
updateStyle(style: header.getTextSpanStyle())
31-
}
25+
/// Set whether or not the context has a certain header style.
26+
public func setStyle(
27+
_ header: HeaderType
28+
) {
29+
updateStyle(style: header.getTextSpanStyle())
30+
}
3231

32+
/// Set whether or not the context has a certain header style.
33+
public func setHeaderStyle(
34+
_ header: HeaderType
35+
) {
36+
actionPublisher.send(.setHeaderStyle(header.getTextSpanStyle()))
37+
setHeaderInternal(header: header)
38+
}
39+
40+
private func setHeaderInternal(
41+
header: HeaderType
42+
) {
43+
guard header != headerType else { return }
44+
headerType = header
45+
}
3346
}

Sources/RichEditorSwiftUI/UI/Context/RichEditorState+UndoRedoManager.swift renamed to Sources/RichEditorSwiftUI/UI/Context/RichEditorState+UndoManager.swift

Lines changed: 106 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//
2-
// RichEditorState+UndoRedoManager.swift
2+
// RichEditorState+UndoManager.swift
33
// RichEditorSwiftUI
44
//
55
// Created by Divyesh Vekariya on 06/01/25.
66
//
77

88
import Foundation
9+
import SwiftUI
910

1011
extension RichEditorState {
1112
func updateUndoRedoState() {
@@ -24,7 +25,7 @@ extension RichEditorState {
2425
// if let operation {
2526
// self.undoManager.registerUndoOperation(operation)
2627
// }
27-
// self.isOperationIsFromUser = false
28+
self.isOperationIsFromUser = false
2829
// self.operationRawText = self.attributedString.string
2930
updateUndoRedoState()
3031
}
@@ -46,7 +47,7 @@ extension RichEditorState {
4647
private func restoreState(for operation: RichTextOperation, isRedo: Bool) {
4748
setSelectedRange(range: operation.range)
4849
if isRedo {
49-
setCurrentAttributes(attributes: operation.attributes)
50+
// setCurrentAttributes(attributes: operation.attributes)
5051
}
5152

5253
switch operation.operationType {
@@ -78,7 +79,7 @@ extension RichEditorState {
7879
}
7980

8081
if !isRedo {
81-
setCurrentAttributes(attributes: undoManager.getPreviousAttributes())
82+
setCurrentAttributes(attributes: operation.previousAttributes)
8283
}
8384

8485
updateUndoRedoState()
@@ -89,16 +90,23 @@ extension RichEditorState {
8990
selectedRange = range
9091
}
9192
private func setCurrentAttributes(attributes: OperationAttributes) {
92-
activeStyles = attributes.activeStyles
93-
headerType = attributes.headerType
94-
textAlignment = attributes.textAlignment
95-
fontName = attributes.fontName
96-
fontSize = attributes.fontSize
97-
colors = attributes.colors
98-
lineSpacing = attributes.lineSpacing
99-
paragraphStyle = attributes.paragraphStyle
100-
// styles = attributes.styles
101-
link = attributes.link
93+
// let attributedStringCopy = NSMutableAttributedString(attributedString: attributes.attributedString)
94+
// attributedString = attributedStringCopy
95+
selectedRange = attributes.selectedRange
96+
headerType = attributes.headerType
97+
textAlignment = attributes.textAlignment
98+
fontName = attributes.fontName
99+
fontSize = attributes.fontSize
100+
lineSpacing = attributes.lineSpacing
101+
colors = attributes.colors
102+
highlightingStyle = attributes.highlightingStyle
103+
paragraphStyle = attributes.paragraphStyle
104+
styles = attributes.styles
105+
link = attributes.link
106+
highlightedRange = attributes.highlightedRange
107+
activeStyles = attributes.activeStyles
108+
activeAttributes = attributes.activeAttributes
109+
// rawText = attributes.rawText
102110
}
103111

104112
func getAttributedStringBy(adding: Bool, chars: String, at index: Int)
@@ -126,15 +134,17 @@ extension RichEditorState {
126134
return RichTextOperation(
127135
operationType: .addOrRemoveText(newText: newText, rawText: rawText, isAdded: isAdded),
128136
range: range,
129-
attributes: getCurrentAttributes()
137+
attributes: getCurrentAttributes(),
138+
previousAttributes: getPreviousAttributes()
130139
)
131140
}
132141

133142
func getOperationFor(style: RichTextSpanStyle, isAdded: Bool) -> RichTextOperation {
134143
return RichTextOperation(
135144
operationType: .addOrRemoveStyle(style: style, isAdded: isAdded),
136145
range: selectedRange,
137-
attributes: getCurrentAttributes()
146+
attributes: getCurrentAttributes(),
147+
previousAttributes: getPreviousAttributes()
138148
)
139149
}
140150

@@ -152,7 +162,8 @@ extension RichEditorState {
152162
return RichTextOperation(
153163
operationType: .setStyleStyle(previousStyle: previousStyle, newStyle: newStyle, isSet: isSet),
154164
range: selectedRange,
155-
attributes: getCurrentAttributes()
165+
attributes: getCurrentAttributes(),
166+
previousAttributes: getPreviousAttributes()
156167
)
157168
}
158169

@@ -176,25 +187,88 @@ extension RichEditorState {
176187
updateUndoRedoState()
177188
}
178189

179-
func registerUndoForSetStyle(previousStyle: RichTextSpanStyle?, newStyle: RichTextSpanStyle) {
190+
func registerUndoForSetStyle(newStyle: RichTextSpanStyle) {
191+
let previousStyle = getPreviousStyleFor(style: newStyle)
180192
let operation = getOperationForSetStyle(
181193
previousStyle: previousStyle, newStyle: newStyle, isSet: true)
182194
undoManager.registerUndoOperation(operation)
183195
updateUndoRedoState()
184196
}
185197

186-
private func getCurrentAttributes() -> OperationAttributes {
187-
return OperationAttributes(
188-
activeStyles: activeStyles,
189-
headerType: headerType,
190-
textAlignment: textAlignment,
191-
fontName: fontName,
192-
fontSize: fontSize,
193-
colors: colors,
194-
lineSpacing: lineSpacing,
195-
paragraphStyle: paragraphStyle,
196-
styles: styles,
197-
link: link
198-
)
199-
}
198+
private func getPreviousStyleFor(style: RichTextSpanStyle) -> RichTextSpanStyle? {
199+
var previousStyle: RichTextSpanStyle? = nil
200+
switch style {
201+
case .h1, .h2, .h3, .h4, .h5, .h6:
202+
previousStyle = previousHeaderType.getTextSpanStyle()
203+
case .size(_):
204+
previousStyle = .size(Int(previousFontSize))
205+
case .font(_):
206+
let fontName: String = previousFontName.isEmpty ? RichTextFont.PickerFont.standardSystemFontDisplayName : previousFontName
207+
previousStyle = .font(fontName)
208+
case .color(_):
209+
if let color = previousColors[.foreground] {
210+
previousStyle = .color(Color(color))
211+
} else {
212+
previousStyle = .color()
213+
}
214+
case .background(_):
215+
if let color = previousColors[.background] {
216+
previousStyle = .background(Color(color))
217+
} else {
218+
previousStyle = .background()
219+
}
220+
case .align(_):
221+
previousStyle = .align(previousTextAlignment)
222+
case .link(_):
223+
previousStyle = .link(previousLink)
224+
default:
225+
previousStyle = nil
226+
}
227+
return previousStyle
228+
}
229+
230+
private func getCurrentAttributes() -> OperationAttributes {
231+
let attributedString = NSMutableAttributedString(attributedString: attributedString)
232+
233+
return OperationAttributes(
234+
attributedString: attributedString,
235+
selectedRange: selectedRange,
236+
headerType: headerType,
237+
textAlignment: textAlignment,
238+
fontName: fontName,
239+
fontSize: fontSize,
240+
lineSpacing: lineSpacing,
241+
colors: colors,
242+
highlightingStyle: highlightingStyle,
243+
paragraphStyle: paragraphStyle,
244+
styles: styles,
245+
link: link,
246+
highlightedRange: highlightedRange,
247+
activeStyles: activeStyles,
248+
activeAttributes: activeAttributes,
249+
rawText: rawText
250+
)
251+
}
252+
253+
private func getPreviousAttributes() -> OperationAttributes {
254+
let previousAttributedString = NSMutableAttributedString(attributedString: previousAttributedString)
255+
return OperationAttributes(
256+
attributedString: previousAttributedString,
257+
selectedRange: previousSelectedRange,
258+
headerType: previousHeaderType,
259+
textAlignment: previousTextAlignment,
260+
fontName: previousFontName,
261+
fontSize: previousFontSize,
262+
lineSpacing: previousLineSpacing,
263+
colors: previousColors,
264+
highlightingStyle: previousHighlightingStyle,
265+
paragraphStyle: previousParagraphStyle,
266+
styles: previousStyles,
267+
link: previousLink,
268+
highlightedRange: previousHighlightedRange,
269+
activeStyles: previousActiveStyles,
270+
activeAttributes: previousActiveAttributes,
271+
rawText: previousRawText
272+
)
273+
}
200274
}

0 commit comments

Comments
 (0)