<commit_before>//
//  OJFTextRevealView.swift
//  TextReveal
//
//  Created by <NAME> on 22/01/2015.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import UIKit

@IBDesignable class OJFTextRevealView: UIView {

    private let revealLabel1 = UILabel()
    private let revealLabel2 = UILabel()
    
    private var currentLabel:UILabel!
    
    var font: UIFont = .systemFontOfSize(21)
    @IBInspectable var color: UIColor = .blackColor()
    @IBInspectable var fadeDuration: Double = 0.4
    @IBInspectable var fadeDelay: Double = 0.4

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        setupView()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupView()
    }
    
    private func setupView() -> Void {
        self.backgroundColor = .clearColor()
        
        revealLabel1.textAlignment = .Center
        revealLabel2.textAlignment = .Center
        
        revealLabel1.numberOfLines = 0
        revealLabel2.numberOfLines = 0
        
        addSubview(revealLabel1)
        addSubview(revealLabel2)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        
        revealLabel1.frame = bounds
        revealLabel2.frame = bounds
    }

    override func prepareForInterfaceBuilder() {
        revealLabel1.text = "Hello, world!"
        revealLabel1.textColor = color
        revealLabel1.font = .systemFontOfSize(21)
        revealLabel1.textAlignment = .Center
        revealLabel1.numberOfLines = 0
    }
    
    func displayText(newText: String) -> Void {
        revealLabel1.attributedText = NSMutableAttributedString(string: newText, attributes: [NSForegroundColorAttributeName: UIColor.clearColor(),
            NSFontAttributeName: font])
        currentLabel = revealLabel1
        
        let letterRanges = self.letterRangeDictionaryFromText(self.revealLabel1.attributedText.string as NSString)
        
        let rangesArray: [[NSRange]] = self.shuffle([[NSRange]](letterRanges.values))
        
        let attributedTextArray = self.attributedTextArrayFromRanges(rangesArray, baseAttributedString: self.revealLabel1.attributedText)
        
        dispatch_async(dispatch_get_main_queue()) {
            self.animateTextAtIndex(0, fromArray: attributedTextArray, duration: self.fadeDuration, delay: self.fadeDelay)
        }
    }
    
    private func letterRangeDictionaryFromText(text: NSString) -> [String : [NSRange]] {
        var letterRanges: [String : [NSRange]] = [:]
        let whiteSpaces: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()
        
        text.enumerateSubstringsInRange(NSMakeRange(0, text.length),
            options: NSStringEnumerationOptions.ByComposedCharacterSequences) {
                (substring, substringRange, enclosingRange, stop) -> () in
                
                if let range = substring.rangeOfCharacterFromSet(whiteSpaces, options: nil, range: nil) {
                    return
                }
                <commit_msg>Removed unneeded main thread dispatch.<commit_after>//
//  OJFTextRevealView.swift
//  TextReveal
//
//  Created by <NAME> on 22/01/2015.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import UIKit

@IBDesignable class OJFTextRevealView: UIView {

    private let revealLabel1 = UILabel()
    private let revealLabel2 = UILabel()
    
    private var currentLabel:UILabel!
    
    var font: UIFont = .systemFontOfSize(21)
    @IBInspectable var color: UIColor = .blackColor()
    @IBInspectable var fadeDuration: Double = 0.4
    @IBInspectable var fadeDelay: Double = 0.4

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        setupView()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupView()
    }
    
    private func setupView() -> Void {
        self.backgroundColor = .clearColor()
        
        revealLabel1.textAlignment = .Center
        revealLabel2.textAlignment = .Center
        
        revealLabel1.numberOfLines = 0
        revealLabel2.numberOfLines = 0
        
        addSubview(revealLabel1)
        addSubview(revealLabel2)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        
        revealLabel1.frame = bounds
        revealLabel2.frame = bounds
    }

    override func prepareForInterfaceBuilder() {
        revealLabel1.text = "Hello, world!"
        revealLabel1.textColor = color
        revealLabel1.font = .systemFontOfSize(21)
        revealLabel1.textAlignment = .Center
        revealLabel1.numberOfLines = 0
    }
    
    func displayText(newText: String) -> Void {
        revealLabel1.attributedText = NSMutableAttributedString(string: newText, attributes: [NSForegroundColorAttributeName: UIColor.clearColor(),
            NSFontAttributeName: font])
        currentLabel = revealLabel1
        
        let letterRanges = self.letterRangeDictionaryFromText(self.revealLabel1.attributedText.string as NSString)
        
        let rangesArray: [[NSRange]] = self.shuffle([[NSRange]](letterRanges.values))
        
        let attributedTextArray = self.attributedTextArrayFromRanges(rangesArray, baseAttributedString: self.revealLabel1.attributedText)
        
        self.animateTextAtIndex(0, fromArray: attributedTextArray, duration: self.fadeDuration, delay: self.fadeDelay)
    }
    
    private func letterRangeDictionaryFromText(text: NSString) -> [String : [NSRange]] {
        var letterRanges: [String : [NSRange]] = [:]
        let whiteSpaces: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()
        
        text.enumerateSubstringsInRange(NSMakeRange(0, text.length),
            options: NSStringEnumerationOptions.ByComposedCharacterSequences) {
                (substring, substringRange, enclosingRange, stop) -> () in
                
                if let range = substring.rangeOfCharacterFromSet(whiteSpaces, options: nil, range: nil) {
                    return
                }
                
{'fraction_non_alphanumeric': 0.08649269653700968, 'fraction_numerical': 0.01444280321680617, 'mean_word_length': 2.4802969731581954, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, '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': '4208496', 'n_tokens_mistral': 1809, 'n_tokens_neox': 1736, 'n_words': 343}