Skip to content

Commit d2f015c

Browse files
authored
Grid cell background fix (#298)
* Fixed background color of gridView to be same a container editorview * Fixed tests * Made BackgroundColorInheriting observable on attachment view * Made GridView BackgroundColorObserving
1 parent 7c32647 commit d2f015c

12 files changed

+113
-0
lines changed

Diff for: Proton/Sources/Swift/Attachment/Attachment.swift

+9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public protocol DynamicBoundsProviding: AnyObject {
2727
func sizeFor(attachment: Attachment, containerSize: CGSize, lineRect: CGRect) -> CGSize
2828
}
2929

30+
/// Denotes an `Attachment`content view that observes background color changes in `containerEditorView`
31+
public protocol BackgroundColorObserving where Self: UIView {
32+
func containerEditor(_ editor: EditorView, backgroundColorUpdated color: UIColor?, oldColor: UIColor?)
33+
}
34+
3035
/// Describes an object capable of providing offsets for the `Attachment`. The value is used to offset the `Attachment` when rendered alongside the text. This may
3136
/// be used to align the content baselines in `Attachment` content to that of it's container's content baselines.
3237
/// - Note:
@@ -598,6 +603,10 @@ open class Attachment: NSTextAttachment, BoundsObserving {
598603
guard let view = view,
599604
view.superview == nil else { return }
600605
editorView.richTextView.addSubview(view)
606+
if let backgroundColorInheriting = self.contentView as? BackgroundColorObserving,
607+
editorView.backgroundColor != nil {
608+
backgroundColorInheriting.containerEditor(editorView, backgroundColorUpdated: editorView.backgroundColor, oldColor: nil)
609+
}
601610

602611
if var editorContentView = contentView as? EditorContentView,
603612
editorContentView.delegate == nil {

Diff for: Proton/Sources/Swift/Editor/EditorView.swift

+11
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ open class EditorView: UIView {
440440
public override var backgroundColor: UIColor? {
441441
didSet {
442442
richTextView.backgroundColor = backgroundColor
443+
if backgroundColor != oldValue {
444+
updateBackgroundInheritingViews(color: backgroundColor, oldColor: backgroundColor)
445+
}
446+
delegate?.editor(self, didChangeBackgroundColor: backgroundColor, oldColor: oldValue)
443447
}
444448
}
445449

@@ -1278,6 +1282,13 @@ open class EditorView: UIView {
12781282
textViewDelegate.textViewDidChange?(richTextView)
12791283
return true
12801284
}
1285+
1286+
private func updateBackgroundInheritingViews(color: UIColor?, oldColor: UIColor?) {
1287+
let backgroundColorInheritingViews = attributedText.attachmentRanges.compactMap{ $0.attachment.contentView as? BackgroundColorObserving }
1288+
backgroundColorInheritingViews.forEach {
1289+
$0.containerEditor(self, backgroundColorUpdated: color, oldColor: oldColor)
1290+
}
1291+
}
12811292
}
12821293

12831294
extension EditorView {

Diff for: Proton/Sources/Swift/Editor/EditorViewDelegate.swift

+3
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ public protocol EditorViewDelegate: AnyObject {
134134
/// - Returns: `true` to delete, else `false`
135135
/// - Note: If either this or`Attachment`s property of `selectBeforeDelete` is `true`, the attachment will be shown as selected on backspace.
136136
func editor(_ editor: EditorView, shouldSelectAttachmentOnBackspace attachment: Attachment) -> Bool?
137+
138+
func editor(_ editor: EditorView, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?)
137139
}
138140

139141
public extension EditorViewDelegate {
@@ -155,4 +157,5 @@ public extension EditorViewDelegate {
155157
func editor(_ editor: EditorView, shouldSelectAttachmentOnBackspace attachment: Attachment) -> Bool? {
156158
return nil
157159
}
160+
func editor(_ editor: EditorView, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?) { }
158161
}

Diff for: Proton/Sources/Swift/Grid/View/GridCell.swift

+21
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ protocol GridCellDelegate: AnyObject {
101101
func cell(_ cell: GridCell, didChangeSelectionAt range: NSRange, attributes: [NSAttributedString.Key : Any], contentType: EditorContent.Name)
102102
func cell(_ cell: GridCell, didReceiveKey key: EditorKey, at range: NSRange)
103103
func cell(_ cell: GridCell, didChangeSelected isSelected: Bool)
104+
func cell(_ cell: GridCell, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?)
104105
}
105106

106107
/// Denotes a cell in the `GridView`
@@ -122,6 +123,13 @@ open class GridCell {
122123
/// Frame of the cell within `GridView`
123124
public internal(set) var frame: CGRect = .zero
124125

126+
public var backgroundColor: UIColor? = nil {
127+
didSet {
128+
contentView.backgroundColor = backgroundColor
129+
editor.backgroundColor = backgroundColor
130+
}
131+
}
132+
125133
private var selectionView: SelectionView?
126134
private let editorInitializer: EditorInitializer
127135

@@ -280,6 +288,13 @@ open class GridCell {
280288
}
281289
}
282290

291+
func updateBackgroundColorFromParent(color: UIColor?, oldColor: UIColor?) {
292+
// check for same color is required. In absence of that, the rendering causes
293+
// collapsed cells to still show text even though cell is collapsed
294+
guard backgroundColor == oldColor, backgroundColor != color else { return }
295+
backgroundColor = color
296+
}
297+
283298
private func assertEditorSetupCompleted() {
284299
guard editorSetupComplete == false,
285300
ignoresOptimizedInit == false else {
@@ -322,6 +337,7 @@ open class GridCell {
322337
editor.translatesAutoresizingMaskIntoConstraints = false
323338
editor.boundsObserver = self
324339
editor.delegate = self
340+
325341
contentView.addSubview(editor)
326342

327343
NSLayoutConstraint.activate([
@@ -367,6 +383,11 @@ extension GridCell: EditorViewDelegate {
367383
public func editor(_ editor: EditorView, didReceiveKey key: EditorKey, at range: NSRange) {
368384
delegate?.cell(self, didReceiveKey: key, at: range)
369385
}
386+
387+
public func editor(_ editor: EditorView, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?) {
388+
contentView.backgroundColor = color
389+
delegate?.cell(self, didChangeBackgroundColor: color, oldColor: oldColor)
390+
}
370391
}
371392

372393
extension GridCell: Equatable {

Diff for: Proton/Sources/Swift/Grid/View/GridContentView.swift

+12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ protocol GridContentViewDelegate: AnyObject {
4343
func gridContentView(_ gridContentView: GridContentView, didDeleteColumnAt index: Int)
4444

4545
func gridContentView(_ gridContentView: GridContentView, shouldChangeColumnWidth proposedWidth: CGFloat, for columnIndex: Int) -> Bool
46+
47+
func gridContentView(_ gridContentView: GridContentView, cell: GridCell, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?)
4648
}
4749

4850
class GridContentView: UIScrollView {
@@ -68,6 +70,12 @@ class GridContentView: UIScrollView {
6870

6971
private(set) var selectedCells: [GridCell] = [GridCell]()
7072

73+
override var backgroundColor: UIColor? {
74+
didSet {
75+
cells.forEach { $0.updateBackgroundColorFromParent(color: backgroundColor, oldColor: oldValue) }
76+
}
77+
}
78+
7179
var numberOfColumns: Int {
7280
grid.numberOfColumns
7381
}
@@ -447,6 +455,10 @@ extension GridContentView: GridCellDelegate {
447455
gridContentViewDelegate?.gridContentView(self, didChangeSelectionAt: range, attributes: attributes, contentType: contentType, in: cell)
448456
}
449457

458+
func cell(_ cell: GridCell, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?) {
459+
gridContentViewDelegate?.gridContentView(self, cell: cell, didChangeBackgroundColor: color, oldColor: oldColor)
460+
}
461+
450462
func cell(_ cell: GridCell, didChangeBounds bounds: CGRect) {
451463
guard let row = cell.rowSpan.first else { return }
452464
if grid.rowHeights.count > row,

Diff for: Proton/Sources/Swift/Grid/View/GridView.swift

+15
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,12 @@ public class GridView: UIView {
262262
fatalError("init(coder:) has not been implemented")
263263
}
264264

265+
public override var backgroundColor: UIColor? {
266+
didSet {
267+
gridView.backgroundColor = backgroundColor
268+
}
269+
}
270+
265271
private func setup() {
266272
gridView.translatesAutoresizingMaskIntoConstraints = false
267273
leadingShadowView.translatesAutoresizingMaskIntoConstraints = false
@@ -655,6 +661,9 @@ extension GridView: GridContentViewDelegate {
655661
func gridContentView(_ gridContentView: GridContentView, shouldChangeColumnWidth proposedWidth: CGFloat, for columnIndex: Int) -> Bool {
656662
delegate?.gridView(self, shouldChangeColumnWidth: proposedWidth, for: columnIndex) ?? true
657663
}
664+
665+
func gridContentView(_ gridContentView: GridContentView, cell: GridCell, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?) {
666+
}
658667
}
659668

660669
class CellHandleButton: UIButton {
@@ -674,3 +683,9 @@ class CellHandleButton: UIButton {
674683
}
675684

676685
extension GridView: AsyncDeferredRenderable { }
686+
687+
extension GridView: BackgroundColorObserving {
688+
public func containerEditor(_ editor: EditorView, backgroundColorUpdated color: UIColor?, oldColor: UIColor?) {
689+
backgroundColor = color
690+
}
691+
}

Diff for: Proton/Tests/Attachments/GridViewAttachment.swift

+6
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,9 @@ extension GridView: AttachmentViewIdentifying {
4848

4949
public var type: AttachmentType { .block }
5050
}
51+
52+
extension GridView: BackgroundColorObserving {
53+
public func containerEditor(_ editor: EditorView, backgroundColorUpdated color: UIColor?, oldColor: UIColor?) {
54+
backgroundColor = color
55+
}
56+
}

Diff for: Proton/Tests/Grid/GridViewAttachmentSnapshotTests.swift

+31
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,37 @@ class GridViewAttachmentSnapshotTests: SnapshotTestCase {
5050
assertSnapshot(matching: viewController.view, as: .image, record: recordMode)
5151
}
5252

53+
func testRendersGridViewAttachmentWithContainerBackgroundColor() {
54+
let viewController = EditorTestViewController()
55+
let editor = viewController.editor
56+
let config = GridConfiguration(
57+
columnsConfiguration: [
58+
GridColumnConfiguration(width: .fixed(100)),
59+
GridColumnConfiguration(width: .fractional(100))
60+
],
61+
rowsConfiguration: [
62+
GridRowConfiguration(initialHeight: 40),
63+
GridRowConfiguration(initialHeight: 40),
64+
])
65+
let attachment = GridViewAttachment(config: config)
66+
67+
editor.backgroundColor = .lightGray
68+
editor.replaceCharacters(in: .zero, with: "Some text in editor")
69+
editor.insertAttachment(in: editor.textEndRange, attachment: attachment)
70+
editor.replaceCharacters(in: editor.textEndRange, with: "Text after grid")
71+
72+
let cell = attachment.view.cellAt(rowIndex: 0, columnIndex: 0)
73+
cell?.editor.attributedText = NSAttributedString(string: "Test\nNew line\nMore text")
74+
cell?.backgroundColor = .white
75+
76+
viewController.render(size: CGSize(width: 300, height: 225))
77+
assertSnapshot(matching: viewController.view, as: .image, record: recordMode)
78+
79+
editor.backgroundColor = .darkGray
80+
viewController.render(size: CGSize(width: 300, height: 225))
81+
assertSnapshot(matching: viewController.view, as: .image, record: recordMode)
82+
}
83+
5384
func testRendersGridViewAttachmentWithConstrainedFixedWidth() {
5485
let viewController = EditorTestViewController()
5586
let editor = viewController.editor

Diff for: Proton/Tests/Grid/Mocks/MockGridCellDelegate.swift

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class MockGridCellDelegate: GridCellDelegate {
3030
var onDidChangeSelection: ((GridCell, NSRange, [NSAttributedString.Key : Any], EditorContent.Name) -> Void)?
3131
var onDidReceiveKey: ((GridCell, EditorKey, NSRange) -> Void)?
3232
var onDidChangeSelected: ((GridCell, Bool) -> Void)?
33+
var onDidChangeBackgroundColor: ((GridCell, UIColor?, UIColor?) -> Void)?
3334

3435

3536
func cell(_ cell: GridCell, didChangeBounds bounds: CGRect) {
@@ -59,4 +60,8 @@ class MockGridCellDelegate: GridCellDelegate {
5960
func cell(_ cell: GridCell, didChangeSelected isSelected: Bool) {
6061
onDidChangeSelected?(cell, isSelected)
6162
}
63+
64+
func cell(_ cell: GridCell, didChangeBackgroundColor color: UIColor?, oldColor: UIColor?) {
65+
onDidChangeBackgroundColor?(cell, color, oldColor)
66+
}
6267
}

0 commit comments

Comments
 (0)