<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import Foundation

struct SwipeAnimationParameters {
    let totalRotationInDegrees: Double
    let deleteThreshold: CGFloat
    let totalScale: CGFloat
    let totalAlpha: CGFloat
    let minExitVelocity: CGFloat
    let recenterAnimationDuration: NSTimeInterval
}

private let DefaultParameters =
    SwipeAnimationParameters(
        totalRotationInDegrees: 10,
        deleteThreshold: 60,
        totalScale: 0.9,
        totalAlpha: 0,
        minExitVelocity: 800,
        recenterAnimationDuration: 0.15)

protocol SwipeAnimatorDelegate: class {
    func swipeAnimator(animator: SwipeAnimator, viewDidExitContainerBounds: UIView)
}

class SwipeAnimator: NSObject {
    weak var delegate: SwipeAnimatorDelegate?
    weak var container: UIView!
    weak var animatingView: UIView!
    
    private var prevOffset: CGPoint!
    private let params: SwipeAnimationParameters

    var containerCenter: CGPoint {
        return CGPoint(x: CGRectGetWidth(container.frame) / 2, y: CGRectGetHeight(container.frame) / 2)
    }

    init(animatingView: UIView, container: UIView, params: SwipeAnimationParameters = DefaultParameters) {
        self.animatingView = animatingView
        self.container = container
        self.params = params

        super.init()

        let panGesture = UIPanGestureRecognizer(target: self, action: Selector("SELdidPan:"))
        container.addGestureRecognizer(panGesture)
        panGesture.delegate = self
    }
}

//MARK: Private Helpers
extension SwipeAnimator {
    private func animateBackToCenter() {
        UIView.animateWithDuration(params.recenterAnimationDuration, animations: {
            self.animatingView.transform = CGAffineTransformIdentity
            self.animatingView.alpha = 1
        })
    }

    private func animateAwayWithVelocity(velocity: CGPoint, speed: CGFloat) {
        // Calculate the edge to calculate distance from
        let translation = velocity.x >= 0 ? CGRectGetWidth(container.frame) : -CGRectGetWidth(container.frame)
        let timeStep = NSTimeInterval(abs(translation) / speed)
        UIView.animateWithDuration(timeStep, animations: {
            self.animatingView.transform = self.transformForTranslation(translation)
            self.animatingView.alpha = self.alphaForDistanceFromCenter(abs(translation))
        }, completion: { finished in
            if finished {
                self.animatingView.alpha = 0
                self.delegate?.swipeAnimator(self, viewDidExitContainerBounds: self.animatingView)
            }
        })
    }

    private func transformForTranslation(translation: CGFloat) -> CGAffineTransform {
        let halfWidth = container.frame.size.width / 2
        let totalRotationInRadians = CGFloat(params.totalRotationInDegrees / 180.0 * M_PI)

        // Determine rotation / scaling amounts by the distance to the edge
        var rotation = (translation / halfWidth) * totalRotationInRadians
        var scale = 1 - (abs(translation) / halfWidth) * (1 - params.totalScale)

        let rotationTransform = CGAffineTransformMakeRotation(rotation)
        let scaleTransform = CGAffineTransformMakeScale(scale, scale)
        let translateTransform = CGAffineTransformMakeTranslation(translation, 0)
        return CGAffineTransformConcat(CGAffineTransformConcat(rotationTransform, scaleTransform), translateTransform)
    }

    private func alphaForDistanceFromCenter(distance: CGFloat) -> CGFloat {
        let halfWidth = container.frame.size.width / 2
        return 1 - (distance / halfWidth) * (1 - params.totalAlpha)
    }
}

