Merge branch 'dev' into light-mode

This commit is contained in:
Niels Andriesse 2020-02-22 10:46:21 +07:00
commit a85875e4df
18 changed files with 154 additions and 83 deletions

2
Pods

@ -1 +1 @@
Subproject commit 67dbced37481e0011a3df1397ed57711384a4957
Subproject commit 2870e676deec6a7ddb931edb6f0284f1f5b36085

View File

@ -11,6 +11,8 @@ extern NSString *const AppDelegateStoryboardMain;
- (void)startLongPollerIfNeeded;
- (void)stopLongPollerIfNeeded;
- (void)setUpDefaultPublicChatsIfNeeded;
- (void)startOpenGroupPollersIfNeeded;
- (void)stopOpenGroupPollersIfNeeded;
- (void)createRSSFeedsIfNeeded;
- (void)startRSSFeedPollersIfNeeded;

View File

@ -177,7 +177,9 @@ static NSTimeInterval launchStartedAt;
[DDLog flushLog];
// Loki: Stop pollers
[self stopLongPollerIfNeeded];
[self stopOpenGroupPollersIfNeeded];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
@ -195,8 +197,10 @@ static NSTimeInterval launchStartedAt;
OWSLogInfo(@"applicationWillTerminate.");
[DDLog flushLog];
// Loki: Stop pollers
[self stopLongPollerIfNeeded];
[self stopOpenGroupPollersIfNeeded];
if (self.lokiP2PServer) { [self.lokiP2PServer stop]; }
}
@ -316,9 +320,6 @@ static NSTimeInterval launchStartedAt;
name:NSNotificationName_2FAStateDidChange
object:nil];
// Loki - Observe new messages received notifications
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleNewMessagesReceived:) name:NSNotification.newMessagesReceived object:nil];
// Loki - Observe thread deleted notifications
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(handleThreadDeleted:) name:NSNotification.threadDeleted object:nil];
@ -770,14 +771,32 @@ static NSTimeInterval launchStartedAt;
[self.socketManager requestSocketOpen];
[Environment.shared.contactsManager fetchSystemContactsOnceIfAlreadyAuthorized];
NSString *userHexEncodedPublicKey = self.tsAccountManager.localNumber;
// Loki: Tell our friends that we are online
[LKP2PAPI broadcastOnlineStatus];
// Loki: Start long polling
// Loki: Start pollers
[self startLongPollerIfNeeded];
[self startOpenGroupPollersIfNeeded];
// Loki: Get device links
[LKFileServerAPI getDeviceLinksAssociatedWith:self.tsAccountManager.localNumber];
[[LKFileServerAPI getDeviceLinksAssociatedWith:userHexEncodedPublicKey] retainUntilComplete];
// Loki: Update profile picture if needed
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
NSDate *now = [NSDate new];
NSDate *lastProfilePictureUpload = (NSDate *)[userDefaults objectForKey:@"lastProfilePictureUpload"];
if (lastProfilePictureUpload != nil && [now timeIntervalSinceDate:lastProfilePictureUpload] > 14 * 24 * 60 * 60) {
OWSProfileManager *profileManager = OWSProfileManager.sharedManager;
NSString *displayName = [profileManager profileNameForRecipientId:userHexEncodedPublicKey];
UIImage *profilePicture = [profileManager profileAvatarForRecipientId:userHexEncodedPublicKey];
[profileManager updateLocalProfileName:displayName avatarImage:profilePicture success:^{
// Do nothing; the user defaults flag is updated in LokiFileServerAPI
} failure:^(NSError *error) {
// Do nothing
} requiresSync:YES];
}
if (![UIApplication sharedApplication].isRegisteredForRemoteNotifications) {
OWSLogInfo(@"Retrying to register for remote notifications since user hasn't registered yet.");
@ -1118,6 +1137,8 @@ static NSTimeInterval launchStartedAt;
OWSLogInfo(@"Ignoring remote notification; app not ready.");
return;
}
CurrentAppContext().wasWokenUpBySilentPushNotification = true;
[LKLogger print:@"[Loki] Silent push notification received; fetching messages."];
@ -1135,7 +1156,7 @@ static NSTimeInterval launchStartedAt;
[OWSPrimaryStorage.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
publicChats = [LKDatabaseUtilities getAllPublicChats:transaction];
}];
for (LKPublicChat *publicChat in publicChats) {
for (LKPublicChat *publicChat in publicChats.allValues) {
if (![publicChat isKindOfClass:LKPublicChat.class]) { continue; } // For some reason publicChat is sometimes a base 64 encoded string...
LKPublicChatPoller *poller = [[LKPublicChatPoller alloc] initForPublicChat:publicChat];
[poller stop];
@ -1146,8 +1167,12 @@ static NSTimeInterval launchStartedAt;
PMKJoin(promises).then(^(id results) {
completionHandler(UIBackgroundFetchResultNewData);
CurrentAppContext().wasWokenUpBySilentPushNotification = false;
[LKLogger print:@"[Loki] UIBackgroundFetchResultNewData"];
}).catch(^(id error) {
completionHandler(UIBackgroundFetchResultFailed);
CurrentAppContext().wasWokenUpBySilentPushNotification = false;
[LKLogger print:@"[Loki] UIBackgroundFetchResultFailed"];
});
}
@ -1444,11 +1469,12 @@ static NSTimeInterval launchStartedAt;
// Loki: Start friend request expiration job
[self.lokiFriendRequestExpirationJob startIfNecessary];
// Loki: Start long polling
// Loki: Start pollers
[self startLongPollerIfNeeded];
[self startOpenGroupPollersIfNeeded];
// Loki: Get device links
[LKFileServerAPI getDeviceLinksAssociatedWith:self.tsAccountManager.localNumber];
[[LKFileServerAPI getDeviceLinksAssociatedWith:self.tsAccountManager.localNumber] retainUntilComplete]; // TODO: Is this even needed?
}
}
@ -1586,16 +1612,6 @@ static NSTimeInterval launchStartedAt;
[self.lokiLongPoller stopIfNeeded];
}
- (LKRSSFeed *)lokiNewsFeed
{
return [[LKRSSFeed alloc] initWithId:@"loki.network.feed" server:@"https://loki.network/feed/" displayName:@"Loki News" isDeletable:true];
}
- (LKRSSFeed *)lokiMessengerUpdatesFeed
{
return [[LKRSSFeed alloc] initWithId:@"loki.network.messenger-updates.feed" server:@"https://loki.network/category/messenger-updates/feed/" displayName:@"Session Updates" isDeletable:false];
}
- (void)setUpDefaultPublicChatsIfNeeded
{
for (LKPublicChat *chat in LKPublicChatAPI.defaultChats) {
@ -1612,6 +1628,27 @@ static NSTimeInterval launchStartedAt;
}
}
- (void)startOpenGroupPollersIfNeeded
{
[LKPublicChatManager.shared startPollersIfNeeded];
[SSKEnvironment.shared.attachmentDownloads continueDownloadIfPossible];
}
- (void)stopOpenGroupPollersIfNeeded
{
[LKPublicChatManager.shared stopPollers];
}
- (LKRSSFeed *)lokiNewsFeed
{
return [[LKRSSFeed alloc] initWithId:@"loki.network.feed" server:@"https://loki.network/feed/" displayName:@"Loki News" isDeletable:true];
}
- (LKRSSFeed *)lokiMessengerUpdatesFeed
{
return [[LKRSSFeed alloc] initWithId:@"loki.network.messenger-updates.feed" server:@"https://loki.network/category/messenger-updates/feed/" displayName:@"Session Updates" isDeletable:false];
}
- (void)createRSSFeedsIfNeeded
{
NSArray *feeds = @[ /*self.lokiNewsFeed,*/ self.lokiMessengerUpdatesFeed ];
@ -1670,6 +1707,7 @@ static NSTimeInterval launchStartedAt;
[SSKEnvironment.shared.identityManager clearIdentityKey];
[LKAPI clearRandomSnodePool];
[self stopLongPollerIfNeeded];
[self stopOpenGroupPollersIfNeeded];
[self.lokiNewsFeedPoller stop];
[self.lokiMessengerUpdatesFeedPoller stop];
[LKPublicChatManager.shared stopPollers];

View File

@ -7,8 +7,8 @@ final class ConversationTitleView : UIView {
// MARK: Types
private enum Status : Int {
case calculatingPoW = 1
case contactingNetwork = 2
case sendingMessage = 3
case routing = 2
case messageSending = 3
case messageSent = 4
case messageFailed = 5
}
@ -40,8 +40,8 @@ final class ConversationTitleView : UIView {
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(handleProfileChangedNotification(_:)), name: NSNotification.Name(rawValue: kNSNotificationName_OtherUsersProfileDidChange), object: nil)
notificationCenter.addObserver(self, selector: #selector(handleCalculatingPoWNotification(_:)), name: .calculatingPoW, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleContactingNetworkNotification(_:)), name: .contactingNetwork, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleSendingMessageNotification(_:)), name: .sendingMessage, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleRoutingNotification(_:)), name: .routing, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleMessageSendingNotification(_:)), name: .messageSending, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleMessageSentNotification(_:)), name: .messageSent, object: nil)
notificationCenter.addObserver(self, selector: #selector(handleMessageFailedNotification(_:)), name: .messageFailed, object: nil)
}
@ -99,14 +99,14 @@ final class ConversationTitleView : UIView {
setStatusIfNeeded(to: .calculatingPoW, forMessageWithTimestamp: timestamp)
}
@objc private func handleContactingNetworkNotification(_ notification: Notification) {
@objc private func handleRoutingNotification(_ notification: Notification) {
guard let timestamp = notification.object as? NSNumber else { return }
setStatusIfNeeded(to: .contactingNetwork, forMessageWithTimestamp: timestamp)
setStatusIfNeeded(to: .routing, forMessageWithTimestamp: timestamp)
}
@objc private func handleSendingMessageNotification(_ notification: Notification) {
@objc private func handleMessageSendingNotification(_ notification: Notification) {
guard let timestamp = notification.object as? NSNumber else { return }
setStatusIfNeeded(to: .sendingMessage, forMessageWithTimestamp: timestamp)
setStatusIfNeeded(to: .messageSending, forMessageWithTimestamp: timestamp)
}
@objc private func handleMessageSentNotification(_ notification: Notification) {
@ -147,8 +147,8 @@ final class ConversationTitleView : UIView {
self.subtitleLabel.isHidden = false
switch self.currentStatus {
case .calculatingPoW: self.subtitleLabel.text = NSLocalizedString("Encrypting message", comment: "")
case .contactingNetwork: self.subtitleLabel.text = NSLocalizedString("Tracing a path", comment: "")
case .sendingMessage: self.subtitleLabel.text = NSLocalizedString("Sending message", comment: "")
case .routing: self.subtitleLabel.text = NSLocalizedString("Tracing a path", comment: "")
case .messageSending: self.subtitleLabel.text = NSLocalizedString("Sending message", comment: "")
case .messageSent: self.subtitleLabel.text = NSLocalizedString("Message sent securely", comment: "")
case .messageFailed: self.subtitleLabel.text = NSLocalizedString("Message failed to send", comment: "")
case nil:

View File

@ -22,7 +22,11 @@ final class LokiPushNotificationManager : NSObject {
}
// Send token to Loki server
let parameters = [ "token" : hexEncodedToken ]
#if DEBUG
let url = URL(string: "https://dev.apns.getsession.org/register")!
#else
let url = URL(string: "https://live.apns.getsession.org/register")!
#endif
let request = TSRequest(url: url, method: "POST", parameters: parameters)
request.allHTTPHeaderFields = [ "Content-Type" : "application/json" ]
TSNetworkManager.shared().makeRequest(request, success: { _, response in

View File

@ -134,8 +134,8 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
if OWSIdentityManager.shared().identityKeyPair() != nil {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.setUpDefaultPublicChatsIfNeeded()
appDelegate.startOpenGroupPollersIfNeeded()
appDelegate.createRSSFeedsIfNeeded()
LokiPublicChatManager.shared.startPollersIfNeeded()
appDelegate.startRSSFeedPollersIfNeeded()
}
// Do initial update

View File

@ -429,12 +429,12 @@ typedef enum : NSUInteger {
name:NSNotification.calculatingPoW
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleContactingNetworkNotification:)
name:NSNotification.contactingNetwork
selector:@selector(handleRoutingNotification:)
name:NSNotification.routing
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleSendingMessageNotification:)
name:NSNotification.sendingMessage
selector:@selector(handleMessageSendingNotification:)
name:NSNotification.messageSending
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleMessageSentNotification:)
@ -5419,13 +5419,13 @@ typedef enum : NSUInteger {
[self setProgressIfNeededTo:0.25f forMessageWithTimestamp:timestamp];
}
- (void)handleContactingNetworkNotification:(NSNotification *)notification
- (void)handleRoutingNotification:(NSNotification *)notification
{
NSNumber *timestamp = (NSNumber *)notification.object;
[self setProgressIfNeededTo:0.50f forMessageWithTimestamp:timestamp];
}
- (void)handleSendingMessageNotification:(NSNotification *)notification
- (void)handleMessageSendingNotification:(NSNotification *)notification
{
NSNumber *timestamp = (NSNumber *)notification.object;
[self setProgressIfNeededTo:0.75f forMessageWithTimestamp:timestamp];

View File

@ -682,6 +682,7 @@ typedef NS_ENUM(NSInteger, HomeViewControllerSection) {
[LKAPI clearRandomSnodePool];
AppDelegate *appDelegate = (AppDelegate *)UIApplication.sharedApplication.delegate;
[appDelegate stopLongPollerIfNeeded];
[appDelegate stopOpenGroupPollersIfNeeded];
[SSKEnvironment.shared.tsAccountManager resetForReregistration];
UIViewController *rootViewController = [[OnboardingController new] initialViewController];
OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:rootViewController];

View File

@ -28,6 +28,7 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
@synthesize mainWindow = _mainWindow;
@synthesize appLaunchTime = _appLaunchTime;
@synthesize wasWokenUpBySilentPushNotification = _wasWokenUpBySilentPushNotification;
- (instancetype)init
{
@ -40,6 +41,7 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
self.reportedApplicationState = UIApplicationStateInactive;
_appLaunchTime = [NSDate new];
_wasWokenUpBySilentPushNotification = false;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)

View File

@ -416,10 +416,10 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
NSData *encryptedAvatarData = [self encryptProfileData:avatarData profileKey:newProfileKey];
OWSAssertDebug(encryptedAvatarData.length > 0);
[[LKFileServerAPI setProfilePicture:encryptedAvatarData]
.thenOn(dispatch_get_main_queue(), ^(NSString *url) {
[[LKFileServerAPI uploadProfilePicture:encryptedAvatarData]
.thenOn(dispatch_get_main_queue(), ^(NSString *downloadURL) {
[self.localUserProfile updateWithProfileKey:newProfileKey dbConnection:self.dbConnection completion:^{
successBlock(url);
successBlock(downloadURL);
}];
})
.catchOn(dispatch_get_main_queue(), ^(id result) {

View File

@ -1,7 +1,8 @@
import PromiseKit
public extension LokiAPI {
/// Only ever accessed from `LokiAPI.errorHandlingQueue` to avoid race conditions.
fileprivate static var failureCount: [LokiAPITarget:UInt] = [:]
// MARK: Settings

View File

@ -187,10 +187,10 @@ public final class LokiAPI : NSObject {
func sendLokiMessageUsingSwarmAPI() -> Promise<Set<RawResponsePromise>> {
notificationCenter.post(name: .calculatingPoW, object: NSNumber(value: signalMessage.timestamp))
return lokiMessage.calculatePoW().then { lokiMessageWithPoW -> Promise<Set<RawResponsePromise>> in
notificationCenter.post(name: .contactingNetwork, object: NSNumber(value: signalMessage.timestamp))
notificationCenter.post(name: .routing, object: NSNumber(value: signalMessage.timestamp))
return getTargetSnodes(for: destination).map { swarm in
return Set(swarm.map { target in
notificationCenter.post(name: .sendingMessage, object: NSNumber(value: signalMessage.timestamp))
notificationCenter.post(name: .messageSending, object: NSNumber(value: signalMessage.timestamp))
return sendLokiMessage(lokiMessageWithPoW, to: target).map { rawResponse in
if let json = rawResponse as? JSON, let powDifficulty = json["difficulty"] as? Int {
guard powDifficulty != LokiAPI.powDifficulty else { return rawResponse }

View File

@ -137,40 +137,33 @@ public final class LokiFileServerAPI : LokiDotNetAPI {
}
// MARK: Profile Pictures (Public API)
public static func setProfilePicture(_ profilePicture: Data) -> Promise<String> {
return Promise<String>() { seal in
guard profilePicture.count < maxFileSize else { return seal.reject(LokiDotNetAPIError.maxFileSizeExceeded) }
getAuthToken(for: server).done { token in
let url = "\(server)/users/me/avatar"
let parameters: JSON = [ "type" : attachmentType, "Content-Type" : "application/binary" ]
var error: NSError?
var request = AFHTTPRequestSerializer().multipartFormRequest(withMethod: "POST", urlString: url, parameters: parameters, constructingBodyWith: { formData in
formData.appendPart(withFileData: profilePicture, name: "avatar", fileName: UUID().uuidString, mimeType: "application/binary")
}, error: &error)
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
if let error = error {
print("[Loki] Couldn't upload profile picture due to error: \(error).")
throw error
}
let _ = LokiFileServerProxy(for: server).performLokiFileServerNSURLRequest(request as NSURLRequest).done { responseObject in
guard let json = responseObject as? JSON, let data = json["data"] as? JSON, let profilePicture = data["avatar_image"] as? JSON, let downloadURL = profilePicture["url"] as? String else {
print("[Loki] Couldn't parse profile picture from: \(responseObject).")
return seal.reject(LokiDotNetAPIError.parsingFailed)
}
return seal.fulfill(downloadURL)
}.catch { error in
seal.reject(error)
}
}.catch { error in
print("[Loki] Couldn't upload profile picture due to error: \(error).")
seal.reject(error)
public static func uploadProfilePicture(_ profilePicture: Data) -> Promise<String> {
guard profilePicture.count < maxFileSize else { return Promise(error: LokiDotNetAPIError.maxFileSizeExceeded) }
let url = "\(server)/files"
let parameters: JSON = [ "type" : attachmentType, "Content-Type" : "application/binary" ]
var error: NSError?
var request = AFHTTPRequestSerializer().multipartFormRequest(withMethod: "POST", urlString: url, parameters: parameters, constructingBodyWith: { formData in
formData.appendPart(withFileData: profilePicture, name: "content", fileName: UUID().uuidString, mimeType: "application/binary")
}, error: &error)
// Uploads to the Loki File Server shouldn't include any personally identifiable information so use a dummy auth token
request.addValue("Bearer loki", forHTTPHeaderField: "Authorization")
if let error = error {
print("[Loki] Couldn't upload profile picture due to error: \(error).")
return Promise(error: error)
}
return LokiFileServerProxy(for: server).performLokiFileServerNSURLRequest(request as NSURLRequest).map { responseObject in
guard let json = responseObject as? JSON, let data = json["data"] as? JSON, let downloadURL = data["url"] as? String else {
print("[Loki] Couldn't parse profile picture from: \(responseObject).")
throw LokiDotNetAPIError.parsingFailed
}
UserDefaults.standard[.lastProfilePictureUpload] = Date()
return downloadURL
}
}
// MARK: Profile Pictures (Public Obj-C API)
@objc(setProfilePicture:)
public static func objc_setProfilePicture(_ profilePicture: Data) -> AnyPromise {
return AnyPromise.from(setProfilePicture(profilePicture))
@objc(uploadProfilePicture:)
public static func objc_uploadProfilePicture(_ profilePicture: Data) -> AnyPromise {
return AnyPromise.from(uploadProfilePicture(profilePicture))
}
}

View File

@ -9,7 +9,11 @@ public enum LKUserDefaults {
/// Whether the device was unlinked as a slave device (used to notify the user on the landing screen).
case wasUnlinked
}
public enum Date : Swift.String {
case lastProfilePictureUpload
}
public enum Double : Swift.String {
case lastDeviceTokenUpload = "lastDeviceTokenUploadTime"
}
@ -36,6 +40,11 @@ public extension UserDefaults {
get { return self.bool(forKey: bool.rawValue) }
set { set(newValue, forKey: bool.rawValue) }
}
public subscript(date: LKUserDefaults.Date) -> Date? {
get { return self.object(forKey: date.rawValue) as? Date }
set { set(newValue, forKey: date.rawValue) }
}
public subscript(double: LKUserDefaults.Double) -> Double {
get { return self.double(forKey: double.rawValue) }

View File

@ -1,36 +1,40 @@
public extension Notification.Name {
// State changes
public static let contactOnlineStatusChanged = Notification.Name("contactOnlineStatusChanged")
public static let newMessagesReceived = Notification.Name("newMessagesReceived")
public static let threadFriendRequestStatusChanged = Notification.Name("threadFriendRequestStatusChanged")
public static let messageFriendRequestStatusChanged = Notification.Name("messageFriendRequestStatusChanged")
public static let threadDeleted = Notification.Name("threadDeleted")
public static let dataNukeRequested = Notification.Name("dataNukeRequested")
public static let threadSessionRestoreDevicesChanged = Notification.Name("threadSessionRestoreDevicesChanged")
// Message statuses
// Message status changes
public static let calculatingPoW = Notification.Name("calculatingPoW")
public static let contactingNetwork = Notification.Name("contactingNetwork")
public static let sendingMessage = Notification.Name("sendingMessage")
public static let routing = Notification.Name("routing")
public static let messageSending = Notification.Name("messageSending")
public static let messageSent = Notification.Name("messageSent")
public static let messageFailed = Notification.Name("messageFailed")
// Onboarding
public static let seedViewed = Notification.Name("seedViewed")
// Interaction
public static let dataNukeRequested = Notification.Name("dataNukeRequested")
}
@objc public extension NSNotification {
// State changes
@objc public static let contactOnlineStatusChanged = Notification.Name.contactOnlineStatusChanged.rawValue as NSString
@objc public static let newMessagesReceived = Notification.Name.newMessagesReceived.rawValue as NSString
@objc public static let threadFriendRequestStatusChanged = Notification.Name.threadFriendRequestStatusChanged.rawValue as NSString
@objc public static let messageFriendRequestStatusChanged = Notification.Name.messageFriendRequestStatusChanged.rawValue as NSString
@objc public static let threadDeleted = Notification.Name.threadDeleted.rawValue as NSString
@objc public static let dataNukeRequested = Notification.Name.dataNukeRequested.rawValue as NSString
@objc public static let threadSessionRestoreDevicesChanged = Notification.Name.threadSessionRestoreDevicesChanged.rawValue as NSString
// Message statuses
@objc public static let calculatingPoW = Notification.Name.calculatingPoW.rawValue as NSString
@objc public static let contactingNetwork = Notification.Name.contactingNetwork.rawValue as NSString
@objc public static let sendingMessage = Notification.Name.sendingMessage.rawValue as NSString
@objc public static let routing = Notification.Name.routing.rawValue as NSString
@objc public static let messageSending = Notification.Name.messageSending.rawValue as NSString
@objc public static let messageSent = Notification.Name.messageSent.rawValue as NSString
@objc public static let messageFailed = Notification.Name.messageFailed.rawValue as NSString
// Onboarding
@objc public static let seedViewed = Notification.Name.seedViewed.rawValue as NSString
// Interaction
@objc public static let dataNukeRequested = Notification.Name.dataNukeRequested.rawValue as NSString
}

View File

@ -43,6 +43,8 @@ extern NSString *const kAttachmentDownloadAttachmentIDKey;
success:(void (^)(NSArray<TSAttachmentStream *> *attachmentStreams))success
failure:(void (^)(NSError *error))failure;
- (void)continueDownloadIfPossible;
@end
NS_ASSUME_NONNULL_END

View File

@ -264,6 +264,8 @@ typedef void (^AttachmentDownloadFailure)(NSError *error);
- (void)startDownloadIfPossible
{
if (CurrentAppContext().wasWokenUpBySilentPushNotification) { return; }
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OWSAttachmentDownloadJob *_Nullable job;
@ -342,6 +344,16 @@ typedef void (^AttachmentDownloadFailure)(NSError *error);
#pragma mark -
- (void)continueDownloadIfPossible
{
if (self.attachmentDownloadJobQueue.count > 0) {
[LKLogger print:@"[Loki] Continuing unfinished attachment download tasks."];
[self startDownloadIfPossible];
}
}
#pragma mark -
- (void)retrieveAttachmentForJob:(OWSAttachmentDownloadJob *)job
success:(void (^)(TSAttachmentStream *attachmentStream))successHandler
failure:(void (^)(NSError *error))failureHandler

View File

@ -37,6 +37,9 @@ NSString *NSStringForUIApplicationState(UIApplicationState value);
@property (nonatomic, readonly) BOOL isMainApp;
@property (nonatomic, readonly) BOOL isMainAppAndActive;
/// Whether the app was woken up by a silent push notification. This is important for
/// determining whether attachments should be downloaded or not.
@property (nonatomic) BOOL wasWokenUpBySilentPushNotification;
// Whether the user is using a right-to-left language like Arabic.
@property (nonatomic, readonly) BOOL isRTL;