Creating a UIImageView outside a view hierarchy now crashes on iOS 18. We can avoid this offscreen rendering technique by removing UIImage.asTintedImage(), configuring the tint colour and template rendering on the UIImage directly, and rendering with UIGraphicsImageRenderer instead of lower-level Core Graphics APIs.
95 lines
3.0 KiB
Swift
95 lines
3.0 KiB
Swift
//
|
|
// Copyright 2023 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import SignalServiceKit
|
|
|
|
public class OWSSearchBar: UISearchBar {
|
|
|
|
public override init(frame: CGRect) {
|
|
super.init(frame: frame)
|
|
configure()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
super.init(coder: coder)
|
|
configure()
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
public var searchFieldBackgroundColorOverride: UIColor? {
|
|
didSet {
|
|
applyTheme()
|
|
}
|
|
}
|
|
|
|
private func configure() {
|
|
applyTheme()
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeDidChange, object: nil)
|
|
}
|
|
|
|
// MARK: Theme
|
|
|
|
public static func applyTheme(to searchBar: UISearchBar) {
|
|
AssertIsOnMainThread()
|
|
|
|
searchBar.tintColor = Theme.secondaryTextAndIconColor
|
|
searchBar.barStyle = Theme.barStyle
|
|
searchBar.barTintColor = Theme.backgroundColor
|
|
|
|
// Hide searchBar border.
|
|
// Alternatively we could hide the border by using `UISearchBarStyleMinimal`, but that causes an issue when toggling
|
|
// from light -> dark -> light theme wherein the textField background color appears darker than it should
|
|
// (regardless of our re-setting textfield.backgroundColor below).
|
|
searchBar.backgroundImage = UIImage()
|
|
|
|
if Theme.isDarkThemeEnabled {
|
|
let foregroundColor = Theme.secondaryTextAndIconColor
|
|
|
|
let clearImage = UIImage(imageLiteralResourceName: "x-circle-fill")
|
|
searchBar.setImage(
|
|
clearImage.withTintColor(foregroundColor, renderingMode: .alwaysTemplate),
|
|
for: .clear,
|
|
state: .normal
|
|
)
|
|
|
|
let searchImage = UIImage(imageLiteralResourceName: "search")
|
|
searchBar.setImage(
|
|
searchImage.withTintColor(foregroundColor, renderingMode: .alwaysTemplate),
|
|
for: .search,
|
|
state: .normal
|
|
)
|
|
} else {
|
|
searchBar.setImage(nil, for: .clear, state: .normal)
|
|
searchBar.setImage(nil, for: .search, state: .normal)
|
|
}
|
|
|
|
let searchFieldBackgroundColor: UIColor
|
|
if let owsSearchBar = searchBar as? OWSSearchBar, let colorOverride = owsSearchBar.searchFieldBackgroundColorOverride {
|
|
searchFieldBackgroundColor = colorOverride
|
|
} else {
|
|
searchFieldBackgroundColor = Theme.searchFieldBackgroundColor
|
|
}
|
|
|
|
searchBar.traverseHierarchyDownward { view in
|
|
guard let textField = view as? UITextField else { return }
|
|
textField.backgroundColor = searchFieldBackgroundColor
|
|
textField.textColor = Theme.primaryTextColor
|
|
textField.keyboardAppearance = Theme.keyboardAppearance
|
|
}
|
|
}
|
|
|
|
private func applyTheme() {
|
|
Self.applyTheme(to: self)
|
|
}
|
|
|
|
@objc
|
|
private func themeDidChange(_ notification: Notification) {
|
|
AssertIsOnMainThread()
|
|
applyTheme()
|
|
}
|
|
}
|