session-ios/Session/Meta/MainAppContext.m
Morgan Pretty aabf656d89 Finished off the MediaGallery logic
Updated the config message generation for GRDB
Migrated more preferences into GRDB
Added paging to the MediaTileViewController and sorted out the various animations/transitions
Fixed an issue where the 'recipientState' for the 'baseQuery' on the ConversationCell.ViewModel wasn't grouping correctly
Fixed an issue where the MediaZoomAnimationController could fail if the contextual info wasn't available
Fixed an issue where the MediaZoomAnimationController bounce looked odd when returning to the detail screen from the tile screen
Fixed an issue where the MediaZoomAnimationController didn't work for videos
Fixed a bug where the YDB to GRDB migration wasn't properly handling video files
Fixed a number of minor UI bugs with the GalleryRailView
Deleted a bunch of legacy code
2022-05-20 17:58:39 +10:00

327 lines
10 KiB
Objective-C

//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "MainAppContext.h"
#import "Session-Swift.h"
#import <SignalCoreKit/Threading.h>
#import <SessionMessagingKit/Environment.h>
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplicationStateDidChangeNotification";
@interface MainAppContext ()
@property (atomic) UIApplicationState reportedApplicationState;
@property (nonatomic, nullable) NSMutableArray<AppActiveBlock> *appActiveBlocks;
@end
#pragma mark -
@implementation MainAppContext
@synthesize mainWindow = _mainWindow;
@synthesize appLaunchTime = _appLaunchTime;
@synthesize wasWokenUpByPushNotification = _wasWokenUpByPushNotification;
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
self.reportedApplicationState = UIApplicationStateInactive;
_appLaunchTime = [NSDate new];
_wasWokenUpByPushNotification = false;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:nil];
// We can't use OWSSingletonAssert() since it uses the app context.
self.appActiveBlocks = [NSMutableArray new];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Notifications
- (void)setReportedApplicationState:(UIApplicationState)reportedApplicationState
{
OWSAssertIsOnMainThread();
if (_reportedApplicationState == reportedApplicationState) {
return;
}
_reportedApplicationState = reportedApplicationState;
[[NSNotificationCenter defaultCenter] postNotificationName:ReportedApplicationStateDidChangeNotification
object:nil
userInfo:nil];
}
- (void)applicationWillEnterForeground:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateInactive;
OWSLogInfo(@"");
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillEnterForegroundNotification object:nil];
}
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateBackground;
OWSLogInfo(@"");
[DDLog flushLog];
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidEnterBackgroundNotification object:nil];
}
- (void)applicationWillResignActive:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateInactive;
OWSLogInfo(@"");
[DDLog flushLog];
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationWillResignActiveNotification object:nil];
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
self.reportedApplicationState = UIApplicationStateActive;
OWSLogInfo(@"");
[NSNotificationCenter.defaultCenter postNotificationName:OWSApplicationDidBecomeActiveNotification object:nil];
[self runAppActiveBlocks];
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
OWSAssertIsOnMainThread();
OWSLogInfo(@"");
[DDLog flushLog];
}
#pragma mark -
- (BOOL)isMainApp
{
return YES;
}
- (BOOL)isMainAppAndActive
{
return [UIApplication sharedApplication].applicationState == UIApplicationStateActive;
}
- (BOOL)isShareExtension {
return NO;
}
- (BOOL)isRTL
{
// FIXME: We should try to remove this as we've had to add a hack to ensure the first call to this runs on the main thread
static BOOL isRTL = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
isRTL = [[UIApplication sharedApplication] userInterfaceLayoutDirection]
== UIUserInterfaceLayoutDirectionRightToLeft;
});
return isRTL;
}
- (void)setStatusBarHidden:(BOOL)isHidden animated:(BOOL)isAnimated
{
[[UIApplication sharedApplication] setStatusBarHidden:isHidden animated:isAnimated];
}
- (CGFloat)statusBarHeight
{
return [UIApplication sharedApplication].statusBarFrame.size.height;
}
- (BOOL)isInBackground
{
return self.reportedApplicationState == UIApplicationStateBackground;
}
- (BOOL)isAppForegroundAndActive
{
return self.reportedApplicationState == UIApplicationStateActive;
}
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:
(BackgroundTaskExpirationHandler)expirationHandler
{
return [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:expirationHandler];
}
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)backgroundTaskIdentifier
{
[UIApplication.sharedApplication endBackgroundTask:backgroundTaskIdentifier];
}
- (void)ensureSleepBlocking:(BOOL)shouldBeBlocking blockingObjects:(NSArray<id> *)blockingObjects
{
if (UIApplication.sharedApplication.isIdleTimerDisabled != shouldBeBlocking) {
if (shouldBeBlocking) {
NSMutableString *logString =
[NSMutableString stringWithFormat:@"Blocking sleep because of: %@", blockingObjects.firstObject];
if (blockingObjects.count > 1) {
[logString appendString:[NSString stringWithFormat:@"(and %lu others)", blockingObjects.count - 1]];
}
OWSLogInfo(@"%@", logString);
} else {
OWSLogInfo(@"Unblocking Sleep.");
}
}
UIApplication.sharedApplication.idleTimerDisabled = shouldBeBlocking;
}
- (void)setMainAppBadgeNumber:(NSInteger)value
{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:value];
[[NSUserDefaults sharedLokiProject] setInteger:value forKey:@"currentBadgeNumber"];
[[NSUserDefaults sharedLokiProject] synchronize];
}
- (nullable UIViewController *)frontmostViewController
{
return UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts;
}
- (nullable UIAlertAction *)openSystemSettingsAction
{
return [UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"system_settings")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *_Nonnull action) {
[UIApplication.sharedApplication openSystemSettings];
}];
}
- (BOOL)isRunningTests
{
return getenv("runningTests_dontStartApp");
}
- (void)setNetworkActivityIndicatorVisible:(BOOL)value
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:value];
}
#pragma mark -
- (void)runNowOrWhenMainAppIsActive:(AppActiveBlock)block
{
OWSAssertDebug(block);
DispatchMainThreadSafe(^{
if (self.isMainAppAndActive) {
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
// work.
OWSBackgroundTask *_Nullable backgroundTask =
[OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
block();
OWSAssertDebug(backgroundTask);
backgroundTask = nil;
return;
}
[self.appActiveBlocks addObject:block];
});
}
- (void)runAppActiveBlocks
{
OWSAssertIsOnMainThread();
OWSAssertDebug(self.isMainAppAndActive);
// App active blocks typically will be used to safely access the
// shared data container, so use a background task to protect this
// work.
OWSBackgroundTask *_Nullable backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__];
NSArray<AppActiveBlock> *appActiveBlocks = [self.appActiveBlocks copy];
[self.appActiveBlocks removeAllObjects];
for (AppActiveBlock block in appActiveBlocks) {
block();
}
OWSAssertDebug(backgroundTask);
backgroundTask = nil;
}
- (id<SSKKeychainStorage>)keychainStorage
{
return [SSKDefaultKeychainStorage shared];
}
- (NSString *)appDocumentDirectoryPath
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectoryURL =
[[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
return [documentDirectoryURL path];
}
- (NSString *)appSharedDataDirectoryPath
{
NSURL *groupContainerDirectoryURL =
[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:SignalApplicationGroup];
return [groupContainerDirectoryURL path];
}
- (NSUserDefaults *)appUserDefaults
{
return [[NSUserDefaults alloc] initWithSuiteName:SignalApplicationGroup];
}
@end
NS_ASSUME_NONNULL_END