Merge branch 'dev' into light-mode
This commit is contained in:
commit
a85875e4df
2
Pods
2
Pods
|
@ -1 +1 @@
|
|||
Subproject commit 67dbced37481e0011a3df1397ed57711384a4957
|
||||
Subproject commit 2870e676deec6a7ddb931edb6f0284f1f5b36085
|
|
@ -11,6 +11,8 @@ extern NSString *const AppDelegateStoryboardMain;
|
|||
- (void)startLongPollerIfNeeded;
|
||||
- (void)stopLongPollerIfNeeded;
|
||||
- (void)setUpDefaultPublicChatsIfNeeded;
|
||||
- (void)startOpenGroupPollersIfNeeded;
|
||||
- (void)stopOpenGroupPollersIfNeeded;
|
||||
- (void)createRSSFeedsIfNeeded;
|
||||
- (void)startRSSFeedPollersIfNeeded;
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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:)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue