mattermost-mobile/ios/UploadAttachments/UploadAttachments/UploadSession.swift
Miguel Alatzar 06dc849c97
iOS - Fetch and store data on push notification receipt (#5645)
* Gekidou package and postNotificationReceipt

* Add back UploadAttachments functions

* ios - Fetch and store Posts

* ios - handle PostsInChannel

* Use queue and group for fetchAndStoreDataForPushNotification

* Handle channel and channel membership

* Handle post props

* Handle reactions

* Handle files

* Handle emojis

* Handle images

* Use notification data

* Credential fixes

* Lint fixes

* Fixes

* Call content handler after requests and db writes

* Handle posts in thread

* Remove comment
2021-08-31 15:43:57 -07:00

138 lines
6.4 KiB
Swift

import UIKit
import os.log
@objc @objcMembers public class UploadSession: NSObject, URLSessionDataDelegate {
public class var shared :UploadSession {
struct Singleton {
static let instance = UploadSession()
}
return Singleton.instance
}
var completionHandler: (() -> Void)?
public var session: URLSession?
public func createPost(identifier: String) {
guard let uploadSessionData = UploadSessionManager.shared.getUploadSessionData(identifier: identifier) else {
return
}
let store = StoreManager.shared() as StoreManager
let _ = store.getEntities(true)
if let serverUrl = uploadSessionData.serverUrl, let sessionToken = store.getToken() {
let urlString = "\(serverUrl)/api/v4/posts"
guard let url = URL(string: urlString) else {
return
}
if uploadSessionData.message != "" || uploadSessionData.fileIds.count > 0 {
let jsonObject: [String: Any] = [
"channel_id": uploadSessionData.channelId as Any,
"message": uploadSessionData.message as Any,
"file_ids": uploadSessionData.fileIds
]
if !JSONSerialization.isValidJSONObject(jsonObject) {
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(sessionToken)", forHTTPHeaderField: "Authorization")
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost will post identifier=%{public}@", identifier)
}
URLSession(configuration: .ephemeral).dataTask(with: request).resume()
UploadSessionManager.shared.removeUploadSessionData(identifier: identifier)
UploadSessionManager.shared.clearTempDirectory()
}
}
}
public func attachSession(identifier: String, completionHandler: @escaping () -> Void) {
self.completionHandler = completionHandler
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost Attached session with completionHandler identifier=%{public}@", identifier)
}
let sessionConfig = URLSessionConfiguration.background(withIdentifier: identifier)
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
sessionConfig.sharedContainerIdentifier = appGroupId
if #available(iOS 11.0, *) {
sessionConfig.waitsForConnectivity = true
}
session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
}
public func createURLSession(identifier: String) -> URLSession {
let sessionConfig = URLSessionConfiguration.background(withIdentifier: identifier)
let appGroupId = Bundle.main.infoDictionary!["AppGroupIdentifier"] as! String
sessionConfig.sharedContainerIdentifier = appGroupId
if #available(iOS 11.0, *) {
sessionConfig.waitsForConnectivity = true
}
self.session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost Session created identifier=%{public}@", identifier)
}
return self.session!
}
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
// here we should get the file Id and update it in the session
guard let identifier = session.configuration.identifier else {return}
do {
let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as! NSDictionary
if jsonObject.object(forKey: "file_infos") != nil {
let fileInfos = jsonObject.object(forKey: "file_infos") as! NSArray
if fileInfos.count > 0 {
let fileInfoData = fileInfos[0] as! NSDictionary
let fileId = fileInfoData.object(forKey: "id") as! String
UploadSessionManager.shared.appendCompletedUploadToSession(identifier: identifier, fileId: fileId)
}
}
} catch {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost Failed to receive data identifier=%{public}@ error=%{public}", identifier, error.localizedDescription)
}
print("MMLOG: Failed to get the file upload response %@", error.localizedDescription)
}
}
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if error == nil {
let identifier = session.configuration.identifier!
guard let sessionData = UploadSessionManager.shared.getUploadSessionData(identifier: identifier) else {return}
if sessionData.fileIds.count == sessionData.totalFiles {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost did complete upload identifier=%{public}@", identifier)
}
ProcessInfo().performExpiringActivity(withReason: "Need to post the message") { (expires) in
self.createPost(identifier: session.configuration.identifier!)
}
}
}
}
public func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost urlSessionDidFinishEvents identifier=%{public}@", session.configuration.identifier ?? "no identifier")
}
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(1.0*Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
if self.completionHandler != nil {
if #available(iOS 12.0, *) {
os_log(OSLogType.default, "Mattermost CALLED COMPLETIONHANDLER")
}
self.completionHandler!()
}
})
}
}