diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 8ebd3a890..3c80e5db9 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -689,6 +689,7 @@ C3AABDDF2553ECF00042FF4C /* Array+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D12553860800C340D1 /* Array+Description.swift */; }; C3AAFFE825AE975D0089E6DD /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */; }; C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFF125AE99710089E6DD /* AppDelegate.swift */; }; + C3ADC66126426688005F1414 /* ShareVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3ADC66026426688005F1414 /* ShareVC.swift */; }; C3BBE0762554CDA60050F1E3 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE0752554CDA60050F1E3 /* Configuration.swift */; }; C3BBE0802554CDD70050F1E3 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BBE07F2554CDD70050F1E3 /* Storage.swift */; }; C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A5D62553860B00C340D1 /* Promise+Retrying.swift */; }; @@ -1690,6 +1691,7 @@ C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManager.swift; sourceTree = ""; }; C3AAFFDE25AE96FF0089E6DD /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = ""; }; C3AAFFF125AE99710089E6DD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + C3ADC66026426688005F1414 /* ShareVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareVC.swift; sourceTree = ""; }; C3AECBEA24EF5244005743DE /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/Localizable.strings; sourceTree = ""; }; C3B7845C25649DA600ADB2E7 /* TSIncomingMessage+Conversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSIncomingMessage+Conversion.swift"; sourceTree = ""; }; C3BBE0752554CDA60050F1E3 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; @@ -1981,14 +1983,13 @@ isa = PBXGroup; children = ( C31C21A4255BCA4800EC2D66 /* Meta */, + C3ADC65F264265D9005F1414 /* Deprecated */, 4535186C1FC635DD00210559 /* MainInterface.storyboard */, - 347850561FD86544007B8332 /* SAEFailedViewController.swift */, - 3461284A1FD0B93F00532771 /* SAELoadViewController.swift */, 34641E1D2088DA6C00E2EDE5 /* SAEScreenLockViewController.h */, 34641E1E2088DA6D00E2EDE5 /* SAEScreenLockViewController.m */, - 4535186A1FC635DD00210559 /* ShareViewController.swift */, 34480B341FD0929200BC14EF /* ShareAppExtensionContext.h */, 34480B351FD0929200BC14EF /* ShareAppExtensionContext.m */, + C3ADC66026426688005F1414 /* ShareVC.swift */, ); path = SessionShareExtension; sourceTree = ""; @@ -3154,6 +3155,16 @@ path = "File Server"; sourceTree = ""; }; + C3ADC65F264265D9005F1414 /* Deprecated */ = { + isa = PBXGroup; + children = ( + 347850561FD86544007B8332 /* SAEFailedViewController.swift */, + 3461284A1FD0B93F00532771 /* SAELoadViewController.swift */, + 4535186A1FC635DD00210559 /* ShareViewController.swift */, + ); + path = Deprecated; + sourceTree = ""; + }; C3BBE0B32554F0D30050F1E3 /* Utilities */ = { isa = PBXGroup; children = ( @@ -4407,6 +4418,7 @@ files = ( 4535186B1FC635DD00210559 /* ShareViewController.swift in Sources */, 34480B361FD0929200BC14EF /* ShareAppExtensionContext.m in Sources */, + C3ADC66126426688005F1414 /* ShareVC.swift in Sources */, 34641E1F2088DA6D00E2EDE5 /* SAEScreenLockViewController.m in Sources */, 3461284B1FD0B94000532771 /* SAELoadViewController.swift in Sources */, 347850571FD86544007B8332 /* SAEFailedViewController.swift in Sources */, diff --git a/SessionShareExtension/Base.lproj/MainInterface.storyboard b/SessionShareExtension/Base.lproj/MainInterface.storyboard index 2e59abc17..5182a5f6f 100644 --- a/SessionShareExtension/Base.lproj/MainInterface.storyboard +++ b/SessionShareExtension/Base.lproj/MainInterface.storyboard @@ -1,28 +1,27 @@ - - - - + + - + - + - + - + + diff --git a/SessionShareExtension/SAEFailedViewController.swift b/SessionShareExtension/Deprecated/SAEFailedViewController.swift similarity index 98% rename from SessionShareExtension/SAEFailedViewController.swift rename to SessionShareExtension/Deprecated/SAEFailedViewController.swift index 27f5be14d..767a65d0c 100644 --- a/SessionShareExtension/SAEFailedViewController.swift +++ b/SessionShareExtension/Deprecated/SAEFailedViewController.swift @@ -10,7 +10,7 @@ protocol SAEFailedViewDelegate: class { func shareViewWasCancelled() } -class SAEFailedViewController: UIViewController { +class SAEFailedViewControllerOld: UIViewController { weak var delegate: SAEFailedViewDelegate? diff --git a/SessionShareExtension/SAELoadViewController.swift b/SessionShareExtension/Deprecated/SAELoadViewController.swift similarity index 98% rename from SessionShareExtension/SAELoadViewController.swift rename to SessionShareExtension/Deprecated/SAELoadViewController.swift index c86abbeb2..6102c9b7b 100644 --- a/SessionShareExtension/SAELoadViewController.swift +++ b/SessionShareExtension/Deprecated/SAELoadViewController.swift @@ -5,7 +5,7 @@ import UIKit import PureLayout -class SAELoadViewController: UIViewController { +class SAELoadViewControllerOld: UIViewController { weak var delegate: ShareViewDelegate? diff --git a/SessionShareExtension/ShareViewController.swift b/SessionShareExtension/Deprecated/ShareViewController.swift similarity index 98% rename from SessionShareExtension/ShareViewController.swift rename to SessionShareExtension/Deprecated/ShareViewController.swift index 5491e73dd..09d353f44 100644 --- a/SessionShareExtension/ShareViewController.swift +++ b/SessionShareExtension/Deprecated/ShareViewController.swift @@ -10,7 +10,7 @@ import SessionUIKit import CoreServices @objc -public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailedViewDelegate, AppModeManagerDelegate { +public class ShareViewControllerOld: UIViewController, ShareViewDelegate, SAEFailedViewDelegate, AppModeManagerDelegate { // MARK: - Dependencies @@ -32,7 +32,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed private var areVersionMigrationsComplete = false private var progressPoller: ProgressPoller? - var loadViewController: SAELoadViewController? + var loadViewController: SAELoadViewControllerOld? private var shareViewNavigationController: OWSNavigationController? @@ -96,7 +96,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed let shareViewNavigationController = OWSNavigationController() self.shareViewNavigationController = shareViewNavigationController - let loadViewController = SAELoadViewController(delegate: self) + let loadViewController = SAELoadViewControllerOld(delegate: self) self.loadViewController = loadViewController // Don't display load screen immediately, in hopes that we can avoid it altogether. @@ -393,7 +393,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed private func showErrorView(title: String, message: String) { AssertIsOnMainThread() - let viewController = SAEFailedViewController(delegate: self, title: title, message: message) + let viewController = SAEFailedViewControllerOld(delegate: self, title: title, message: message) self.showPrimaryViewController(viewController) } @@ -466,7 +466,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed // If no view has been presented yet, do nothing. return } - if let _ = firstViewController as? SAEFailedViewController { + if let _ = firstViewController as? SAEFailedViewControllerOld { // If root view is an error view, do nothing. return } @@ -708,7 +708,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed Logger.error("invalid inputItem \(inputItemRaw)") continue } - if let itemProviders = ShareViewController.preferredItemProviders(inputItem: inputItem) { + if let itemProviders = ShareViewControllerOld.preferredItemProviders(inputItem: inputItem) { return Promise.value(itemProviders) } } @@ -753,7 +753,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed // * UTIs aren't very descriptive (there are far more MIME types than UTI types) // so in the case of file attachments we try to refine the attachment type // using the file extension. - guard let srcUtiType = ShareViewController.utiType(itemProvider: itemProvider) else { + guard let srcUtiType = ShareViewControllerOld.utiType(itemProvider: itemProvider) else { let error = ShareViewControllerError.unsupportedMedia return Promise(error: error) } @@ -880,7 +880,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed Logger.debug("building DataSource with url: \(url), utiType: \(utiType)") - guard let dataSource = ShareViewController.createDataSource(utiType: utiType, url: url, customFileName: loadedItem.customFileName) else { + guard let dataSource = ShareViewControllerOld.createDataSource(utiType: utiType, url: url, customFileName: loadedItem.customFileName) else { let error = ShareViewControllerError.assertionError(description: "Unable to read attachment data") return Promise(error: error) } diff --git a/SessionShareExtension/SAEScreenLockViewController.m b/SessionShareExtension/SAEScreenLockViewController.m index 70d5e6696..06e8f553b 100644 --- a/SessionShareExtension/SAEScreenLockViewController.m +++ b/SessionShareExtension/SAEScreenLockViewController.m @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN UIView.appearance.tintColor = LKColors.text; - // Loki: Set gradient background + // Gradient background self.view.backgroundColor = UIColor.clearColor; CAGradientLayer *layer = [CAGradientLayer new]; layer.frame = UIScreen.mainScreen.bounds; @@ -52,20 +52,21 @@ NS_ASSUME_NONNULL_BEGIN layer.colors = @[ (id)gradientStartColor.CGColor, (id)gradientEndColor.CGColor ]; [self.view.layer insertSublayer:layer atIndex:0]; - // Loki: Set navigation bar background color + // Navigation bar background color UINavigationBar *navigationBar = self.navigationController.navigationBar; [navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; navigationBar.shadowImage = [UIImage new]; [navigationBar setTranslucent:NO]; navigationBar.barTintColor = LKColors.navigationBarBackground; - // Loki: Customize title + // Title UILabel *titleLabel = [UILabel new]; titleLabel.text = NSLocalizedString(@"Share to Session", @""); titleLabel.textColor = LKColors.text; titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize]; self.navigationItem.titleView = titleLabel; + // Close button UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"X"] style:UIBarButtonItemStylePlain target:self action:@selector(dismissPressed:)]; closeButton.tintColor = LKColors.text; self.navigationItem.leftBarButtonItem = closeButton; diff --git a/SessionShareExtension/ShareVC.swift b/SessionShareExtension/ShareVC.swift new file mode 100644 index 000000000..3454146be --- /dev/null +++ b/SessionShareExtension/ShareVC.swift @@ -0,0 +1,172 @@ +import SessionUIKit + +final class ShareVC : UIViewController, AppModeManagerDelegate { + private var areVersionMigrationsComplete = false + + // MARK: Lifecycle + override func loadView() { + super.loadView() + + // This should be the first thing we do. + let appContext = ShareAppExtensionContext(rootViewController: self) + SetCurrentAppContext(appContext) + + AppModeManager.configure(delegate: self) + + DebugLogger.shared().enableTTYLogging() + if _isDebugAssertConfiguration() { + DebugLogger.shared().enableFileLogging() + } else if OWSPreferences.isLoggingEnabled() { + DebugLogger.shared().enableFileLogging() + } + + Logger.info("") + + _ = AppVersion.sharedInstance() + + Cryptography.seedRandom() + + // We don't need to use DeviceSleepManager in the SAE. + + // We don't need to use applySignalAppearence in the SAE. + + if CurrentAppContext().isRunningTests { + // TODO: Do we need to implement isRunningTests in the SAE context? + return + } + + AppSetup.setupEnvironment(appSpecificSingletonBlock: { + SSKEnvironment.shared.notificationsManager = NoopNotificationsManager() + }, migrationCompletion: { [weak self] in + AssertIsOnMainThread() + + guard let strongSelf = self else { return } + + // performUpdateCheck must be invoked after Environment has been initialized because + // upgrade process may depend on Environment. + strongSelf.versionMigrationsDidComplete() + }) + + // We don't need to use "screen protection" in the SAE. + + NotificationCenter.default.addObserver(self, + selector: #selector(storageIsReady), + name: .StorageIsReady, + object: nil) + NotificationCenter.default.addObserver(self, + selector: #selector(applicationDidEnterBackground), + name: .OWSApplicationDidEnterBackground, + object: nil) + } + + @objc + func versionMigrationsDidComplete() { + AssertIsOnMainThread() + + Logger.debug("") + + areVersionMigrationsComplete = true + + checkIsAppReady() + } + + @objc + func storageIsReady() { + AssertIsOnMainThread() + + Logger.debug("") + + checkIsAppReady() + } + + @objc + func checkIsAppReady() { + AssertIsOnMainThread() + + // App isn't ready until storage is ready AND all version migrations are complete. + guard areVersionMigrationsComplete else { + return + } + guard OWSStorage.isStorageReady() else { + return + } + guard !AppReadiness.isAppReady() else { + // Only mark the app as ready once. + return + } + + SignalUtilitiesKit.Configuration.performMainSetup() + + Logger.debug("") + + // TODO: Once "app ready" logic is moved into AppSetup, move this line there. + OWSProfileManager.shared().ensureLocalProfileCached() + + // Note that this does much more than set a flag; + // it will also run all deferred blocks. + AppReadiness.setAppIsReady() + + // We don't need to use messageFetcherJob in the SAE. + + // We don't need to use SyncPushTokensJob in the SAE. + + // We don't need to use DeviceSleepManager in the SAE. + + AppVersion.sharedInstance().saeLaunchDidComplete() + + setUpViewHierarchy() + + // We don't need to use OWSMessageReceiver in the SAE. + // We don't need to use OWSBatchMessageProcessor in the SAE. + + OWSProfileManager.shared().ensureLocalProfileCached() + + // We don't need to use OWSOrphanDataCleaner in the SAE. + + // We don't need to fetch the local profile in the SAE + + OWSReadReceiptManager.shared().prepareCachedValues() + } + + private func setUpViewHierarchy() { + + } + + @objc + public func applicationDidEnterBackground() { + AssertIsOnMainThread() + + Logger.info("") + + if OWSScreenLock.shared.isScreenLockEnabled() { + + self.dismiss(animated: false) { [weak self] in + AssertIsOnMainThread() + guard let strongSelf = self else { return } + strongSelf.extensionContext!.completeRequest(returningItems: [], completionHandler: nil) + } + } + } + + deinit { + NotificationCenter.default.removeObserver(self) + + // Share extensions reside in a process that may be reused between usages. + // That isn't safe; the codebase is full of statics (e.g. singletons) which + // we can't easily clean up. + ExitShareExtension() + } + + // MARK: App Mode + + public func getCurrentAppMode() -> AppMode { + guard let window = self.view.window else { return .light } + let userInterfaceStyle = window.traitCollection.userInterfaceStyle + let isLightMode = (userInterfaceStyle == .light || userInterfaceStyle == .unspecified) + return isLightMode ? .light : .dark + } + + public func setCurrentAppMode(to appMode: AppMode) { + return // Not applicable to share extensions + } +}