<commit_before>open class DrawerPlugin: OverlayPlugin {
    public enum Position {
        case undefined
        case bottom
    }

    open var position: DrawerPlugin.Position {
        return .undefined
    }

    var size: CGSize {
        return .zero
    }

    open var placeholder: CGFloat {
        return .zero
    }

    open var overlayViewFrame: CGRect {
        guard let overlayView = view.superview else { return .zero }
        return overlayView.frame
    }

    private(set) var isClosed: Bool = true {
        willSet {
            let event: Event = newValue ? .willHideDrawerPlugin : .willShowDrawerPlugin
            core?.trigger(event)
        }
        didSet {
            if isClosed {
                hide()
                core?.trigger(.didHideDrawerPlugin)
            } else {
                show()
                core?.trigger(.didShowDrawerPlugin)
            }
        }
    }

    public required init(context: UIObject) {
        super.init(context: context)
        view.alpha = .zero
    }

    open override func bindEvents() {
        guard let core = core else { return }

        bindCoreEvents(context: core)
        bindMediaControlEvents(context: core)
        bindDrawerEvents(context: core)
    }

    private func bindCoreEvents(context: UIObject) {
        listenTo(context, eventName: InternalEvent.didTappedCore.rawValue) { [weak self] _ in
            guard self?.isClosed == false else { return }

            context.trigger(.hideDrawerPlugin)
        }
    }

    private func bindMediaControlEvents(context: UIObject) {
        listenTo(context, event: .willShowMediaControl) { [weak self] _ in
            UIView.animate(withDuration: ClapprAnimationDuration.mediaControlShow) {
                self?.view.alpha = 1
            }
        }

        listenTo(context, event: .willHideMediaControl) { [weak self] _ in
            guard self?.isClosed == true else { return }
            UIView.animate(withDuration: ClapprAnimationDuration.mediaControlHide) {
                self?.view.alpha = 0
            }
        }
    }

    private func bindDrawerEvents(context: UIObject) {
        listenTo(context, event: .showDrawerPlugin) { [weak self] _ in
            self?.toggleIsClosed(to: false)
            self?.onDrawerShow()
        }

        listenTo(context, event: .hideDrawerPlugin) { [weak self] _ in
            self?.toggleIsClosed(to: true)
            self?.onDrawerHide()
        }
    }

    private func toggleIsClosed(to newValue: Bool) {
        guard isClosed != newValue else { return }
        isClosed = newValue
    }

    override open func render() {
        requestPaddingIfNeeded()
    }
<commit_msg>fix: allow the drawer plugin to trigger close and open events when drawer comes back to the same state after drag<commit_after>open class DrawerPlugin: OverlayPlugin {
    public enum Position {
        case undefined
        case bottom
    }

    open var position: DrawerPlugin.Position {
        return .undefined
    }

    var size: CGSize {
        return .zero
    }

    open var placeholder: CGFloat {
        return .zero
    }

    open var overlayViewFrame: CGRect {
        guard let overlayView = view.superview else { return .zero }
        return overlayView.frame
    }

    private(set) var isClosed: Bool = true {
        willSet {
            let event: Event = newValue ? .willHideDrawerPlugin : .willShowDrawerPlugin
            core?.trigger(event)
        }
        didSet {
            if isClosed {
                hide()
                core?.trigger(.didHideDrawerPlugin)
            } else {
                show()
                core?.trigger(.didShowDrawerPlugin)
            }
        }
    }

    public required init(context: UIObject) {
        super.init(context: context)
        view.alpha = .zero
    }

    open override func bindEvents() {
        guard let core = core else { return }

        bindCoreEvents(context: core)
        bindMediaControlEvents(context: core)
        bindDrawerEvents(context: core)
    }

    private func bindCoreEvents(context: UIObject) {
        listenTo(context, eventName: InternalEvent.didTappedCore.rawValue) { [weak self] _ in
            guard self?.isClosed == false else { return }

            context.trigger(.hideDrawerPlugin)
        }
    }

    private func bindMediaControlEvents(context: UIObject) {
        listenTo(context, event: .willShowMediaControl) { [weak self] _ in
            UIView.animate(withDuration: ClapprAnimationDuration.mediaControlShow) {
                self?.view.alpha = 1
            }
        }

        listenTo(context, event: .willHideMediaControl) { [weak self] _ in
            guard self?.isClosed == true else { return }
            UIView.animate(withDuration: ClapprAnimationDuration.mediaControlHide) {
                self?.view.alpha = 0
            }
        }
    }

    private func bindDrawerEvents(context: UIObject) {
        listenTo(context, event: .showDrawerPlugin) { [weak self] _ in
            self?.toggleIsClosed(to: false)
            self?.onDrawerShow()
        }

        listenTo(context, event: .hideDrawerPlugin) { [weak self] _ in
            self?.toggleIsClosed(to: true)
            self?.onDrawerHide()
        }
    }

    private func toggleIsClosed(to newValue: Bool) {
        isClosed = newValue
    }

    override open func render() {
        requestPaddingIfNeeded()
    }

{'fraction_non_alphanumeric': 0.08347153123272526, 'fraction_numerical': 0.0007370554634236226, 'mean_word_length': 1.8980245595301655, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '677773', 'n_tokens_mistral': 1521, 'n_tokens_neox': 1431, 'n_words': 355}