<commit_before>// MIT license. Copyright (c) 2016 SwiftyFORM. All rights reserved.
import UIKit

/// Adjusts bottom insets when keyboard is shown and makes sure the keyboard doesn't obscure the cell.
///
/// Resets insets when the keyboard is hidden.
public class KeyboardHandler {
	private let tableView: UITableView
	private var innerKeyboardVisible: Bool = false
	
	init(tableView: UITableView) {
		self.tableView = tableView
	}
	
	var keyboardVisible: Bool {
		return innerKeyboardVisible
	}

	/// Start listening for changes to keyboard visibility so that we can adjust the scroll view accordingly.
	func addObservers() {
		/*
		I listen to UIKeyboardWillShowNotification.
		I don't listen to UIKeyboardWillChangeFrameNotification
		
		Explanation:
		UIKeyboardWillChangeFrameNotification vs. UIKeyboardWillShowNotification
		
		The notifications behave the same on iPhone.
		However there is a big difference on iPad.
		
		On iPad with a split keyboard or a non-docked keyboard.
		When you make a textfield first responder and the keyboard appears,
		then UIKeyboardWillShowNotification is not invoked.
		only UIKeyboardWillChangeFrameNotification is invoked.
		
		The user has chosen actively to manually position the keyboard.
		In this case it's non-trivial to scroll to the textfield.
		It's not something I will support for now.
		*/
		
		let notificationCenter = NotificationCenter.default
		notificationCenter.addObserver(self, selector: #selector(KeyboardHandler.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
		notificationCenter.addObserver(self, selector: #selector(KeyboardHandler.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
	}
	
	/// Stop listening to keyboard visibility changes
	func removeObservers() {
		let notificationCenter = NotificationCenter.default
		notificationCenter.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
		notificationCenter.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
	}
	
	/// The keyboard will appear, scroll content so it's not covered by the keyboard.
	@objc func keyboardWillShow(_ notification: Notification) {
//		SwiftyFormLog("show\n\n\n\n\n\n\n\n")
		innerKeyboardVisible = true
		guard let cell = tableView.form_firstResponder()?.form_cell() else {
			return
		}
		guard let indexPath = tableView.indexPath(for: cell) else {
			return
		}
		
		let rectForRow = tableView.rectForRow(at: indexPath)
//		SwiftyFormLog("rectForRow \(NSStringFromCGRect(rectForRow))")
		
		guard let userInfo: [AnyHashable: Any] = notification.userInfo else {
			return
		}
		guard let window: UIWindow = tableView.window else {
			return
		}

		let keyboardFrameEnd = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
//		SwiftyFormLog("keyboardFrameEnd \(NSStringFromCGRect(keyboardFrameEnd))")
		
		
		let keyboardFrame = window.convert(keyboardFrameEnd, to: tableView.superview)
//		SwiftyFormLog("keyboardFrame \(keyboardFrame)")
		
		let convertedRectForRow = window.convert(rectForRow, from: tableView)
//		SwiftyFormLog("convertedRectForRow \(NSStringFromCGRect(convertedRectForRow))")
		
//		SwiftyFormLog("tableView.frame \(NSStringFromCGRect(tableView.frame))")
		
		var scrollToVisible = false
		var scrollToRect = CGRect.zero

		let spaceBetweenCellAndKeyboard: CGFloat = 36
		let y0 = convertedRectForRow.maxY + spaceBetweenCellAndKeyboard
		let y1 = keyboardFrameEnd.minY
		let obscured = y0 > y1
//		SwiftyFormLog("values \(y0) \(y1) \(obscured)")
		if obscured {
			SwiftyFormLog("cell is obscured by keyboard, we are scrolling")
			scrollToVisible = true
			scrollToRect = rectForRow
			scrollToRect.size.height += spaceBetweenCellAndKeyboard
		} else {
			SwiftyFormLog("cell is fully visible, no need to scroll")
		}
		let inset: CGFloat = tableView.frame.origin.y + tableView.frame.size.height - keyboardFrame.origin.y
		//SwiftyFormLog("inset \(inset)")<commit_msg>KeyboardHandler - simplified inset computation<commit_after>// MIT license. Copyright (c) 2016 SwiftyFORM. All rights reserved.
import UIKit

/// Adjusts bottom insets when keyboard is shown and makes sure the keyboard doesn't obscure the cell.
///
/// Resets insets when the keyboard is hidden.
public class KeyboardHandler {
	private let tableView: UITableView
	private var innerKeyboardVisible: Bool = false
	
	init(tableView: UITableView) {
		self.tableView = tableView
	}
	
	var keyboardVisible: Bool {
		return innerKeyboardVisible
	}

	/// Start listening for changes to keyboard visibility so that we can adjust the scroll view accordingly.
	func addObservers() {
		/*
		I listen to UIKeyboardWillShowNotification.
		I don't listen to UIKeyboardWillChangeFrameNotification
		
		Explanation:
		UIKeyboardWillChangeFrameNotification vs. UIKeyboardWillShowNotification
		
		The notifications behave the same on iPhone.
		However there is a big difference on iPad.
		
		On iPad with a split keyboard or a non-docked keyboard.
		When you make a textfield first responder and the keyboard appears,
		then UIKeyboardWillShowNotification is not invoked.
		only UIKeyboardWillChangeFrameNotification is invoked.
		
		The user has chosen actively to manually position the keyboard.
		In this case it's non-trivial to scroll to the textfield.
		It's not something I will support for now.
		*/
		
		let notificationCenter = NotificationCenter.default
		notificationCenter.addObserver(self, selector: #selector(KeyboardHandler.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
		notificationCenter.addObserver(self, selector: #selector(KeyboardHandler.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
	}
	
	/// Stop listening to keyboard visibility changes
	func removeObservers() {
		let notificationCenter = NotificationCenter.default
		notificationCenter.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
		notificationCenter.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
	}
	
	/// The keyboard will appear, scroll content so it's not covered by the keyboard.
	@objc func keyboardWillShow(_ notification: Notification) {
//		SwiftyFormLog("show\n\n\n\n\n\n\n\n")
		innerKeyboardVisible = true
		guard let cell = tableView.form_firstResponder()?.form_cell() else {
			return
		}
		guard let indexPath = tableView.indexPath(for: cell) else {
			return
		}
		
		let rectForRow = tableView.rectForRow(at: indexPath)
//		SwiftyFormLog("rectForRow \(NSStringFromCGRect(rectForRow))")
		
		guard let userInfo: [AnyHashable: Any] = notification.userInfo else {
			return
		}
		guard let window: UIWindow = tableView.window else {
			return
		}

		let keyboardFrameEnd = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
//		SwiftyFormLog("keyboardFrameEnd \(NSStringFromCGRect(keyboardFrameEnd))")
		
		
		let keyboardFrame = window.convert(keyboardFrameEnd, to: tableView.superview)
//		SwiftyFormLog("keyboardFrame \(keyboardFrame)")
		
		let convertedRectForRow = window.convert(rectForRow, from: tableView)
//		SwiftyFormLog("convertedRectForRow \(NSStringFromCGRect(convertedRectForRow))")
		
//		SwiftyFormLog("tableView.frame \(NSStringFromCGRect(tableView.frame))")
		
		var scrollToVisible = false
		var scrollToRect = CGRect.zero

		let spaceBetweenCellAndKeyboard: CGFloat = 36
		let y0 = convertedRectForRow.maxY + spaceBetweenCellAndKeyboard
		let y1 = keyboardFrameEnd.minY
		let obscured = y0 > y1
//		SwiftyFormLog("values \(y0) \(y1) \(obscured)")
		if obscured {
			SwiftyFormLog("cell is obscured by keyboard, we are scrolling")
			scrollToVisible = true
			scrollToRect = rectForRow
			scrollToRect.size.height += spaceBetweenCellAndKeyboard
		} else {
			SwiftyFormLog("cell is fully visible, no need to scroll")
		}
		let inset: CGFloat = tableView.frame.maxY - keyboardFrame.origin.y
		//SwiftyFormLog("inset \(inset)")
{'fraction_non_alphanumeric': 0.08346951602765557, 'fraction_numerical': 0.003016970458830924, 'mean_word_length': 4.650568181818182, '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': '2865753', 'n_tokens_mistral': 2538, 'n_tokens_neox': 2276, 'n_words': 669}