diff --git a/Limelight/Crypto/IdManager.m b/Limelight/Crypto/IdManager.m index 25c6551..3208490 100644 --- a/Limelight/Crypto/IdManager.m +++ b/Limelight/Crypto/IdManager.m @@ -13,15 +13,14 @@ + (NSString*) getUniqueId { DataManager* dataMan = [[DataManager alloc] init]; - Settings* prefs = [dataMan retrieveSettings]; - - NSString* uniqueId = prefs.uniqueId; + + NSString* uniqueId = [dataMan getUniqueId]; if (uniqueId == nil) { uniqueId = [IdManager generateUniqueId]; - prefs.uniqueId = uniqueId; - [dataMan saveData]; + [dataMan updateUniqueId:uniqueId]; Log(LOG_I, @"No UUID found. Generated new UUID: %@", uniqueId); } + return uniqueId; } diff --git a/Limelight/Database/DataManager.h b/Limelight/Database/DataManager.h index 0962363..bd969ed 100644 --- a/Limelight/Database/DataManager.h +++ b/Limelight/Database/DataManager.h @@ -7,23 +7,22 @@ // #import -#import "Settings.h" #import "AppDelegate.h" -#import "Host.h" -#import "App.h" +#import "TemporaryHost.h" #import "TemporaryApp.h" +#import "TemporarySettings.h" @interface DataManager : NSObject -@property (strong, nonatomic) AppDelegate* appDelegate; - - (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls; -- (Settings*) retrieveSettings; -- (NSArray*) retrieveHosts; -- (void) saveData; -- (Host*) createHost; -- (void) removeHost:(Host*)host; -- (App*) addAppFromTemporaryApp:(TemporaryApp*)tempApp; -- (void) removeAppFromHost:(App*)app; + +- (NSArray*) getHosts; +- (void) updateHost:(TemporaryHost*)host; +- (void) removeHost:(TemporaryHost*)host; + +- (TemporarySettings*) getSettings; + +- (void) updateUniqueId:(NSString*)uniqueId; +- (NSString*) getUniqueId; @end diff --git a/Limelight/Database/DataManager.m b/Limelight/Database/DataManager.m index bb16b4d..e72f336 100644 --- a/Limelight/Database/DataManager.m +++ b/Limelight/Database/DataManager.m @@ -8,45 +8,87 @@ #import "DataManager.h" #import "TemporaryApp.h" +#import "TemporarySettings.h" +#import "Settings.h" -@implementation DataManager - -+ (NSObject *)databaseLock { - static NSObject *lock = nil; - if (lock == nil) { - lock = [[NSObject alloc] init]; - } - return lock; +@implementation DataManager { + NSManagedObjectContext *_managedObjectContext; + AppDelegate *_appDelegate; } - (id) init { self = [super init]; - self.appDelegate = [[UIApplication sharedApplication] delegate]; + + _appDelegate = [[UIApplication sharedApplication] delegate]; + _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; + [_managedObjectContext setPersistentStoreCoordinator:_appDelegate.persistentStoreCoordinator]; + return self; } -- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls { - Settings* settingsToSave = [self retrieveSettings]; - settingsToSave.framerate = [NSNumber numberWithInteger:framerate]; - // Bitrate is persisted in kbps - settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate]; - settingsToSave.height = [NSNumber numberWithInteger:height]; - settingsToSave.width = [NSNumber numberWithInteger:width]; - settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls]; +- (void) updateUniqueId:(NSString*)uniqueId { + [_managedObjectContext performBlockAndWait:^{ + [self retrieveSettings].uniqueId = uniqueId; + [self saveData]; + }]; +} - NSError* error; - if (![[self.appDelegate managedObjectContext] save:&error]) { - Log(LOG_E, @"Unable to save settings to database: %@", error); - } - [self.appDelegate saveContext]; +- (NSString*) getUniqueId { + __block NSString *uid; + + [_managedObjectContext performBlockAndWait:^{ + uid = [self retrieveSettings].uniqueId; + }]; + + return uid; +} + +- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls { + + [_managedObjectContext performBlockAndWait:^{ + Settings* settingsToSave = [self retrieveSettings]; + settingsToSave.framerate = [NSNumber numberWithInteger:framerate]; + // Bitrate is persisted in kbps + settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate]; + settingsToSave.height = [NSNumber numberWithInteger:height]; + settingsToSave.width = [NSNumber numberWithInteger:width]; + settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls]; + + [self saveData]; + }]; +} + +- (void) updateHost:(TemporaryHost *)host { + [_managedObjectContext performBlockAndWait:^{ + // Add a new persistent managed object if one doesn't exist + if (host.parent == nil) { + NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:_managedObjectContext]; + host.parent = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext]; + } + + // Push changes from the temp host to the persistent one + [host propagateChangesToParent]; + + [self saveData]; + }]; +} + +- (TemporarySettings*) getSettings { + __block TemporarySettings *tempSettings; + + [_managedObjectContext performBlockAndWait:^{ + tempSettings = [[TemporarySettings alloc] initFromSettings:[self retrieveSettings]]; + }]; + + return tempSettings; } - (Settings*) retrieveSettings { NSArray* fetchedRecords = [self fetchRecords:@"Settings"]; if (fetchedRecords.count == 0) { // create a new settings object with the default values - NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:[self.appDelegate managedObjectContext]]; - Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]]; + NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext]; + Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext]; return settings; } else { @@ -55,74 +97,51 @@ } } -- (Host*) createHost { - NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]]; - return [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]]; -} - -- (void) removeHost:(Host*)host { - [[self.appDelegate managedObjectContext] deleteObject:host]; - [self saveData]; +- (void) removeHost:(TemporaryHost*)host { + if (host.parent == nil) { + // Not inserted into the DB + return; + } + + [_managedObjectContext performBlockAndWait:^{ + [_managedObjectContext deleteObject:host.parent]; + [self saveData]; + }]; } - (void) saveData { - @synchronized([DataManager databaseLock]) { - NSError* error; - if (![[self.appDelegate managedObjectContext] save:&error]) { - Log(LOG_E, @"Unable to save hosts to database: %@", error); + NSError* error; + if (![_managedObjectContext save:&error]) { + Log(LOG_E, @"Unable to save hosts to database: %@", error); + } + + [_appDelegate saveContext]; +} + +- (NSArray*) getHosts { + __block NSMutableArray *tempHosts = [[NSMutableArray alloc] init]; + + [_managedObjectContext performBlockAndWait:^{ + NSArray *hosts = [self fetchRecords:@"Host"]; + + for (Host* host in hosts) { + [tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]]; } - [self.appDelegate saveContext]; - } -} - -- (NSArray*) retrieveHosts { - return [self fetchRecords:@"Host"]; -} - -- (App*) addAppFromTemporaryApp:(TemporaryApp*)tempApp { + }]; - App* managedApp; - - @synchronized([DataManager databaseLock]) { - NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:[self.appDelegate managedObjectContext]]; - managedApp = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]]; - - assert(tempApp.host != nil); - - managedApp.id = tempApp.id; - managedApp.image = tempApp.image; - managedApp.name = tempApp.name; - managedApp.isRunning = tempApp.isRunning; - managedApp.host = tempApp.host; - - [managedApp.host addAppListObject:managedApp]; - } - - return managedApp; -} - -- (void) removeAppFromHost:(App*)app { - @synchronized([DataManager databaseLock]) { - assert(app.host != nil); - - [app.host removeAppListObject:app]; - [[self.appDelegate managedObjectContext] deleteObject:app]; - } + return tempHosts; } - (NSArray*) fetchRecords:(NSString*)entityName { NSArray* fetchedRecords; - @synchronized([DataManager databaseLock]) { - NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init]; - NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self.appDelegate managedObjectContext]]; - [fetchRequest setEntity:entity]; - [fetchRequest setAffectedStores:[NSArray arrayWithObjects:[[self.appDelegate persistentStoreCoordinator] persistentStoreForURL:[self.appDelegate getStoreURL]], nil]]; - - NSError* error; - fetchedRecords = [[self.appDelegate managedObjectContext] executeFetchRequest:fetchRequest error:&error]; - //TODO: handle errors - } + NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init]; + NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext]; + [fetchRequest setEntity:entity]; + + NSError* error; + fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error]; + //TODO: handle errors return fetchedRecords; } diff --git a/Limelight/Database/TemporaryApp.h b/Limelight/Database/TemporaryApp.h index b2b6fdf..41b8b5c 100644 --- a/Limelight/Database/TemporaryApp.h +++ b/Limelight/Database/TemporaryApp.h @@ -8,6 +8,7 @@ #import #import "TemporaryHost.h" +#import "App.h" @interface TemporaryApp : NSObject @@ -17,10 +18,16 @@ @property (nonatomic) BOOL isRunning; @property (nullable, nonatomic, retain) TemporaryHost *host; +@property (nullable, nonatomic) App* parent; + NS_ASSUME_NONNULL_BEGIN +- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost; + - (NSComparisonResult)compareName:(TemporaryApp *)other; +- (void) propagateChangesToParent; + NS_ASSUME_NONNULL_END @end diff --git a/Limelight/Database/TemporaryApp.m b/Limelight/Database/TemporaryApp.m index 13f7818..19b2327 100644 --- a/Limelight/Database/TemporaryApp.m +++ b/Limelight/Database/TemporaryApp.m @@ -7,9 +7,30 @@ // #import "TemporaryApp.h" +#import "App.h" @implementation TemporaryApp +- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost { + self = [self init]; + + self.parent = app; + + self.id = app.id; + self.image = app.image; + self.name = app.name; + self.host = tempHost; + + return self; +} + +- (void) propagateChangesToParent { + self.parent.id = self.id; + self.parent.image = self.image; + self.parent.name = self.name; + self.parent.host = self.host.parent; +} + - (NSComparisonResult)compareName:(TemporaryApp *)other { return [self.name caseInsensitiveCompare:other.name]; } diff --git a/Limelight/Database/TemporaryHost.h b/Limelight/Database/TemporaryHost.h index be6602c..8ed11c3 100644 --- a/Limelight/Database/TemporaryHost.h +++ b/Limelight/Database/TemporaryHost.h @@ -8,6 +8,7 @@ #import #import "Utils.h" +#import "Host.h" @interface TemporaryHost : NSObject @@ -15,18 +16,24 @@ @property (nonatomic) PairState pairState; @property (nonatomic, nullable) NSString * activeAddress; -@property (nullable, nonatomic, retain) NSString *address; -@property (nullable, nonatomic, retain) NSString *externalAddress; -@property (nullable, nonatomic, retain) NSString *localAddress; -@property (nullable, nonatomic, retain) NSString *mac; -@property (nullable, nonatomic, retain) NSString *name; -@property (nullable, nonatomic, retain) NSString *uuid; -@property (nullable, nonatomic, retain) NSSet *appList; +@property (nullable, nonatomic) Host* parent; NS_ASSUME_NONNULL_BEGIN +@property (nonatomic, retain) NSString *address; +@property (nonatomic, retain) NSString *externalAddress; +@property (nonatomic, retain) NSString *localAddress; +@property (nonatomic, retain) NSString *mac; +@property (nonatomic, retain) NSString *name; +@property (nonatomic, retain) NSString *uuid; +@property (nonatomic, retain) NSSet *appList; + +- (id) initFromHost:(Host*)host; + - (NSComparisonResult)compareName:(TemporaryHost *)other; +- (void) propagateChangesToParent; + NS_ASSUME_NONNULL_END @end diff --git a/Limelight/Database/TemporaryHost.m b/Limelight/Database/TemporaryHost.m index 2c1bd21..45e0d0e 100644 --- a/Limelight/Database/TemporaryHost.m +++ b/Limelight/Database/TemporaryHost.m @@ -7,9 +7,60 @@ // #import "TemporaryHost.h" +#import "Host.h" +#import "TemporaryApp.h" +#import "App.h" @implementation TemporaryHost +- (id) initFromHost:(Host*)host { + self = [self init]; + + self.parent = host; + + self.address = host.address; + self.externalAddress = host.externalAddress; + self.localAddress = host.localAddress; + self.mac = host.mac; + self.name = host.name; + self.uuid = host.uuid; + + NSMutableSet *appList = [[NSMutableSet alloc] init]; + + for (App* app in host.appList) { + TemporaryApp *tempApp = [[TemporaryApp alloc] initFromApp:app withTempHost:self]; + [appList addObject:tempApp]; + } + + self.appList = appList; + + return self; +} + +- (void) propagateChangesToParent { + self.parent.address = self.address; + self.parent.externalAddress = self.externalAddress; + self.parent.localAddress = self.localAddress; + self.parent.mac = self.mac; + self.parent.name = self.name; + self.parent.uuid = self.uuid; + + NSMutableSet *applist = [[NSMutableSet alloc] init]; + for (TemporaryApp* app in self.appList) { + // Add a new persistent managed object if one doesn't exist + if (app.parent == nil) { + NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:self.parent.managedObjectContext]; + app.parent = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:self.parent.managedObjectContext]; + } + + [app propagateChangesToParent]; + + [applist addObject:app.parent]; + } + + self.parent.appList = applist; +} + - (NSComparisonResult)compareName:(TemporaryHost *)other { return [self.name caseInsensitiveCompare:other.name]; } diff --git a/Limelight/Database/TemporarySettings.h b/Limelight/Database/TemporarySettings.h new file mode 100644 index 0000000..2228912 --- /dev/null +++ b/Limelight/Database/TemporarySettings.h @@ -0,0 +1,25 @@ +// +// TemporarySettings.h +// Moonlight +// +// Created by Cameron Gutman on 12/1/15. +// Copyright © 2015 Moonlight Stream. All rights reserved. +// + +#import +#import "Settings.h" + +@interface TemporarySettings : NSObject + +@property (nonatomic, retain) Settings * parent; + +@property (nonatomic, retain) NSNumber * bitrate; +@property (nonatomic, retain) NSNumber * framerate; +@property (nonatomic, retain) NSNumber * height; +@property (nonatomic, retain) NSNumber * width; +@property (nonatomic, retain) NSNumber * onscreenControls; +@property (nonatomic, retain) NSString * uniqueId; + +- (id) initFromSettings:(Settings*)settings; + +@end diff --git a/Limelight/Database/TemporarySettings.m b/Limelight/Database/TemporarySettings.m new file mode 100644 index 0000000..4b7437f --- /dev/null +++ b/Limelight/Database/TemporarySettings.m @@ -0,0 +1,28 @@ +// +// TemporarySettings.m +// Moonlight +// +// Created by Cameron Gutman on 12/1/15. +// Copyright © 2015 Moonlight Stream. All rights reserved. +// + +#import "TemporarySettings.h" + +@implementation TemporarySettings + +- (id) initFromSettings:(Settings*)settings { + self = [self init]; + + self.parent = settings; + + self.bitrate = settings.bitrate; + self.framerate = settings.framerate; + self.height = settings.height; + self.width = settings.width; + self.onscreenControls = settings.onscreenControls; + self.uniqueId = settings.uniqueId; + + return self; +} + +@end diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index 421438a..3f6cb9a 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -32,7 +32,7 @@ - (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id)swipeDelegate { onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate]; DataManager* dataMan = [[DataManager alloc] init]; - OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue]; + OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue]; if (level == OnScreenControlsLevelAuto) { [controllerSupport initAutoOnScreenControlMode:onScreenControls]; diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m index 6deee0b..8e7c3ec 100644 --- a/Limelight/ViewControllers/MainFrameViewController.m +++ b/Limelight/ViewControllers/MainFrameViewController.m @@ -17,7 +17,7 @@ #import "UIAppView.h" #import "SettingsViewController.h" #import "DataManager.h" -#import "Settings.h" +#import "TemporarySettings.h" #import "WakeOnLanManager.h" #import "AppListResponse.h" #import "ServerInfoResponse.h" @@ -162,15 +162,12 @@ static NSMutableSet* hostList; DataManager* database = [[DataManager alloc] init]; host.appList = newList; - [database updateHost:host]; - [database saveData]; } - (void)showHostSelectionView { [_appManager stopRetrieving]; - [[[DataManager alloc] init] saveData]; _selectedHost = nil; _computerNameButton.title = @"No Host Selected"; [self.collectionView reloadData]; @@ -339,7 +336,7 @@ static NSMutableSet* hostList; _streamConfig.appID = app.id; DataManager* dataMan = [[DataManager alloc] init]; - Settings* streamSettings = [dataMan retrieveSettings]; + TemporarySettings* streamSettings = [dataMan getSettings]; _streamConfig.frameRate = [streamSettings.framerate intValue]; _streamConfig.bitRate = [streamSettings.bitrate intValue]; @@ -556,14 +553,11 @@ static NSMutableSet* hostList; // Purge the box art cache [_boxArtCache removeAllObjects]; - - // In case the host objects were updated in the background - [[[DataManager alloc] init] saveData]; } - (void) retrieveSavedHosts { DataManager* dataMan = [[DataManager alloc] init]; - NSArray* hosts = [dataMan retrieveHosts]; + NSArray* hosts = [dataMan getHosts]; @synchronized(hostList) { [hostList addObjectsFromArray:hosts]; diff --git a/Limelight/ViewControllers/SettingsViewController.m b/Limelight/ViewControllers/SettingsViewController.m index 30eddfb..0d81572 100644 --- a/Limelight/ViewControllers/SettingsViewController.m +++ b/Limelight/ViewControllers/SettingsViewController.m @@ -7,7 +7,7 @@ // #import "SettingsViewController.h" -#import "Settings.h" +#import "TemporarySettings.h" #import "DataManager.h" #define BITRATE_INTERVAL 500 // in kbps @@ -22,7 +22,7 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps"; [super viewDidLoad]; DataManager* dataMan = [[DataManager alloc] init]; - Settings* currentSettings = [dataMan retrieveSettings]; + TemporarySettings* currentSettings = [dataMan getSettings]; // Bitrate is persisted in kbps _bitrate = [currentSettings.bitrate integerValue]; diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj index 11e4019..a27ab4b 100644 --- a/Moonlight.xcodeproj/project.pbxproj +++ b/Moonlight.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */; }; 987140041B04542F00AB57D5 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */; }; 98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; }; + 98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */; }; 9E5D600B1A5A5A3900689918 /* Apache License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FF81A5A5A3900689918 /* Apache License.txt */; }; 9E5D600C1A5A5A3900689918 /* Roboto-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FF91A5A5A3900689918 /* Roboto-Black.ttf */; }; 9E5D600E1A5A5A3900689918 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */; }; @@ -101,6 +102,8 @@ 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "limelight-common-c/moonlight-common.xcodeproj"; sourceTree = ""; }; 98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryHost.h; path = Database/TemporaryHost.h; sourceTree = ""; }; 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryHost.m; path = Database/TemporaryHost.m; sourceTree = ""; }; + 98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporarySettings.h; path = Database/TemporarySettings.h; sourceTree = ""; }; + 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporarySettings.m; path = Database/TemporarySettings.m; sourceTree = ""; }; 9E5D5FF81A5A5A3900689918 /* Apache License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Apache License.txt"; sourceTree = ""; }; 9E5D5FF91A5A5A3900689918 /* Roboto-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Black.ttf"; sourceTree = ""; }; 9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = ""; }; @@ -738,6 +741,8 @@ 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */, 98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */, 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */, + 98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */, + 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */, ); name = Database; sourceTree = ""; @@ -866,6 +871,7 @@ FB1D599A1BBCCD7E00F482CA /* AppCollectionView.m in Sources */, FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */, 9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */, + 98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */, FB89462819F646E200339C8A /* CryptoManager.m in Sources */, FB89462E19F646E200339C8A /* PairManager.m in Sources */, FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,