Skip to content

Commit 284c424

Browse files
committed
Add macCatalyst header UI & bump deps/version
Update workspace packages and app version, and add macCatalyst-specific header UI in ChatView. - Bump Package.resolved versions: swift-asn1 -> 1.6.0, swift-collections -> 1.4.1, SwiftSoup -> 2.13.2 (revision updates included). - Increment MARKETING_VERSION to 4.6.5. - Modify ChatView to provide macCatalyst-specific layout and header visuals: use a plain background view and separator on macCatalyst instead of the glass/edge-effect header, adjust constraints and subview setup, and guard trait/layout/update methods with conditional compilation to keep existing iOS behavior unchanged. These changes improve macCatalyst compatibility and UI consistency while preserving the original behavior on iOS.
1 parent c76253f commit 284c424

File tree

3 files changed

+113
-76
lines changed

3 files changed

+113
-76
lines changed

FlowDown.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

FlowDown/Configuration/Version.xcconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010
// https://help.apple.com/xcode/#/dev745c5c974
1111
//
1212

13-
MARKETING_VERSION = 4.6.4;
13+
MARKETING_VERSION = 4.6.5;
1414
CURRENT_PROJECT_VERSION = 1;

FlowDown/Interface/ChatView/ChatView.swift

Lines changed: 105 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ class ChatView: UIView {
9090
editor.handlerColor = handlerColor
9191
editor.delegate = self
9292
editor.snp.makeConstraints { make in
93-
make.bottom.equalTo(safeAreaLayoutGuide)
93+
#if targetEnvironment(macCatalyst)
94+
make.bottom.equalToSuperview()
95+
#else
96+
make.bottom.equalTo(safeAreaLayoutGuide)
97+
#endif
9498
make.centerX.equalToSuperview()
9599
make.width.lessThanOrEqualTo(750)
96100
make.width.lessThanOrEqualToSuperview()
@@ -305,8 +309,13 @@ extension ChatView {
305309
$0.showsMenuAsPrimaryAction = true
306310
}
307311

308-
let edgeEffectView = ChatHeaderEdgeEffectView()
309-
let backgroundContainer = ChatHeaderGlassBackgroundContainerView()
312+
#if targetEnvironment(macCatalyst)
313+
let bg = UIView().with { $0.backgroundColor = .background }
314+
let sep = SeparatorView()
315+
#else
316+
let edgeEffectView = ChatHeaderEdgeEffectView()
317+
let backgroundContainer = ChatHeaderGlassBackgroundContainerView()
318+
#endif
310319

311320
let rightClick = RightClickFinder()
312321
var cancellables: Set<AnyCancellable> = .init()
@@ -317,42 +326,77 @@ extension ChatView {
317326
init() {
318327
super.init(frame: .zero)
319328
translatesAutoresizingMaskIntoConstraints = false
320-
clipsToBounds = false
321329

322330
snp.makeConstraints { make in
323331
make.height.equalTo(40).priority(.low)
324332
}
325333

326-
addSubview(edgeEffectView)
327-
addSubview(backgroundContainer)
334+
#if targetEnvironment(macCatalyst)
335+
addSubview(bg)
336+
bg.snp.makeConstraints { make in
337+
make.left.bottom.right.equalToSuperview()
338+
make.top.equalToSuperview().offset(-128)
339+
}
340+
addSubview(sep)
341+
sep.snp.makeConstraints { make in
342+
make.left.right.equalToSuperview()
343+
make.bottom.equalToSuperview()
344+
make.height.equalTo(1)
345+
}
328346

329-
backgroundContainer.contentView.addSubview(icon)
330-
backgroundContainer.contentView.addSubview(textLabel)
347+
addSubview(icon)
348+
addSubview(textLabel)
349+
addSubview(menuButton)
331350

332-
let menuButtonGlass = menuButton.wrappedInGlassEffect(cornerStyle: .capsule)
333-
backgroundContainer.contentView.addSubview(menuButtonGlass)
351+
icon.snp.makeConstraints { make in
352+
make.centerY.equalToSuperview()
353+
make.left.equalToSuperview().inset(20)
354+
make.width.height.equalTo(24)
355+
}
356+
textLabel.snp.makeConstraints { make in
357+
make.center.equalToSuperview()
358+
make.top.greaterThanOrEqualToSuperview()
359+
make.bottom.lessThanOrEqualToSuperview()
360+
make.left.greaterThanOrEqualTo(icon.snp.right).offset(8)
361+
make.right.lessThanOrEqualTo(menuButton.snp.left).offset(-8)
362+
}
363+
menuButton.snp.makeConstraints { make in
364+
make.centerY.equalToSuperview()
365+
make.right.equalToSuperview().inset(20)
366+
make.width.height.equalTo(18)
367+
}
368+
#else
369+
clipsToBounds = false
334370

335-
menuButtonGlass.snp.makeConstraints { make in
336-
make.centerY.equalToSuperview()
337-
make.right.equalToSuperview().inset(12)
338-
make.width.height.equalTo(34)
339-
}
371+
addSubview(edgeEffectView)
372+
addSubview(backgroundContainer)
340373

341-
icon.snp.makeConstraints { make in
342-
make.centerY.equalToSuperview()
343-
make.left.equalToSuperview().inset(20)
344-
make.width.height.equalTo(24)
345-
}
346-
textLabel.snp.makeConstraints { make in
347-
make.centerX.equalToSuperview()
348-
make.centerY.equalToSuperview()
349-
make.top.greaterThanOrEqualToSuperview()
350-
make.bottom.lessThanOrEqualToSuperview()
351-
make.left.greaterThanOrEqualTo(icon.snp.right).offset(8)
352-
make.right.lessThanOrEqualTo(menuButtonGlass.snp.left).offset(-8)
353-
}
374+
backgroundContainer.contentView.addSubview(icon)
375+
backgroundContainer.contentView.addSubview(textLabel)
376+
377+
let menuButtonGlass = menuButton.wrappedInGlassEffect(cornerStyle: .capsule)
378+
backgroundContainer.contentView.addSubview(menuButtonGlass)
379+
380+
menuButtonGlass.snp.makeConstraints { make in
381+
make.centerY.equalToSuperview()
382+
make.right.equalToSuperview().inset(12)
383+
make.width.height.equalTo(34)
384+
}
385+
386+
icon.snp.makeConstraints { make in
387+
make.centerY.equalToSuperview()
388+
make.left.equalToSuperview().inset(20)
389+
make.width.height.equalTo(24)
390+
}
391+
textLabel.snp.makeConstraints { make in
392+
make.centerX.equalToSuperview()
393+
make.centerY.equalToSuperview()
394+
make.top.greaterThanOrEqualToSuperview()
395+
make.bottom.lessThanOrEqualToSuperview()
396+
make.left.greaterThanOrEqualTo(icon.snp.right).offset(8)
397+
make.right.lessThanOrEqualTo(menuButtonGlass.snp.left).offset(-8)
398+
}
354399

355-
#if !targetEnvironment(macCatalyst)
356400
icon.alpha = 0
357401
#endif
358402

@@ -369,41 +413,25 @@ extension ChatView {
369413
}
370414
.store(in: &cancellables)
371415

372-
_ = registerForTraitChanges([UITraitUserInterfaceStyle.self]) { (view: TitleBar, _: UITraitCollection) in
373-
view.updateBackgroundInterfaceStyle()
374-
}
375-
updateBackgroundInterfaceStyle()
416+
#if !targetEnvironment(macCatalyst)
417+
_ = registerForTraitChanges([UITraitUserInterfaceStyle.self]) { (view: TitleBar, _: UITraitCollection) in
418+
view.updateBackgroundInterfaceStyle()
419+
}
420+
updateBackgroundInterfaceStyle()
421+
#endif
376422
}
377423

378424
@available(*, unavailable)
379425
required init?(coder _: NSCoder) {
380426
fatalError()
381427
}
382428

383-
override func layoutSubviews() {
384-
super.layoutSubviews()
385-
386-
let safeTop = safeAreaInsets.top
429+
#if !targetEnvironment(macCatalyst)
430+
override func layoutSubviews() {
431+
super.layoutSubviews()
387432

388-
#if targetEnvironment(macCatalyst)
389-
backgroundContainer.frame = CGRect(
390-
x: 0,
391-
y: 0,
392-
width: bounds.width,
393-
height: bounds.height,
394-
)
395-
backgroundContainer.setContentTopOffset(safeTop)
433+
let safeTop = safeAreaInsets.top
396434

397-
let edgeHeight = bounds.height + 14
398-
edgeEffectView.update(
399-
content: .background,
400-
blur: true,
401-
alpha: 0.85,
402-
rect: CGRect(x: 0, y: 0, width: bounds.width, height: edgeHeight),
403-
edge: .top,
404-
edgeSize: min(54, edgeHeight),
405-
)
406-
#else
407435
let usesUnifiedBackdrop = if #available(iOS 26.0, *) {
408436
false
409437
} else {
@@ -437,29 +465,38 @@ extension ChatView {
437465
edge: .top,
438466
edgeSize: min(54, edgeHeight),
439467
)
440-
#endif
441-
}
468+
}
469+
#endif
442470

443471
deinit {
444472
cancellables.forEach { $0.cancel() }
445473
cancellables.removeAll()
446474
}
447475

448-
override func didMoveToWindow() {
449-
super.didMoveToWindow()
450-
updateBackgroundInterfaceStyle()
451-
}
476+
#if !targetEnvironment(macCatalyst)
477+
override func didMoveToWindow() {
478+
super.didMoveToWindow()
479+
updateBackgroundInterfaceStyle()
480+
}
481+
#endif
452482

453483
private var conv: Conversation.ID?
454484

455-
private func updateBackgroundInterfaceStyle() {
456-
backgroundContainer.update(isDark: traitCollection.userInterfaceStyle == .dark)
457-
}
485+
#if !targetEnvironment(macCatalyst)
486+
private func updateBackgroundInterfaceStyle() {
487+
backgroundContainer.update(isDark: traitCollection.userInterfaceStyle == .dark)
488+
}
458489

459-
func setDecorativeBackgroundHidden(_ isHidden: Bool) {
460-
backgroundContainer.setVisualEffectEnabled(!isHidden)
461-
edgeEffectView.isHidden = isHidden
462-
}
490+
func setDecorativeBackgroundHidden(_ isHidden: Bool) {
491+
backgroundContainer.setVisualEffectEnabled(!isHidden)
492+
edgeEffectView.isHidden = isHidden
493+
}
494+
#else
495+
func setDecorativeBackgroundHidden(_ isHidden: Bool) {
496+
bg.isHidden = isHidden
497+
sep.isHidden = isHidden
498+
}
499+
#endif
463500

464501
func use(identifier: Conversation.ID?) {
465502
conv = identifier

0 commit comments

Comments
 (0)