//MARK: Selectors
extension SwipeAnimator {
    @objc func SELdidPan(recognizer: UIPanGestureRecognizer!) {
        let translation = recognizer.translationInView(container)

        switch (recognizer.state) {
        case .Began:
            prevOffset = containerCenter
        case .Changed:
            animatingView.transform = transformForTranslation(translation.x)
            animatingView.alpha = alphaForDistanceFromCenter(abs(translation.x))
            prevOffset = CGPoint(x: translation.x, y: 0)
        case .Cancelled:
            animateBackToCenter()
        case .Ended:
            let velocity = recognizer.velocityInView(container)
            // Bounce back if the velocity is too low or if we have not reached the treshold yet
            let speed = max(abs(velocity.x), params.minExitVelocity)<commit_msg>Make the swipe-to-delete gesture a bit less sensitive.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import Foundation

struct SwipeAnimationParameters {
    let totalRotationInDegrees: Double
    let deleteThreshold: CGFloat
    let totalScale: CGFloat
    let totalAlpha: CGFloat
    let minExitVelocity: CGFloat
    let recenterAnimationDuration: NSTimeInterval
}

private let DefaultParameters =
    SwipeAnimationParameters(
        totalRotationInDegrees: 10,
        deleteThreshold: 80,
        totalScale: 0.9,
        totalAlpha: 0,
        minExitVelocity: 800,
        recenterAnimationDuration: 0.15)

protocol SwipeAnimatorDelegate: class {
    func swipeAnimator(animator: SwipeAnimator, viewDidExitContainerBounds: UIView)
}

class SwipeAnimator: NSObject {
    weak var delegate: SwipeAnimatorDelegate?
    weak var container: UIView!
    weak var animatingView: UIView!
    
    private var prevOffset: CGPoint!
    private let params: SwipeAnimationParameters

    var containerCenter: CGPoint {
        return CGPoint(x: CGRectGetWidth(container.frame) / 2, y: CGRectGetHeight(container.frame) / 2)
    }

    init(animatingView: UIView, container: UIView, params: SwipeAnimationParameters = DefaultParameters) {
        self.animatingView = animatingView
        self.container = container
        self.params = params

        super.init()

        let panGesture = UIPanGestureRecognizer(target: self, action: Selector("SELdidPan:"))
        container.addGestureRecognizer(panGesture)
        panGesture.delegate = self
    }
}

//MARK: Private Helpers
extension SwipeAnimator {
    private func animateBackToCenter() {
        UIView.animateWithDuration(params.recenterAnimationDuration, animations: {
            self.animatingView.transform = CGAffineTransformIdentity
            self.animatingView.alpha = 1
        })
    }

    private func animateAwayWithVelocity(velocity: CGPoint, speed: CGFloat) {
        // Calculate the edge to calculate distance from
        let translation = velocity.x >= 0 ? CGRectGetWidth(container.frame) : -CGRectGetWidth(container.frame)
        let timeStep = NSTimeInterval(abs(translation) / speed)
        UIView.animateWithDuration(timeStep, animations: {
            self.animatingView.transform = self.transformForTranslation(translation)
            self.animatingView.alpha = self.alphaForDistanceFromCenter(abs(translation))
        }, completion: { finished in
            if finished {
                self.animatingView.alpha = 0
                self.delegate?.swipeAnimator(self, viewDidExitContainerBounds: self.animatingView)
            }
        })
    }

    private func transformForTranslation(translation: CGFloat) -> CGAffineTransform {
        let swipeWidth = container.frame.size.width
        let totalRotationInRadians = CGFloat(params.totalRotationInDegrees / 180.0 * M_PI)

        // Determine rotation / scaling amounts by the distance to the edge
        var rotation = (translation / swipeWidth) * totalRotationInRadians
        var scale = 1 - (abs(translation) / swipeWidth) * (1 - params.totalScale)

        let rotationTransform = CGAffineTransformMakeRotation(rotation)
        let scaleTransform = CGAffineTransformMakeScale(scale, scale)
        let translateTransform = CGAffineTransformMakeTranslation(translation, 0)
        return CGAffineTransformConcat(CGAffineTransformConcat(rotationTransform, scaleTransform), translateTransform)
    }

    private func alphaForDistanceFromCenter(distance: CGFloat) -> CGFloat {
        let swipeWidth = container.frame.size.width
        return 1 - (distance / swipeWidth) * (1 - params.totalAlpha)
    }
}

//MARK: Selectors
extension SwipeAnimator {
    @objc func SELdidPan(recognizer: UIPanGestureRecognizer!) {
        let translation = recognizer.translationInView(container)

        switch (recognizer.state) {
        case .Began:
            prevOffset = containerCenter
        case .Changed:
            animatingView.transform = transformForTranslation(translation.x)
            animatingView.alpha = alphaForDistanceFromCenter(abs(translation.x))
            prevOffset = CGPoint(x: translation.x, y: 0)
        case .Cancelled:
            animateBackToCenter()
        case .Ended:
            let velocity = recognizer.velocityInView(container)
            // Bounce back if the velocity is too low or if we have not reached the threshold yet
            let speed = max(abs(velocity.x), params.minExitVelocity)
{'fraction_non_alphanumeric': 0.07482993197278912, 'fraction_numerical': 0.007126660187884677, 'mean_word_length': 3.0676328502415457, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '6708828', 'n_tokens_mistral': 2601, 'n_tokens_neox': 2453, 'n_words': 630}