<commit_before>protocol ThemeableTextViewPlaceholderDelegate: AnyObject {
    func themeableTextViewPlaceholderDidHide(_ themeableTextView: UITextView, isPlaceholderHidden: Bool)
}

class ThemeableTextView: UITextView {
    private var theme = Theme.standard
    public var isUnderlined = true
    private var firstTimeEditing = true

    weak var _delegate: UITextViewDelegate?
    weak var placeholderDelegate: ThemeableTextViewPlaceholderDelegate?

    private var clearButton: UIButton!

    override var delegate: UITextViewDelegate? {
        didSet {
            if delegate != nil, placeholder != nil {
                assert(delegate === self, "ThemeableTextView must be its own delegate to manage placeholder")
            }
        }
    }

    public func reset() {
        placeholder = nil
    }

    var placeholder: String? {
        didSet {
            isShowingPlaceholder = placeholder != nil
        }
    }

    public private(set) var isShowingPlaceholder: Bool = true {
        didSet {
            if isShowingPlaceholder {
                text = placeholder
                textColor = theme.colors.tertiaryText
            } else {
                textColor = theme.colors.primaryText
            }
        }
    }

    override var text: String! {
        get {
            return isShowingPlaceholder ? "" : super.text
        }
        set {
            super.text = newValue
        }
    }

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    private func setup() {
        delegate = self
        let image = #imageLiteral(resourceName: "clear-mini")
        clearButton = UIButton(frame: CGRect(origin: .zero, size: image.size))
        clearButton.setImage(image, for: .normal)
        clearButton.addTarget(self, action: #selector(clear), for: .touchUpInside)
        addSubview(clearButton)
        clearButton.isHidden = true
        var inset = textContainerInset
        inset.top += 8
        textContainerInset = inset
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        clearButton.frame = CGRect(x: frame.width - clearButton.frame.width, y: 0, width: clearButton.frame.width, height: clearButton.frame.height)
    }

    @objc private func clear() {
        text = nil
    }

    private func setClearButtonHidden(_ hidden: Bool) {
        guard clearButton.isHidden != hidden else {
            return
        }
        clearButton.isHidden = hidden
    }
}

extension ThemeableTextView: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        _delegate?.textViewDidChange?(textView)
        setClearButtonHidden(textView.text.isEmpty)
    }

    func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
        if firstTimeEditing {
            if textView.text.isEmpty, !isShowingPlaceholder {
                isShowingPlaceholder = true
                placeholderDelegate?.themeableTextViewPlaceholderDidHide(self, isPlaceholderHidden: false)
            } else if isShowingPlaceholder {
                textView.text = nil
                isShowingPlaceholder = false
                placeholderDelegate?.themeableTextViewPlaceholderDidHide(self, isPlaceholderHidden: true)<commit_msg>hide button after niling out text<commit_after>protocol ThemeableTextViewPlaceholderDelegate: AnyObject {
    func themeableTextViewPlaceholderDidHide(_ themeableTextView: UITextView, isPlaceholderHidden: Bool)
}

class ThemeableTextView: UITextView {
    private var theme = Theme.standard
    public var isUnderlined = true
    private var firstTimeEditing = true

    weak var _delegate: UITextViewDelegate?
    weak var placeholderDelegate: ThemeableTextViewPlaceholderDelegate?

    private var clearButton: UIButton!

    override var delegate: UITextViewDelegate? {
        didSet {
            if delegate != nil, placeholder != nil {
                assert(delegate === self, "ThemeableTextView must be its own delegate to manage placeholder")
            }
        }
    }

    public func reset() {
        placeholder = nil
    }

    var placeholder: String? {
        didSet {
            isShowingPlaceholder = placeholder != nil
        }
    }

    public private(set) var isShowingPlaceholder: Bool = true {
        didSet {
            if isShowingPlaceholder {
                text = placeholder
                textColor = theme.colors.tertiaryText
            } else {
                textColor = theme.colors.primaryText
            }
        }
    }

    override var text: String! {
        get {
            return isShowingPlaceholder ? "" : super.text
        }
        set {
            super.text = newValue
        }
    }

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    private func setup() {
        delegate = self
        let image = #imageLiteral(resourceName: "clear-mini")
        clearButton = UIButton(frame: CGRect(origin: .zero, size: image.size))
        clearButton.setImage(image, for: .normal)
        clearButton.addTarget(self, action: #selector(clear), for: .touchUpInside)
        addSubview(clearButton)
        clearButton.isHidden = true
        var inset = textContainerInset
        inset.top += 8
        textContainerInset = inset
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        clearButton.frame = CGRect(x: frame.width - clearButton.frame.width, y: 0, width: clearButton.frame.width, height: clearButton.frame.height)
    }

    @objc private func clear() {
        text = nil
        setClearButtonHidden(true)
    }

    private func setClearButtonHidden(_ hidden: Bool) {
        guard clearButton.isHidden != hidden else {
            return
        }
        clearButton.isHidden = hidden
    }
}

extension ThemeableTextView: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        _delegate?.textViewDidChange?(textView)
        setClearButtonHidden(textView.text.isEmpty)
    }

    func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
        if firstTimeEditing {
            if textView.text.isEmpty, !isShowingPlaceholder {
                isShowingPlaceholder = true
                placeholderDelegate?.themeableTextViewPlaceholderDidHide(self, isPlaceholderHidden: false)
            } else if isShowingPlaceholder {
                textView.text = nil
                isShowingPlaceholder = false
                placeholderDelegate?.themeableTextViewPlaceholderDidHide(self, isPlaceholderHidden: true)
{'fraction_non_alphanumeric': 0.07617386248001164, 'fraction_numerical': 0.0005814798662596307, 'mean_word_length': 2.3252779120347995, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5884888', 'n_tokens_mistral': 1852, 'n_tokens_neox': 1766, 'n_words': 429}