diff --git a/Signal/Signal-Prefix.pch b/Signal/Signal-Prefix.pch index 27fe91e1d..bf34561b0 100644 --- a/Signal/Signal-Prefix.pch +++ b/Signal/Signal-Prefix.pch @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import @@ -15,7 +15,7 @@ static const NSUInteger ddLogLevel = DDLogLevelInfo; #endif - #import + #import #import #import #import diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index a60b35755..cbef62759 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import @@ -58,7 +58,6 @@ #import #import #import -#import #import #import #import @@ -72,6 +71,7 @@ #import #import #import +#import #import #import #import diff --git a/Signal/src/ViewControllers/AboutTableViewController.m b/Signal/src/ViewControllers/AboutTableViewController.m index 3e50c9c27..a0efd3199 100644 --- a/Signal/src/ViewControllers/AboutTableViewController.m +++ b/Signal/src/ViewControllers/AboutTableViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "AboutTableViewController.h" @@ -75,11 +75,14 @@ threadCount = [[transaction ext:TSThreadDatabaseViewExtensionName] numberOfItemsInAllGroups]; messageCount = [[transaction ext:TSMessageDatabaseViewExtensionName] numberOfItemsInAllGroups]; }]; + unsigned long long databaseFileSize = [TSStorageManager.sharedManager databaseFileSize]; OWSTableSection *debugSection = [OWSTableSection new]; debugSection.headerTitle = @"Debug"; [debugSection addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"Threads: %zd", threadCount]]]; [debugSection addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"Messages: %zd", messageCount]]]; + [debugSection + addItem:[OWSTableItem labelItemWithText:[NSString stringWithFormat:@"Database size: %llu", databaseFileSize]]]; [contents addSection:debugSection]; OWSPreferences *preferences = [Environment preferences]; diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 0971fdd98..bfca7e7a8 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -146,7 +146,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver { func observeNotifications() { NotificationCenter.default.addObserver(self, selector:#selector(didBecomeActive), - name:NSNotification.Name.UIApplicationDidBecomeActive, + name:NSNotification.Name.OWSApplicationDidBecomeActive, object:nil) NotificationCenter.default.addObserver(forName: CallAudioServiceSessionChanged, object: nil, queue: nil) { [weak self] _ in diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 1d13ae902..caf084ff5 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "ConversationViewController.h" @@ -302,19 +302,19 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) - name:UIApplicationWillEnterForegroundNotification + name:OWSApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification + name:OWSApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) - name:UIApplicationWillResignActiveNotification + name:OWSApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancelReadTimer) - name:UIApplicationDidEnterBackgroundNotification + name:OWSApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherUsersProfileDidChange:) diff --git a/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift b/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift index 89d7f5036..c0019fd33 100644 --- a/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift +++ b/Signal/src/ViewControllers/GifPicker/GifPickerViewController.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -127,7 +127,7 @@ class GifPickerViewController: OWSViewController, UISearchBarDelegate, UICollect object: nil) NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), - name: NSNotification.Name.UIApplicationDidBecomeActive, + name: NSNotification.Name.OWSApplicationDidBecomeActive, object: nil) } diff --git a/Signal/src/ViewControllers/HomeViewController.m b/Signal/src/ViewControllers/HomeViewController.m index 4bfc51d57..69cfc85b2 100644 --- a/Signal/src/ViewControllers/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeViewController.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "HomeViewController.h" @@ -124,24 +124,24 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) - name:UIApplicationWillEnterForegroundNotification + name:OWSApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification + name:OWSApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification + name:OWSApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yapDatabaseModified:) name:YapDatabaseModifiedNotification - object:nil]; + object:TSStorageManager.sharedManager.dbNotificationObject]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yapDatabaseModifiedExternally:) name:YapDatabaseModifiedExternallyNotification - object:nil]; + object:TSStorageManager.sharedManager.dbNotificationObject]; } - (void)dealloc diff --git a/Signal/src/call/CallService.swift b/Signal/src/call/CallService.swift index 090d067b7..5c4b4f826 100644 --- a/Signal/src/call/CallService.swift +++ b/Signal/src/call/CallService.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -230,11 +230,11 @@ protocol CallServiceObserver: class { NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground), - name: NSNotification.Name.UIApplicationDidEnterBackground, + name: NSNotification.Name.OWSApplicationDidEnterBackground, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), - name: NSNotification.Name.UIApplicationDidBecomeActive, + name: NSNotification.Name.OWSApplicationDidBecomeActive, object: nil) } diff --git a/Signal/src/network/GiphyDownloader.swift b/Signal/src/network/GiphyDownloader.swift index 47b1949d7..7c65a216e 100644 --- a/Signal/src/network/GiphyDownloader.swift +++ b/Signal/src/network/GiphyDownloader.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -848,7 +848,7 @@ extension URLSessionTask { } // Don't back up Giphy downloads. - OWSFileSystem.protectFolder(atPath:dirPath) + OWSFileSystem.protectFileOrFolder(atPath:dirPath) } catch let error as NSError { owsFail("\(GiphyAsset.TAG) ensureTempFolder failed: \(dirPath), \(error)") gifFolderPath = tempDirPath diff --git a/Signal/src/util/MainAppContext.m b/Signal/src/util/MainAppContext.m index d4e825ecb..1b4f45d9b 100644 --- a/Signal/src/util/MainAppContext.m +++ b/Signal/src/util/MainAppContext.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "MainAppContext.h" @@ -53,28 +53,46 @@ NS_ASSUME_NONNULL_BEGIN - (void)applicationWillEnterForeground:(NSNotification *)notification { + AssertIsOnMainThread(); + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); + + [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillEnterForegroundNotification object:nil]; } - (void)applicationDidEnterBackground:(NSNotification *)notification { + AssertIsOnMainThread(); + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); [DDLog flushLog]; + + [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidEnterBackgroundNotification object:nil]; } - (void)applicationWillResignActive:(NSNotification *)notification { + AssertIsOnMainThread(); + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); [DDLog flushLog]; + + [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillResignActiveNotification object:nil]; } - (void)applicationDidBecomeActive:(NSNotification *)notification { + AssertIsOnMainThread(); + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); + + [NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidBecomeActiveNotification object:nil]; } - (void)applicationWillTerminate:(NSNotification *)notification { + AssertIsOnMainThread(); + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); [DDLog flushLog]; } diff --git a/Signal/src/views/MarqueeLabel.swift b/Signal/src/views/MarqueeLabel.swift index 96da084f3..13b4508f7 100644 --- a/Signal/src/views/MarqueeLabel.swift +++ b/Signal/src/views/MarqueeLabel.swift @@ -1,10 +1,5 @@ -// Grabbed from: https://github.com/cbpowell/MarqueeLabel-Swift/blob/cd331f3cfc3f9d7114ffa5aa4f243f1d5eda9d0d/Classes/MarqueeLabel.swift -// License: MIT License // -// MarqueeLabel.swift -// -// Created by Charles Powell on 8/6/14. -// Copyright (c) 2015 Charles Powell. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import UIKit @@ -13,7 +8,7 @@ import QuartzCore @IBDesignable open class MarqueeLabel: UILabel, CAAnimationDelegate { - + /** An enum that defines the types of `MarqueeLabel` scrolling @@ -32,11 +27,11 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { case continuous case continuousReverse } - + // // MARK: - Public properties // - + /** Defines the direction and method in which the `MarqueeLabel` instance scrolls. `MarqueeLabel` supports six default types of scrolling: `Left`, `LeftRight`, `Right`, `RightLeft`, `Continuous`, and `ContinuousReverse`. @@ -61,7 +56,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { updateAndScroll() } } - + /** An optional custom scroll "sequence", defined by an array of `ScrollStep` or `FadeStep` instances. A sequence defines a single scroll/animation loop, which will continue to be automatically repeated like the default types. @@ -85,7 +80,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { - SeeAlso: FadeStep */ open var scrollSequence: Array? - + /** Specifies the animation curve used in the scrolling motion of the labels. Allowable options: @@ -98,7 +93,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { Defaults to `UIViewAnimationOptionCurveEaseInOut`. */ open var animationCurve: UIViewAnimationCurve = .linear - + /** A boolean property that sets whether the `MarqueeLabel` should behave like a normal `UILabel`. @@ -124,7 +119,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + /** A boolean property that sets whether the `MarqueeLabel` should hold (prevent) automatic label scrolling. @@ -147,7 +142,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + /** A boolean property that sets whether the `MarqueeLabel` should only begin a scroll when tapped. @@ -175,7 +170,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + /** A read-only boolean property that indicates if the label's scroll animation has been paused. @@ -185,7 +180,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { open var isPaused: Bool { return (sublabel.layer.speed == 0.0) } - + /** A boolean property that indicates if the label is currently away from the home location. @@ -195,10 +190,10 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { if let presentationLayer = sublabel.layer.presentation() { return !(presentationLayer.position.x == homeLabelFrame.origin.x) } - + return false } - + /** The `MarqueeLabel` scrolling speed may be defined by one of two ways: - Rate(CGFloat): The speed is defined by a rate of motion, in units of points per second. @@ -209,7 +204,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { public enum SpeedLimit { case rate(CGFloat) case duration(CGFloat) - + var value: CGFloat { switch self { case .rate(let rate): @@ -219,7 +214,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + /** Defines the speed of the `MarqueeLabel` scrolling animation. @@ -239,7 +234,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + @available(*, deprecated : 2.6, message : "Use speed property instead") @IBInspectable open var scrollDuration: CGFloat { get { @@ -252,7 +247,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { speed = .duration(newValue) } } - + @available(*, deprecated : 2.6, message : "Use speed property instead") @IBInspectable open var scrollRate: CGFloat { get { @@ -265,7 +260,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { speed = .rate(newValue) } } - + /** A buffer (offset) between the leading edge of the label text and the label frame. @@ -289,7 +284,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + /** A buffer (offset) between the trailing edge of the label text and the label frame. @@ -313,7 +308,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + /** The length of transparency fade at the left and right edges of the frame. @@ -331,25 +326,23 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - - + /** The length of delay in seconds that the label pauses at the completion of a scroll. */ @IBInspectable open var animationDelay: CGFloat = 1.0 - - + /** The read-only duration of the scroll animation (not including delay). The value of this property is calculated from the value set to the `speed` property. If a .duration value is used to set the label animation speed, this value will be equivalent. */ private(set) public var animationDuration: CGFloat = 0.0 - + // // MARK: - Class Functions and Helpers // - + /** Convenience method to restart all `MarqueeLabel` instances that have the specified view controller in their next responder chain. @@ -368,7 +361,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { open class func restartLabelsOfController(_ controller: UIViewController) { MarqueeLabel.notifyController(controller, message: .Restart) } - + /** Convenience method to restart all `MarqueeLabel` instances that have the specified view controller in their next responder chain. @@ -381,7 +374,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { open class func controllerViewWillAppear(_ controller: UIViewController) { MarqueeLabel.restartLabelsOfController(controller) } - + /** Convenience method to restart all `MarqueeLabel` instances that have the specified view controller in their next responder chain. @@ -394,7 +387,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { open class func controllerViewDidAppear(_ controller: UIViewController) { MarqueeLabel.restartLabelsOfController(controller) } - + /** Labelizes all `MarqueeLabel` instances that have the specified view controller in their next responder chain. @@ -406,7 +399,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { open class func controllerLabelsLabelize(_ controller: UIViewController) { MarqueeLabel.notifyController(controller, message: .Labelize) } - + /** De-labelizes all `MarqueeLabel` instances that have the specified view controller in their next responder chain. @@ -419,11 +412,10 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { MarqueeLabel.notifyController(controller, message: .Animate) } - // // MARK: - Initialization // - + /** Returns a newly initialized `MarqueeLabel` instance with the specified scroll rate and edge transparency fade length. @@ -439,7 +431,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { super.init(frame: frame) setup() } - + /** Returns a newly initialized `MarqueeLabel` instance with the specified scroll rate and edge transparency fade length. @@ -455,12 +447,12 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { super.init(frame: frame) setup() } - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } - + /** Returns a newly initialized `MarqueeLabel` instance. @@ -472,7 +464,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { convenience public override init(frame: CGRect) { self.init(frame: frame, duration:7.0, fadeLength:0.0) } - + private func setup() { // Create sublabel sublabel = UILabel(frame: self.bounds) @@ -481,46 +473,46 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { // Add sublabel addSubview(sublabel) - + // Configure self super.clipsToBounds = true super.numberOfLines = 1 - + // Add notification observers // Custom class notifications NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.restartForViewController(_:)), name: NSNotification.Name(rawValue: MarqueeKeys.Restart.rawValue), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.labelizeForController(_:)), name: NSNotification.Name(rawValue: MarqueeKeys.Labelize.rawValue), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.animateForController(_:)), name: NSNotification.Name(rawValue: MarqueeKeys.Animate.rawValue), object: nil) // UIApplication state notifications - NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.restartLabel), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.shutdownLabel), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.restartLabel), name: NSNotification.Name.OWSApplicationDidBecomeActive, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(MarqueeLabel.shutdownLabel), name: NSNotification.Name.OWSApplicationDidEnterBackground, object: nil) } - + override open func awakeFromNib() { super.awakeFromNib() forwardPropertiesToSublabel() } - + @available(iOS 8.0, *) override open func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() forwardPropertiesToSublabel() } - + private func forwardPropertiesToSublabel() { /* Note that this method is currently ONLY called from awakeFromNib, i.e. when text properties are set via a Storyboard. As the Storyboard/IB doesn't currently support attributed strings, there's no need to "forward" the super attributedString value. */ - + // Since we're a UILabel, we actually do implement all of UILabel's properties. // We don't care about these values, we just want to forward them on to our sublabel. let properties = ["baselineAdjustment", "enabled", "highlighted", "highlightedTextColor", "minimumFontSize", "shadowOffset", "textAlignment", "userInteractionEnabled", "adjustsFontSizeToFitWidth", "lineBreakMode", "numberOfLines", "contentMode"] - + // Iterate through properties sublabel.text = super.text sublabel.font = super.font @@ -533,14 +525,14 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { sublabel.setValue(value, forKeyPath: prop) } } - + // // MARK: - MarqueeLabel Heavy Lifting // override open func layoutSubviews() { super.layoutSubviews() - + updateAndScroll(true) } @@ -549,7 +541,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { shutdownLabel() } } - + override open func didMoveToWindow() { if self.window == nil { shutdownLabel() @@ -557,33 +549,33 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { updateAndScroll() } } - + private func updateAndScroll() { updateAndScroll(true) } - + private func updateAndScroll(_ shouldBeginScroll: Bool) { // Check if scrolling can occur if !labelReadyForScroll() { return } - + // Calculate expected size let expectedLabelSize = sublabelSize() - + // Invalidate intrinsic size invalidateIntrinsicContentSize() - + // Move label to home returnLabelToHome() - + // Check if label should scroll // Note that the holdScrolling propery does not affect this if !labelShouldScroll() { // Set text alignment and break mode to act like a normal label sublabel.textAlignment = super.textAlignment sublabel.lineBreakMode = super.lineBreakMode - + let labelFrame: CGRect switch type { case .continuousReverse, .rightLeft: @@ -591,24 +583,24 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { default: labelFrame = CGRect(x: leadingBuffer, y: 0.0, width: bounds.size.width - leadingBuffer, height: bounds.size.height).integral } - + homeLabelFrame = labelFrame awayOffset = 0.0 - + // Remove an additional sublabels (for continuous types) - repliLayer?.instanceCount = 1; - + repliLayer?.instanceCount = 1 + // Set the sublabel frame to calculated labelFrame sublabel.frame = labelFrame - + // Remove fade, as by definition none is needed in this case removeGradientMask() - + return } - + // Label DOES need to scroll - + // Recompute the animation duration animationDuration = { switch self.speed { @@ -618,13 +610,13 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { return duration } }() - + // Spacing between primary and second sublabel must be at least equal to leadingBuffer, and at least equal to the fadeLength let minTrailing = max(max(leadingBuffer, trailingBuffer), fadeLength) - + // Determine positions and generate scroll steps let sequence: [MarqueeStep] - + switch type { case .continuous, .continuousReverse: if (type == .continuous) { @@ -634,7 +626,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { homeLabelFrame = CGRect(x: bounds.size.width - (expectedLabelSize.width + leadingBuffer), y: 0.0, width: expectedLabelSize.width, height: bounds.size.height).integral awayOffset = (homeLabelFrame.size.width + minTrailing) } - + // Find when the lead label will be totally offscreen let offsetDistance = awayOffset let offscreenAmount = homeLabelFrame.size.width @@ -642,7 +634,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { // Find when the animation will hit that point let startFadeTimeFraction = timingFunctionForAnimationCurve(animationCurve).durationPercentageForPositionPercentage(startFadeFraction, duration: (animationDelay + animationDuration)) let startFadeTime = startFadeTimeFraction * animationDuration - + sequence = scrollSequence ?? [ ScrollStep(timeStep: 0.0, position: .home, edgeFades: .trailing), // Starting point, at home, with trailing fade ScrollStep(timeStep: animationDelay, position: .home, edgeFades: .trailing), // Delay at home, maintaining fade state @@ -652,14 +644,14 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { ScrollStep(timeStep: animationDuration, timingFunction: animationCurve, // Ending point (back at home), with animationCurve transition, with trailing fade position: .away, edgeFades: .trailing) ] - + // Set frame and text sublabel.frame = homeLabelFrame - + // Configure replication repliLayer?.instanceCount = 2 repliLayer?.instanceTransform = CATransform3DMakeTranslation(-awayOffset, 0.0, 0.0) - + case .leftRight, .left, .rightLeft, .right: if (type == .leftRight || type == .left) { homeLabelFrame = CGRect(x: leadingBuffer, y: 0.0, width: expectedLabelSize.width, height: bounds.size.height).integral @@ -674,10 +666,10 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } // Set frame and text sublabel.frame = homeLabelFrame - + // Remove any replication repliLayer?.instanceCount = 1 - + if (type == .leftRight || type == .rightLeft) { sequence = scrollSequence ?? [ ScrollStep(timeStep: 0.0, position: .home, edgeFades: .trailing), // Starting point, at home, with trailing fade @@ -701,27 +693,25 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { ScrollStep(timeStep: animationDuration, timingFunction: animationCurve, // Away position, using animationCurve transition, with only leading edge faded in position: .away, edgeFades: .leading), ScrollStep(timeStep: 60*60*24*365.0, // "Delay" at away, for huge time to effectie stay at away permanently - position: .away, edgeFades: .leading), + position: .away, edgeFades: .leading) ] } } - - - + // Configure gradient for current condition applyGradientMask(fadeLength, animated: !self.labelize) - + if !tapToScroll && !holdScrolling && shouldBeginScroll { beginScroll(sequence) } } - + private func sublabelSize() -> CGSize { // Bound the expected size let maximumLabelSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude) // Calculate the expected size var expectedLabelSize = sublabel.sizeThatFits(maximumLabelSize) - + #if os(tvOS) // Sanitize width to 16384.0 (largest width a UILabel will draw on tvOS) expectedLabelSize.width = min(expectedLabelSize.width, 16384.0) @@ -734,45 +724,45 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { expectedLabelSize.height = bounds.size.height return expectedLabelSize } - + override open func sizeThatFits(_ size: CGSize) -> CGSize { var fitSize = sublabel.sizeThatFits(size) fitSize.width += leadingBuffer return fitSize } - + // // MARK: - Animation Handling // - + open func labelShouldScroll() -> Bool { // Check for nil string if sublabel.text == nil { return false } - + // Check for empty string if sublabel.text!.isEmpty { return false } - + // Check if the label string fits let labelTooLarge = (sublabelSize().width + leadingBuffer) > self.bounds.size.width + CGFloat.ulpOfOne let animationHasDuration = speed.value > 0.0 return (!labelize && labelTooLarge && animationHasDuration) } - + private func labelReadyForScroll() -> Bool { // Check if we have a superview if superview == nil { return false } - + // Check if we are attached to a window if window == nil { return false } - + // Check if our view controller is ready let viewController = firstAvailableViewController() if viewController != nil { @@ -780,28 +770,28 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { return false } } - + return true } - + private func returnLabelToHome() { // Remove any gradient animation maskLayer?.removeAllAnimations() - + // Remove all sublabel position animations sublabel.layer.removeAllAnimations() - + // Remove completion block scrollCompletionBlock = nil } - + private func beginScroll(_ sequence: [MarqueeStep]) { let scroller = generateScrollAnimation(sequence) let fader = generateGradientAnimation(sequence, totalDuration: scroller.duration) - + scroll(scroller, fader: fader) } - + private func scroll(_ scroller: MLAnimation, fader: MLAnimation?) { // Check for conditions which would prevent scrolling if !labelReadyForScroll() { @@ -809,14 +799,14 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } // Convert fader to var var fader = fader - + // Call pre-animation hook labelWillBeginScroll() - + // Start animation transactions CATransaction.begin() CATransaction.setAnimationDuration(TimeInterval(scroller.duration)) - + // Create gradient animation, if needed let gradientAnimation: CAKeyframeAnimation? // Check for IBDesignable @@ -827,14 +817,14 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { maskLayer?.colors = finalColors } maskLayer?.removeAnimation(forKey: "setupFade") - + // Generate animation if needed if let previousAnimation = fader?.anim { gradientAnimation = previousAnimation } else { gradientAnimation = nil } - + // Apply fade animation maskLayer?.add(gradientAnimation!, forKey: "gradient") } else { @@ -842,22 +832,22 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { fader = nil } #else - fader = nil; + fader = nil #endif - - scrollCompletionBlock = { [weak self] (finished: Bool) -> () in + + scrollCompletionBlock = { [weak self] (finished: Bool) -> Void in guard finished else { // Do not continue into the next loop return } - + guard (self != nil) else { return } - + // Call returned home function self!.labelReturnedToHome(true) - + // Check to ensure that: // 1) We don't double fire if an animation already exists // 2) The instance is still attached to a window - this completion block is called for @@ -866,45 +856,45 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { guard self!.window != nil else { return } - + guard self!.sublabel.layer.animation(forKey: "position") == nil else { return } - + // Begin again, if conditions met if (self!.labelShouldScroll() && !self!.tapToScroll && !self!.holdScrolling) { // Perform completion callback self!.scroll(scroller, fader: fader) } } - + // Perform scroll animation scroller.anim.setValue(true, forKey: MarqueeKeys.CompletionClosure.rawValue) scroller.anim.delegate = self sublabel.layer.add(scroller.anim, forKey: "position") - + CATransaction.commit() } - + private func generateScrollAnimation(_ sequence: [MarqueeStep]) -> MLAnimation { // Create scroller, which defines the animation to perform let homeOrigin = homeLabelFrame.origin let awayOrigin = offsetCGPoint(homeLabelFrame.origin, offset: awayOffset) - + let scrollSteps = sequence.filter({ $0 is ScrollStep }) as! [ScrollStep] let totalDuration = scrollSteps.reduce(0.0) { $0 + $1.timeStep } - + // Build scroll data var totalTime: CGFloat = 0.0 var scrollKeyTimes = [NSNumber]() var scrollKeyValues = [NSValue]() var scrollTimingFunctions = [CAMediaTimingFunction]() - + for (offset, step) in scrollSteps.enumerated() { // Scroll Times totalTime += step.timeStep scrollKeyTimes.append(NSNumber(value:Float(totalTime/totalDuration))) - + // Scroll Values let scrollPosition: CGPoint switch step.position { @@ -916,23 +906,23 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { scrollPosition = offsetCGPoint(homeOrigin, offset: awayOffset*frac) } scrollKeyValues.append(NSValue(cgPoint:scrollPosition)) - + // Scroll Timing Functions // Only need n-1 timing functions, so discard the first value as it's unused if offset == 0 { continue } scrollTimingFunctions.append(timingFunctionForAnimationCurve(step.timingFunction)) } - + // Create animation let animation = CAKeyframeAnimation(keyPath: "position") // Set values animation.keyTimes = scrollKeyTimes animation.values = scrollKeyValues animation.timingFunctions = scrollTimingFunctions - + return (anim: animation, duration: totalDuration) } - + private func generateGradientAnimation(_ sequence: [MarqueeStep], totalDuration: CGFloat) -> MLAnimation { // Setup var totalTime: CGFloat = 0.0 @@ -942,26 +932,26 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { var fadeTimingFunctions = [CAMediaTimingFunction]() let transp = UIColor.clear.cgColor let opaque = UIColor.black.cgColor - + // Filter to get only scroll steps and valid precedent/subsequent fade steps let fadeSteps = sequence.enumerated().filter { (arg: (offset: Int, element: MarqueeStep)) -> Bool in let (offset, element) = arg - + // Include all Scroll Steps if element is ScrollStep { return true } - + // Include all Fade Steps that have a directly preceding or subsequent Scroll Step // Exception: Fade Step cannot be first step if offset == 0 { return false } - + // Subsequent step if 1) positive/zero time step and 2) follows a Scroll Step let subsequent = element.timeStep >= 0 && (sequence[max(0, offset - 1)] is ScrollStep) // Precedent step if 1) negative time step and 2) precedes a Scroll Step let precedent = element.timeStep < 0 && (sequence[min(sequence.count - 1, offset + 1)] is ScrollStep) - + return (precedent || subsequent) } - + for (offset, step) in fadeSteps { // Fade times if (step is ScrollStep) { @@ -977,7 +967,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } fadeKeyTimes.append(NSNumber(value:Float(stepTime/totalDuration))) - + // Fade Values let values: [CGColor] let leading = step.edgeFades.contains(.leading) ? transp : opaque @@ -989,37 +979,37 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { values = [trailing, opaque, opaque, leading] } fadeKeyValues.append(values) - + // Fade Timing Function // Only need n-1 timing functions, so discard the first value as it's unused if offset == 0 { continue } fadeTimingFunctions.append(timingFunctionForAnimationCurve(step.timingFunction)) } - + // Create new animation let animation = CAKeyframeAnimation(keyPath: "colors") - + animation.values = fadeKeyValues animation.keyTimes = fadeKeyTimes animation.timingFunctions = fadeTimingFunctions - - return (anim: animation, duration: max(totalTime,totalDuration)) + + return (anim: animation, duration: max(totalTime, totalDuration)) } - + private func applyGradientMask(_ fadeLength: CGFloat, animated: Bool, firstStep: MarqueeStep? = nil) { // Remove any in-flight animations maskLayer?.removeAllAnimations() - + // Check for zero-length fade if (fadeLength <= 0.0) { removeGradientMask() return } - + // Configure gradient mask without implicit animations CATransaction.begin() CATransaction.setDisableActions(true) - + // Determine if gradient mask needs to be created let gradientMask: CAGradientLayer if let currentMask = self.maskLayer { @@ -1033,7 +1023,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { gradientMask.startPoint = CGPoint(x:0.0, y:0.5) gradientMask.endPoint = CGPoint(x:1.0, y:0.5) } - + // Check if there is a mask to layer size mismatch if gradientMask.bounds != self.layer.bounds { // Adjust stops based on fade length @@ -1041,41 +1031,41 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { let rightFadeStop = 1.0 - fadeLength/self.bounds.size.width gradientMask.locations = [0.0, leftFadeStop, rightFadeStop, 1.0].map { NSNumber(value: Float($0)) } } - + gradientMask.bounds = self.layer.bounds gradientMask.position = CGPoint(x:self.bounds.midX, y:self.bounds.midY) - + // Set up colors let transparent = UIColor.clear.cgColor let opaque = UIColor.black.cgColor - + // Set mask self.layer.mask = gradientMask - + // Determine colors for non-scrolling label (i.e. at home) let adjustedColors: [CGColor] let trailingFadeNeeded = self.labelShouldScroll() - + switch (type) { case .continuousReverse, .rightLeft: adjustedColors = [(trailingFadeNeeded ? transparent : opaque), opaque, opaque, opaque] - + // .Continuous, .LeftRight default: adjustedColors = [opaque, opaque, opaque, (trailingFadeNeeded ? transparent : opaque)] } - + // Check for IBDesignable #if TARGET_INTERFACE_BUILDER gradientMask.colors = adjustedColors CATransaction.commit() return #endif - + if (animated) { // Finish transaction CATransaction.commit() - + // Create animation for color change let colorAnimation = GradientSetupAnimation(keyPath: "colors") colorAnimation.fromValue = gradientMask.colors @@ -1089,14 +1079,14 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { CATransaction.commit() } } - + private func removeGradientMask() { self.layer.mask = nil } - + private func timingFunctionForAnimationCurve(_ curve: UIViewAnimationCurve) -> CAMediaTimingFunction { let timingFunction: String? - + switch curve { case .easeIn: timingFunction = kCAMediaTimingFunctionEaseIn @@ -1107,10 +1097,10 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { default: timingFunction = kCAMediaTimingFunctionLinear } - + return CAMediaTimingFunction(name: timingFunction!) } - + private func transactionDurationType(_ labelType: MarqueeType, interval: CGFloat, delay: CGFloat) -> TimeInterval { switch (labelType) { case .leftRight, .rightLeft: @@ -1119,7 +1109,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { return TimeInterval(delay + interval) } } - + public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if let setupAnim = anim as? GradientSetupAnimation { if let finalColors = setupAnim.toValue as? [CGColor] { @@ -1131,53 +1121,52 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { scrollCompletionBlock?(flag) } } - - + // // MARK: - Private details // - + private var sublabel = UILabel() - + fileprivate var homeLabelFrame = CGRect.zero fileprivate var awayOffset: CGFloat = 0.0 - + override open class var layerClass: AnyClass { return CAReplicatorLayer.self } - + fileprivate weak var repliLayer: CAReplicatorLayer? { return self.layer as? CAReplicatorLayer } - + fileprivate weak var maskLayer: CAGradientLayer? { return self.layer.mask as! CAGradientLayer? } - + fileprivate var scrollCompletionBlock: MLAnimationCompletionBlock? - + override open func draw(_ layer: CALayer, in ctx: CGContext) { // Do NOT call super, to prevent UILabel superclass from drawing into context // Label drawing is handled by sublabel and CAReplicatorLayer layer class - + // Draw only background color if let bgColor = backgroundColor { - ctx.setFillColor(bgColor.cgColor); - ctx.fill(layer.bounds); + ctx.setFillColor(bgColor.cgColor) + ctx.fill(layer.bounds) } } - + fileprivate enum MarqueeKeys: String { case Restart = "MLViewControllerRestart" case Labelize = "MLShouldLabelize" case Animate = "MLShouldAnimate" case CompletionClosure = "MLAnimationCompletion" } - + class fileprivate func notifyController(_ controller: UIViewController, message: MarqueeKeys) { NotificationCenter.default.post(name: Notification.Name(rawValue: message.rawValue), object: nil, userInfo: ["controller" : controller]) } - + @objc public func restartForViewController(_ notification: Notification) { if let controller = (notification as NSNotification).userInfo?["controller"] as? UIViewController { if controller === self.firstAvailableViewController() { @@ -1185,7 +1174,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + @objc public func labelizeForController(_ notification: Notification) { if let controller = (notification as NSNotification).userInfo?["controller"] as? UIViewController { if controller === self.firstAvailableViewController() { @@ -1193,7 +1182,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - + @objc public func animateForController(_ notification: Notification) { if let controller = (notification as NSNotification).userInfo?["controller"] as? UIViewController { if controller === self.firstAvailableViewController() { @@ -1201,12 +1190,11 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { } } } - - + // // MARK: - Label Control // - + /** Overrides any non-size condition which is preventing the receiver from automatically scrolling, and begins a scroll animation. @@ -1226,7 +1214,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { updateAndScroll() } } - + /** Immediately resets the label to the home position, cancelling any in-flight scroll animation, and restarts the scroll animation if the appropriate conditions are met. @@ -1241,7 +1229,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { updateAndScroll() } } - + /** Resets the label text, recalculating the scroll animation. @@ -1256,7 +1244,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { homeLabelFrame = CGRect.null awayOffset = 0.0 } - + /** Immediately resets the label to the home position, cancelling any in-flight scroll animation. @@ -1273,7 +1261,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { // Apply gradient mask for home location applyGradientMask(fadeLength, animated: false) } - + /** Pauses the text scrolling animation, at any point during an in-progress animation. @@ -1287,18 +1275,18 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { guard (!isPaused && awayFromHome) else { return } - + // Pause sublabel position animations let labelPauseTime = sublabel.layer.convertTime(CACurrentMediaTime(), from: nil) sublabel.layer.speed = 0.0 sublabel.layer.timeOffset = labelPauseTime - + // Pause gradient fade animation let gradientPauseTime = maskLayer?.convertTime(CACurrentMediaTime(), from:nil) maskLayer?.speed = 0.0 maskLayer?.timeOffset = gradientPauseTime! } - + /** Un-pauses a previously paused text scrolling animation. This method has no effect if the label was not previously paused using `pauseLabel`. @@ -1309,14 +1297,14 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { guard (isPaused) else { return } - + // Unpause sublabel position animations let labelPausedTime = sublabel.layer.timeOffset sublabel.layer.speed = 1.0 sublabel.layer.timeOffset = 0.0 sublabel.layer.beginTime = 0.0 sublabel.layer.beginTime = sublabel.layer.convertTime(CACurrentMediaTime(), from:nil) - labelPausedTime - + // Unpause gradient fade animation let gradientPauseTime = maskLayer?.timeOffset maskLayer?.speed = 1.0 @@ -1324,13 +1312,13 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { maskLayer?.beginTime = 0.0 maskLayer?.beginTime = maskLayer!.convertTime(CACurrentMediaTime(), from:nil) - gradientPauseTime! } - + @objc public func labelWasTapped(_ recognizer: UIGestureRecognizer) { if labelShouldScroll() && !awayFromHome { updateAndScroll() } } - + /** Called when the label animation is about to begin. @@ -1341,7 +1329,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { // Default implementation does nothing - override to customize return } - + /** Called when the label animation has finished, and the label is at the home position. @@ -1357,17 +1345,17 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { // Default implementation does nothing - override to customize return } - + // // MARK: - Modified UILabel Functions/Getters/Setters // - + #if os(iOS) override open func forBaselineLayout() -> UIView { // Use subLabel view for handling baseline layouts return sublabel } - + override open var forLastBaselineLayout: UIView { // Use subLabel view for handling baseline layouts return sublabel @@ -1378,7 +1366,7 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { get { return sublabel.text } - + set { if sublabel.text == newValue { return @@ -1388,12 +1376,12 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { super.text = text } } - + override open var attributedText: NSAttributedString? { get { return sublabel.attributedText } - + set { if sublabel.attributedText == newValue { return @@ -1403,195 +1391,193 @@ open class MarqueeLabel: UILabel, CAAnimationDelegate { super.attributedText = attributedText } } - + override open var font: UIFont! { get { return sublabel.font } - + set { if sublabel.font == newValue { return } sublabel.font = newValue super.font = newValue - + updateAndScroll() } } - + override open var textColor: UIColor! { get { return sublabel.textColor } - + set { sublabel.textColor = newValue super.textColor = newValue } } - + override open var backgroundColor: UIColor? { get { return sublabel.backgroundColor } - + set { sublabel.backgroundColor = newValue super.backgroundColor = newValue } } - + override open var shadowColor: UIColor? { get { return sublabel.shadowColor } - + set { sublabel.shadowColor = newValue super.shadowColor = newValue } } - + override open var shadowOffset: CGSize { get { return sublabel.shadowOffset } - + set { sublabel.shadowOffset = newValue super.shadowOffset = newValue } } - + override open var highlightedTextColor: UIColor? { get { return sublabel.highlightedTextColor } - + set { sublabel.highlightedTextColor = newValue super.highlightedTextColor = newValue } } - + override open var isHighlighted: Bool { get { return sublabel.isHighlighted } - + set { sublabel.isHighlighted = newValue super.isHighlighted = newValue } } - + override open var isEnabled: Bool { get { return sublabel.isEnabled } - + set { sublabel.isEnabled = newValue super.isEnabled = newValue } } - + override open var numberOfLines: Int { get { return super.numberOfLines } - + set { // By the nature of MarqueeLabel, this is 1 super.numberOfLines = 1 } } - + override open var adjustsFontSizeToFitWidth: Bool { get { return super.adjustsFontSizeToFitWidth } - + set { // By the nature of MarqueeLabel, this is false super.adjustsFontSizeToFitWidth = false } } - + override open var minimumScaleFactor: CGFloat { get { return super.minimumScaleFactor } - + set { super.minimumScaleFactor = 0.0 } } - + override open var baselineAdjustment: UIBaselineAdjustment { get { return sublabel.baselineAdjustment } - + set { sublabel.baselineAdjustment = newValue super.baselineAdjustment = newValue } } - + override open var intrinsicContentSize: CGSize { var content = sublabel.intrinsicContentSize content.width += leadingBuffer return content } - + override open var tintColor: UIColor! { get { return sublabel.tintColor } - + set { sublabel.tintColor = newValue super.tintColor = newValue } } - + override open func tintColorDidChange() { super.tintColorDidChange() sublabel.tintColorDidChange() } - + override open var contentMode: UIViewContentMode { get { return sublabel.contentMode } - + set { super.contentMode = contentMode sublabel.contentMode = newValue } } - // // MARK: - Support // - + fileprivate func offsetCGPoint(_ point: CGPoint, offset: CGFloat) -> CGPoint { return CGPoint(x: point.x + offset, y: point.y) } - + // // MARK: - Deinit // - + deinit { NotificationCenter.default.removeObserver(self) } - -} +} // // MARK: - Support @@ -1602,7 +1588,6 @@ public protocol MarqueeStep { var edgeFades: EdgeFade { get } } - /** `ScrollStep` types define the label position at a specified time delta since the last `ScrollStep` step, as well as the animation curve to that position and edge fade state at the position @@ -1626,25 +1611,25 @@ public struct ScrollStep: MarqueeStep { case away case partial(CGFloat) } - + /** The desired time between this step and the previous `ScrollStep` in a sequence. */ public let timeStep: CGFloat - + /** The animation curve to utilize between the previous `ScrollStep` in a sequence and this step. - Note: The animation curve value for the first `ScrollStep` in a sequence has no effect. */ public let timingFunction: UIViewAnimationCurve - + /** The position of the label for this scroll step. - SeeAlso: Position */ public let position: Position - + /** The option set defining the edge fade state for this scroll step. @@ -1652,7 +1637,7 @@ public struct ScrollStep: MarqueeStep { the direction of scroll) and trailing edge of the label. */ public let edgeFades: EdgeFade - + public init(timeStep: CGFloat, timingFunction: UIViewAnimationCurve = .linear, position: Position, edgeFades: EdgeFade) { self.timeStep = timeStep self.position = position @@ -1661,7 +1646,6 @@ public struct ScrollStep: MarqueeStep { } } - /** `FadeStep` types allow additional edge fade state definitions, around the states defined by the `ScrollStep` steps of a sequence. `FadeStep` steps are defined by the time delta to the preceding or subsequent `ScrollStep` step and the timing @@ -1683,12 +1667,12 @@ public struct FadeStep: MarqueeStep { a `ScrollStep`. */ public let timeStep: CGFloat - + /** The animation curve to utilize between the previous fade state in a sequence and this step. */ public let timingFunction: UIViewAnimationCurve - + /** The option set defining the edge fade state for this fade step. @@ -1698,7 +1682,7 @@ public struct FadeStep: MarqueeStep { As an Option Set type, both edge fade states may be defined using an array literal: `[.leading, .trailing]`. */ public let edgeFades: EdgeFade - + public init(timeStep: CGFloat, timingFunction: UIViewAnimationCurve = .linear, edgeFades: EdgeFade) { self.timeStep = timeStep self.timingFunction = timingFunction @@ -1706,32 +1690,32 @@ public struct FadeStep: MarqueeStep { } } -public struct EdgeFade : OptionSet { +public struct EdgeFade: OptionSet { public let rawValue: Int public static let leading = EdgeFade(rawValue: 1 << 0) public static let trailing = EdgeFade(rawValue: 1 << 1) - + public init(rawValue: Int) { - self.rawValue = rawValue; + self.rawValue = rawValue } } // Define helpful typealiases -fileprivate typealias MLAnimationCompletionBlock = (_ finished: Bool) -> () +fileprivate typealias MLAnimationCompletionBlock = (_ finished: Bool) -> Void fileprivate typealias MLAnimation = (anim: CAKeyframeAnimation, duration: CGFloat) -fileprivate class GradientSetupAnimation: CABasicAnimation { +private class GradientSetupAnimation: CABasicAnimation { } fileprivate extension UIResponder { // Thanks to Phil M // http://stackoverflow.com/questions/1340434/get-to-uiviewcontroller-from-uiview-on-iphone - + func firstAvailableViewController() -> UIViewController? { // convenience function for casting and to "mask" the recursive function return self.traverseResponderChainForFirstViewController() } - + func traverseResponderChainForFirstViewController() -> UIViewController? { if let nextResponder = self.next { if nextResponder is UIViewController { @@ -1747,30 +1731,30 @@ fileprivate extension UIResponder { } fileprivate extension CAMediaTimingFunction { - + func durationPercentageForPositionPercentage(_ positionPercentage: CGFloat, duration: CGFloat) -> CGFloat { // Finds the animation duration percentage that corresponds with the given animation "position" percentage. // Utilizes Newton's Method to solve for the parametric Bezier curve that is used by CAMediaAnimation. - + let controlPoints = self.controlPoints() let epsilon: CGFloat = 1.0 / (100.0 * CGFloat(duration)) - + // Find the t value that gives the position percentage we want let t_found = solveTforY(positionPercentage, epsilon: epsilon, controlPoints: controlPoints) - + // With that t, find the corresponding animation percentage let durationPercentage = XforCurveAt(t_found, controlPoints: controlPoints) - + return durationPercentage } - + func solveTforY(_ y_0: CGFloat, epsilon: CGFloat, controlPoints: [CGPoint]) -> CGFloat { // Use Newton's Method: http://en.wikipedia.org/wiki/Newton's_method // For first guess, use t = y (i.e. if curve were linear) var t0 = y_0 var t1 = y_0 var f0, df0: CGFloat - + for _ in 0..<15 { // Base this iteration of t1 calculated from last iteration t0 = t1 @@ -1790,56 +1774,56 @@ fileprivate extension CAMediaTimingFunction { // Else recalculate t1 t1 = t0 - f0/df0 } - + // Give up - shouldn't ever get here...I hope print("MarqueeLabel: Failed to find t for Y input!") return t0 } - - func YforCurveAt(_ t: CGFloat, controlPoints:[CGPoint]) -> CGFloat { + + func YforCurveAt(_ t: CGFloat, controlPoints: [CGPoint]) -> CGFloat { let P0 = controlPoints[0] let P1 = controlPoints[1] let P2 = controlPoints[2] let P3 = controlPoints[3] - + // Per http://en.wikipedia.org/wiki/Bezier_curve#Cubic_B.C3.A9zier_curves - let y0 = (pow((1.0 - t),3.0) * P0.y) + let y0 = (pow((1.0 - t), 3.0) * P0.y) let y1 = (3.0 * pow(1.0 - t, 2.0) * t * P1.y) let y2 = (3.0 * (1.0 - t) * pow(t, 2.0) * P2.y) let y3 = (pow(t, 3.0) * P3.y) - + return y0 + y1 + y2 + y3 } - + func XforCurveAt(_ t: CGFloat, controlPoints: [CGPoint]) -> CGFloat { let P0 = controlPoints[0] let P1 = controlPoints[1] let P2 = controlPoints[2] let P3 = controlPoints[3] - + // Per http://en.wikipedia.org/wiki/Bezier_curve#Cubic_B.C3.A9zier_curves - - let x0 = (pow((1.0 - t),3.0) * P0.x) + + let x0 = (pow((1.0 - t), 3.0) * P0.x) let x1 = (3.0 * pow(1.0 - t, 2.0) * t * P1.x) let x2 = (3.0 * (1.0 - t) * pow(t, 2.0) * P2.x) let x3 = (pow(t, 3.0) * P3.x) - + return x0 + x1 + x2 + x3 } - + func derivativeCurveYValueAt(_ t: CGFloat, controlPoints: [CGPoint]) -> CGFloat { let P0 = controlPoints[0] let P1 = controlPoints[1] let P2 = controlPoints[2] let P3 = controlPoints[3] - + let dy0 = (P0.y + 3.0 * P1.y + 3.0 * P2.y - P3.y) * -3.0 let dy1 = t * (6.0 * P0.y + 6.0 * P2.y) let dy2 = (-3.0 * P0.y + 3.0 * P1.y) return dy0 * pow(t, 2.0) + dy1 + dy2 } - + func controlPoints() -> [CGPoint] { // Create point array to point to var point: [Float] = [0.0, 0.0] @@ -1848,8 +1832,7 @@ fileprivate extension CAMediaTimingFunction { self.getControlPoint(at: i, values: &point) pointArray.append(CGPoint(x: CGFloat(point[0]), y: CGFloat(point[1]))) } - + return pointArray } } - diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 987c5cf90..e93e381b1 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -656,7 +656,7 @@ "FINGERPRINT_SCAN_VERIFY_BUTTON" = "Mark as Verified"; /* No comment provided by engineer. */ -"FINGERPRINT_SHRED_KEYMATERIAL_BUTTON" = "Reset this session."; +"FINGERPRINT_SHRED_KEYMATERIAL_BUTTON" = "Reset this session"; /* Accessibilty label for finishing new group */ "FINISH_GROUP_CREATION_LABEL" = "Finish creating group"; diff --git a/SignalMessaging/SignalMessaging-Prefix.pch b/SignalMessaging/SignalMessaging-Prefix.pch index 27fe91e1d..bf34561b0 100644 --- a/SignalMessaging/SignalMessaging-Prefix.pch +++ b/SignalMessaging/SignalMessaging-Prefix.pch @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import @@ -15,7 +15,7 @@ static const NSUInteger ddLogLevel = DDLogLevelInfo; #endif - #import + #import #import #import #import diff --git a/SignalMessaging/Views/ThreadViewHelper.m b/SignalMessaging/Views/ThreadViewHelper.m index 76607bb7e..d765c5478 100644 --- a/SignalMessaging/Views/ThreadViewHelper.m +++ b/SignalMessaging/Views/ThreadViewHelper.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "ThreadViewHelper.h" @@ -57,11 +57,11 @@ NS_ASSUME_NONNULL_BEGIN [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) - name:UIApplicationWillEnterForegroundNotification + name:OWSApplicationWillEnterForegroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification + name:OWSApplicationDidEnterBackgroundNotification object:nil]; self.shouldObserveDBModifications diff --git a/SignalMessaging/attachments/OWSAudioAttachmentPlayer.m b/SignalMessaging/attachments/OWSAudioAttachmentPlayer.m index 52a5634b3..fc8990ca0 100644 --- a/SignalMessaging/attachments/OWSAudioAttachmentPlayer.m +++ b/SignalMessaging/attachments/OWSAudioAttachmentPlayer.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSAudioAttachmentPlayer.h" @@ -48,7 +48,7 @@ NS_ASSUME_NONNULL_BEGIN [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification + name:OWSApplicationDidEnterBackgroundNotification object:nil]; return self; diff --git a/SignalMessaging/contacts/SystemContactsFetcher.swift b/SignalMessaging/contacts/SystemContactsFetcher.swift index 0ed13a0d3..75742594d 100644 --- a/SignalMessaging/contacts/SystemContactsFetcher.swift +++ b/SignalMessaging/contacts/SystemContactsFetcher.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -57,7 +57,7 @@ class ContactsFrameworkContactStoreAdaptee: ContactStoreAdaptee { self.changeHandler = changeHandler self.lastSortOrder = CNContactsUserDefaults.shared().sortOrder NotificationCenter.default.addObserver(self, selector: #selector(runChangeHandler), name: .CNContactStoreDidChange, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: .UIApplicationDidBecomeActive, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: .OWSApplicationDidBecomeActive, object: nil) } @objc diff --git a/SignalMessaging/environment/AppSetup.m b/SignalMessaging/environment/AppSetup.m index abc3583cd..8c73aead7 100644 --- a/SignalMessaging/environment/AppSetup.m +++ b/SignalMessaging/environment/AppSetup.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "AppSetup.h" @@ -7,6 +7,7 @@ #import "Release.h" #import "VersionMigrations.h" #import +#import #import #import #import @@ -40,6 +41,10 @@ NS_ASSUME_NONNULL_BEGIN profileManager:OWSProfileManager.sharedManager]; [TextSecureKitEnv setSharedEnv:sharedEnv]; + // Register renamed classes. + [NSKeyedUnarchiver setClass:[OWSUserProfile class] forClassName:[OWSUserProfile collection]]; + [NSKeyedUnarchiver setClass:[OWSDatabaseMigration class] forClassName:[OWSDatabaseMigration collection]]; + [OWSStorage setupWithSafeBlockingMigrations:^{ [VersionMigrations runSafeBlockingMigrations]; }]; diff --git a/SignalMessaging/profiles/OWSProfileManager.m b/SignalMessaging/profiles/OWSProfileManager.m index 5bc3f644d..7349e3390 100644 --- a/SignalMessaging/profiles/OWSProfileManager.m +++ b/SignalMessaging/profiles/OWSProfileManager.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSProfileManager.h" @@ -124,7 +124,7 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification + name:OWSApplicationDidBecomeActiveNotification object:nil]; } @@ -1128,8 +1128,8 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640; profileAvatarsDirPath = OWSProfileManager.sharedDataProfileAvatarsDirPath; [OWSFileSystem ensureDirectoryExists:profileAvatarsDirPath]; - - [OWSFileSystem protectFolderAtPath:profileAvatarsDirPath]; + + [OWSFileSystem protectFileOrFolderAtPath:profileAvatarsDirPath]; }); return profileAvatarsDirPath; } diff --git a/SignalMessaging/profiles/OWSUserProfile.m b/SignalMessaging/profiles/OWSUserProfile.m index 2e4294bad..10aff04ea 100644 --- a/SignalMessaging/profiles/OWSUserProfile.m +++ b/SignalMessaging/profiles/OWSUserProfile.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSUserProfile.h" @@ -112,7 +112,7 @@ NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId"; __block BOOL didChange = YES; [dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { NSString *collection = [[self class] collection]; - OWSUserProfile *latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection]; + OWSUserProfile *_Nullable latestInstance = [transaction objectForKey:self.uniqueId inCollection:collection]; if (latestInstance) { changeBlock(latestInstance); diff --git a/SignalMessaging/utils/DebugLogger.m b/SignalMessaging/utils/DebugLogger.m index 5e2fb16ad..cb38f4f8f 100644 --- a/SignalMessaging/utils/DebugLogger.m +++ b/SignalMessaging/utils/DebugLogger.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "DebugLogger.h" @@ -35,7 +35,7 @@ { NSString *dirPath = [[OWSFileSystem cachesDirectoryPath] stringByAppendingPathComponent:@"Logs"]; [OWSFileSystem ensureDirectoryExists:dirPath]; - [OWSFileSystem protectFolderAtPath:dirPath]; + [OWSFileSystem protectFileOrFolderAtPath:dirPath]; return dirPath; } @@ -44,7 +44,7 @@ NSString *dirPath = [[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"ShareExtensionLogs"]; [OWSFileSystem ensureDirectoryExists:dirPath]; - [OWSFileSystem protectFolderAtPath:dirPath]; + [OWSFileSystem protectFileOrFolderAtPath:dirPath]; return dirPath; } diff --git a/SignalMessaging/utils/DeviceSleepManager.swift b/SignalMessaging/utils/DeviceSleepManager.swift index 1cb886c18..4a7da90e6 100644 --- a/SignalMessaging/utils/DeviceSleepManager.swift +++ b/SignalMessaging/utils/DeviceSleepManager.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -42,7 +42,7 @@ public class DeviceSleepManager: NSObject { NotificationCenter.default.addObserver(self, selector:#selector(didEnterBackground), - name:NSNotification.Name.UIApplicationDidEnterBackground, + name:NSNotification.Name.OWSApplicationDidEnterBackground, object:nil) } diff --git a/SignalMessaging/utils/OWSPreferences.m b/SignalMessaging/utils/OWSPreferences.m index 8a2cc0a29..815a1e4ac 100644 --- a/SignalMessaging/utils/OWSPreferences.m +++ b/SignalMessaging/utils/OWSPreferences.m @@ -1,8 +1,9 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSPreferences.h" +#import #import #import #import @@ -24,7 +25,7 @@ NSString *const OWSPreferencesKeyCallKitPrivacyEnabled = @"CallKitPrivacyEnabled NSString *const OWSPreferencesKeyCallsHideIPAddress = @"CallsHideIPAddress"; NSString *const OWSPreferencesKeyHasDeclinedNoContactsView = @"hasDeclinedNoContactsView"; NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion"; -NSString *const OWSPreferencesKey_IsReadyForAppExtensions = @"isReadyForAppExtensions2"; +NSString *const OWSPreferencesKey_IsReadyForAppExtensions = @"isReadyForAppExtensions_5"; NSString *const OWSPreferencesKey_IsRegistered = @"OWSPreferencesKey_IsRegistered"; @implementation OWSPreferences @@ -78,6 +79,8 @@ NSString *const OWSPreferencesKey_IsRegistered = @"OWSPreferencesKey_IsRegistere + (void)setIsReadyForAppExtensions { + OWSAssert(CurrentAppContext().isMainApp); + [NSUserDefaults.appUserDefaults setObject:@(YES) forKey:OWSPreferencesKey_IsReadyForAppExtensions]; [NSUserDefaults.appUserDefaults synchronize]; } @@ -95,6 +98,8 @@ NSString *const OWSPreferencesKey_IsRegistered = @"OWSPreferencesKey_IsRegistere + (void)setIsRegistered:(BOOL)value { + OWSAssert(CurrentAppContext().isMainApp); + [NSUserDefaults.appUserDefaults setObject:@(value) forKey:OWSPreferencesKey_IsRegistered]; [NSUserDefaults.appUserDefaults synchronize]; } @@ -143,6 +148,8 @@ NSString *const OWSPreferencesKey_IsRegistered = @"OWSPreferencesKey_IsRegistere + (void)setIsLoggingEnabled:(BOOL)flag { + OWSAssert(CurrentAppContext().isMainApp); + // Logging preferences are stored in UserDefaults instead of the database, so that we can (optionally) start // logging before the database is initialized. This is important because sometimes there are problems *with* the // database initialization, and without logging it would be hard to track down. diff --git a/SignalServiceKit/src/Account/TSPreKeyManager.m b/SignalServiceKit/src/Account/TSPreKeyManager.m index 50618e153..9078842f3 100644 --- a/SignalServiceKit/src/Account/TSPreKeyManager.m +++ b/SignalServiceKit/src/Account/TSPreKeyManager.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "TSPreKeyManager.h" @@ -91,9 +91,10 @@ static const NSTimeInterval kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * + (void)checkPreKeysIfNecessary { - if (CurrentAppContext().isMainApp) { - OWSAssert(CurrentAppContext().isMainAppAndActive); + if (!CurrentAppContext().isMainApp) { + return; } + OWSAssert(CurrentAppContext().isMainAppAndActive); // Update the prekey check timestamp. dispatch_async(TSPreKeyManager.prekeyQueue, ^{ @@ -214,6 +215,10 @@ static const NSTimeInterval kSignedPreKeyUpdateFailureMaxFailureDuration = 10 * + (void)checkPreKeys { + if (!CurrentAppContext().isMainApp) { + return; + } + // Optimistically mark the prekeys as checked. This // de-bounces prekey checks. // diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.m b/SignalServiceKit/src/Messages/OWSBlockingManager.m index bffb9a12e..55f757de4 100644 --- a/SignalServiceKit/src/Messages/OWSBlockingManager.m +++ b/SignalServiceKit/src/Messages/OWSBlockingManager.m @@ -1,8 +1,9 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSBlockingManager.h" +#import "AppContext.h" #import "NSNotificationCenter+OWS.h" #import "OWSBlockedPhoneNumbersMessage.h" #import "OWSMessageSender.h" @@ -86,7 +87,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification + name:OWSApplicationDidBecomeActiveNotification object:nil]; } diff --git a/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m b/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m index 8b8d15334..aa5a0e7ce 100644 --- a/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m +++ b/SignalServiceKit/src/Messages/OWSDisappearingMessagesJob.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSDisappearingMessagesJob.h" @@ -57,11 +57,11 @@ NS_ASSUME_NONNULL_BEGIN [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) - name:UIApplicationDidBecomeActiveNotification + name:OWSApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) - name:UIApplicationWillResignActiveNotification + name:OWSApplicationWillResignActiveNotification object:nil]; return self; diff --git a/SignalServiceKit/src/Messages/OWSFailedAttachmentDownloadsJob.m b/SignalServiceKit/src/Messages/OWSFailedAttachmentDownloadsJob.m index 3021d30b9..56ccb8fa0 100644 --- a/SignalServiceKit/src/Messages/OWSFailedAttachmentDownloadsJob.m +++ b/SignalServiceKit/src/Messages/OWSFailedAttachmentDownloadsJob.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSFailedAttachmentDownloadsJob.h" @@ -82,7 +82,6 @@ static NSString *const OWSFailedAttachmentDownloadsJobAttachmentStateIndex = @"i [self enumerateAttemptingOutAttachmentsWithBlock:^(TSAttachmentPointer *attachment) { // sanity check if (attachment.state != TSAttachmentPointerStateFailed) { - DDLogDebug(@"%@ marking attachment as failed", self.logTag); attachment.state = TSAttachmentPointerStateFailed; [attachment saveWithTransaction:transaction]; count++; diff --git a/SignalServiceKit/src/TSPrefix.h b/SignalServiceKit/src/TSPrefix.h index 85837ee0c..b6229c025 100644 --- a/SignalServiceKit/src/TSPrefix.h +++ b/SignalServiceKit/src/TSPrefix.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import @@ -11,11 +11,10 @@ static const NSUInteger ddLogLevel = DDLogLevelAll; #else static const NSUInteger ddLogLevel = DDLogLevelInfo; #endif - -#import "Asserts.h" #import "Constraints.h" #import "NSObject+OWS.h" #import "OWSAnalytics.h" +#import "OWSAsserts.h" #import "OWSDispatch.h" #import "iOSVersions.h"