<commit_before>import UIKit

@objc public protocol ReadingListHintProvider: NSObjectProtocol {
    var addArticleToReadingListToolbarController: AddArticleToReadingListToolbarController! { get set }
}

protocol AddArticleToReadingListToolbarViewControllerDelegate: NSObjectProtocol {
    func viewControllerWillBeDismissed()
    func addedArticleToReadingList()
}

@objc(WMFAddArticleToReadingListToolbarController)
public class AddArticleToReadingListToolbarController: NSObject, AddArticleToReadingListToolbarViewControllerDelegate {

    fileprivate let dataStore: MWKDataStore
    fileprivate let owner: UIViewController
    fileprivate let toolbar: AddArticleToReadingListToolbarViewController
    fileprivate let toolbarHeight: CGFloat = 50
    
    fileprivate var isToolbarVisible = false {
        didSet {
            guard isToolbarVisible != oldValue else {
                return
            }
            if isToolbarVisible {
                addToolbar()
                perform(#selector(dismissToolbar), with: self, afterDelay: 8)
            } else {
                removeToolbar()
            }
        }
    }
    
    @objc init(dataStore: MWKDataStore, owner: UIViewController) {
        self.dataStore = dataStore
        self.owner = owner
        self.toolbar = AddArticleToReadingListToolbarViewController(dataStore: dataStore)
        super.init()
        self.toolbar.delegate = self
    }
    
    func removeToolbar() {
        toolbar.willMove(toParentViewController: nil)
        toolbar.view.removeFromSuperview()
        toolbar.removeFromParentViewController()
        toolbar.reset()
    }
    
    func addToolbar() {
        // apply theme
        owner.addChildViewController(toolbar)
        toolbar.view.autoresizingMask = [.flexibleTopMargin, .flexibleWidth]
        owner.view.addSubview(toolbar.view)
        toolbar.didMove(toParentViewController: owner)
    }
    
    @objc func dismissToolbar() {
        setToolbar(visible: false, animated: true)
    }
    
    func setToolbar(visible: Bool, animated: Bool) {
        let frame = visible ? toolbarFrame.visible : toolbarFrame.hidden
        if animated {
            if visible {
                // add toolbar before animation starts
                isToolbarVisible = visible
                // set initial frame
                if toolbar.view.frame.origin.y == 0 {
                    toolbar.view.frame = toolbarFrame.hidden
                }
            }
            if shouldHideExistingToolbar {
                owner.navigationController?.setToolbarHidden(visible, animated: true)
            }
            UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseInOut, .beginFromCurrentState], animations: {
                self.toolbar.view.frame = frame
                self.owner.view.setNeedsLayout()
            }, completion: { (_) in
                if !visible {
                    // remove toolbar after animation is completed
                    self.isToolbarVisible = visible
                }
            })
        }
    }
    
    fileprivate lazy var shouldHideExistingToolbar: Bool = {
        return owner.tabBarController?.tabBar.isHidden ?? true
    }()
    
    fileprivate lazy var toolbarFrame: (visible: CGRect, hidden: CGRect) = {
        var bottomInset: CGFloat = 0
        if #available(iOS 11.0, *) {
            bottomInset = owner.view.safeAreaInsets.bottom
        } else {
            bottomInset = owner.bottomLayoutGuide.length
        }
        let visible = CGRect(x: 0, y: owner.view.bounds.height - toolbarHeight - bottomInset, width: owner.view.bounds.size.width, height: toolbarHeight)
        let hidden = CGRect(x: 0, y: owner.view.bounds.height + toolbarHeight - bottomInset, width: owner.view.bounds.size.width, height: toolbarHeight)
        return (visible: visible, hidden: hidden)
    }()
    
    @objc func didSave(_ didSave: Bool, article: WMFArticle) {
        let didSaveOtherArticle = didSave && isToolbarVisible && article != toolbar.article
        let didUnsaveOtherArticle = !didSave && isToolbarVisible && article != toolbar.article
        
        guard !didUnsaveOtherArticle else {
            return
        }
        
        guard !didSaveOtherArticle else {
            toolbar.reset()
            NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(dismissToolbar), object: self) // object: nil?
            perform(#selector(dismissToolbar), with: self, afterDelay: 8)
            toolbar.article = article
            return<commit_msg>more bottom inset calculation<commit_after>import UIKit

@objc public protocol ReadingListHintProvider: NSObjectProtocol {
    var addArticleToReadingListToolbarController: AddArticleToReadingListToolbarController! { get set }
}

protocol AddArticleToReadingListToolbarViewControllerDelegate: NSObjectProtocol {
    func viewControllerWillBeDismissed()
    func addedArticleToReadingList()
}

@objc(WMFAddArticleToReadingListToolbarController)
public class AddArticleToReadingListToolbarController: NSObject, AddArticleToReadingListToolbarViewControllerDelegate {

    fileprivate let dataStore: MWKDataStore
    fileprivate let owner: UIViewController
    fileprivate let toolbar: AddArticleToReadingListToolbarViewController
    fileprivate let toolbarHeight: CGFloat = 50
    
    fileprivate var isToolbarVisible = false {
        didSet {
            guard isToolbarVisible != oldValue else {
                return
            }
            if isToolbarVisible {
                addToolbar()
                perform(#selector(dismissToolbar), with: self, afterDelay: 8)
            } else {
                removeToolbar()
            }
        }
    }
    
    @objc init(dataStore: MWKDataStore, owner: UIViewController) {
        self.dataStore = dataStore
        self.owner = owner
        self.toolbar = AddArticleToReadingListToolbarViewController(dataStore: dataStore)
        super.init()
        self.toolbar.delegate = self
    }
    
    func removeToolbar() {
        toolbar.willMove(toParentViewController: nil)
        toolbar.view.removeFromSuperview()
        toolbar.removeFromParentViewController()
        toolbar.reset()
    }
    
    func addToolbar() {
        // apply theme
        owner.addChildViewController(toolbar)
        toolbar.view.autoresizingMask = [.flexibleTopMargin, .flexibleWidth]
        owner.view.addSubview(toolbar.view)
        toolbar.didMove(toParentViewController: owner)
    }
    
    @objc func dismissToolbar() {
        setToolbar(visible: false, animated: true)
    }
    
    func setToolbar(visible: Bool, animated: Bool) {
        let frame = visible ? toolbarFrame.visible : toolbarFrame.hidden
        if animated {
            if visible {
                // add toolbar before animation starts
                isToolbarVisible = visible
                // set initial frame
                if toolbar.view.frame.origin.y == 0 {
                    toolbar.view.frame = toolbarFrame.hidden
                }
            }
            if shouldHideExistingToolbar {
                owner.navigationController?.setToolbarHidden(visible, animated: true)
            }
            UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseInOut, .beginFromCurrentState], animations: {
                self.toolbar.view.frame = frame
                self.owner.view.setNeedsLayout()
            }, completion: { (_) in
                if !visible {
                    // remove toolbar after animation is completed
                    self.isToolbarVisible = visible
                }
            })
        }
    }
    
    fileprivate lazy var shouldHideExistingToolbar: Bool = {
        return owner.tabBarController?.tabBar.isHidden ?? true
    }()
    
    fileprivate lazy var toolbarFrame: (visible: CGRect, hidden: CGRect) = {
        let bottomInset = owner is WMFViewController ? 0 : owner.bottomLayoutGuide.length
        let visible = CGRect(x: 0, y: owner.view.bounds.height - toolbarHeight - bottomInset, width: owner.view.bounds.size.width, height: toolbarHeight)
        let hidden = CGRect(x: 0, y: owner.view.bounds.height + toolbarHeight - bottomInset, width: owner.view.bounds.size.width, height: toolbarHeight)
        return (visible: visible, hidden: hidden)
    }()
    
    @objc func didSave(_ didSave: Bool, article: WMFArticle) {
        let didSaveOtherArticle = didSave && isToolbarVisible && article != toolbar.article
        let didUnsaveOtherArticle = !didSave && isToolbarVisible && article != toolbar.article
        
        guard !didUnsaveOtherArticle else {
            return
        }
        
        guard !didSaveOtherArticle else {
            toolbar.reset()
            NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(dismissToolbar), object: self) // object: nil?
            perform(#selector(dismissToolbar), with: self, afterDelay: 8)
            toolbar.article = article
            return
{'fraction_non_alphanumeric': 0.07780371234856064, 'fraction_numerical': 0.002778704012448594, 'mean_word_length': 2.3080882352941177, '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': '6345744', 'n_tokens_mistral': 2417, 'n_tokens_neox': 2265, 'n_words': 515}