mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Use loading screen whenever launch is slow.
Previously we had to manually account for each version that had a DB change. // FREEBIE
This commit is contained in:
parent
f2cc8cf9d2
commit
f782ea97df
4 changed files with 119 additions and 79 deletions
|
@ -307,6 +307,7 @@
|
||||||
45360B911F952AA900FA666C /* MarqueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */; };
|
45360B911F952AA900FA666C /* MarqueeLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45E5A6981F61E6DD001E4A8A /* MarqueeLabel.swift */; };
|
||||||
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4539B5851F79348F007141FF /* PushRegistrationManager.swift */; };
|
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4539B5851F79348F007141FF /* PushRegistrationManager.swift */; };
|
||||||
4542DF52208B82E9007B4E76 /* ThreadModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadModel.swift */; };
|
4542DF52208B82E9007B4E76 /* ThreadModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF51208B82E9007B4E76 /* ThreadModel.swift */; };
|
||||||
|
4542DF54208D40AC007B4E76 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4542DF53208D40AC007B4E76 /* LoadingViewController.swift */; };
|
||||||
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
|
45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */; };
|
||||||
454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454A84032059C787008B8C75 /* MediaTileViewController.swift */; };
|
454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454A84032059C787008B8C75 /* MediaTileViewController.swift */; };
|
||||||
454A965A1FD6017E008D2A0E /* SignalAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D913491F62D4A500722898 /* SignalAttachment.swift */; };
|
454A965A1FD6017E008D2A0E /* SignalAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D913491F62D4A500722898 /* SignalAttachment.swift */; };
|
||||||
|
@ -931,6 +932,7 @@
|
||||||
4539B5851F79348F007141FF /* PushRegistrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushRegistrationManager.swift; sourceTree = "<group>"; };
|
4539B5851F79348F007141FF /* PushRegistrationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushRegistrationManager.swift; sourceTree = "<group>"; };
|
||||||
453CC0361D08E1A60040EBA3 /* sn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sn; path = translations/sn.lproj/Localizable.strings; sourceTree = "<group>"; };
|
453CC0361D08E1A60040EBA3 /* sn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sn; path = translations/sn.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
4542DF51208B82E9007B4E76 /* ThreadModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadModel.swift; sourceTree = "<group>"; };
|
4542DF51208B82E9007B4E76 /* ThreadModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadModel.swift; sourceTree = "<group>"; };
|
||||||
|
4542DF53208D40AC007B4E76 /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = "<group>"; };
|
||||||
45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataChannelMessage.swift; sourceTree = "<group>"; };
|
45464DBB1DFA041F001D3FD6 /* DataChannelMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataChannelMessage.swift; sourceTree = "<group>"; };
|
||||||
454A84032059C787008B8C75 /* MediaTileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTileViewController.swift; sourceTree = "<group>"; };
|
454A84032059C787008B8C75 /* MediaTileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTileViewController.swift; sourceTree = "<group>"; };
|
||||||
454A965E1FD60EA2008D2A0E /* OWSFlatButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OWSFlatButton.swift; path = SignalMessaging/Views/OWSFlatButton.swift; sourceTree = SOURCE_ROOT; };
|
454A965E1FD60EA2008D2A0E /* OWSFlatButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OWSFlatButton.swift; path = SignalMessaging/Views/OWSFlatButton.swift; sourceTree = SOURCE_ROOT; };
|
||||||
|
@ -1655,6 +1657,7 @@
|
||||||
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */,
|
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */,
|
||||||
340FC897204DAC8D007AEB0F /* ThreadSettings */,
|
340FC897204DAC8D007AEB0F /* ThreadSettings */,
|
||||||
34D1F0BE1F8EC1760066283D /* Utils */,
|
34D1F0BE1F8EC1760066283D /* Utils */,
|
||||||
|
4542DF53208D40AC007B4E76 /* LoadingViewController.swift */,
|
||||||
);
|
);
|
||||||
path = ViewControllers;
|
path = ViewControllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3200,6 +3203,7 @@
|
||||||
452314A01F7E9E18003A428C /* DirectionalPanGestureRecognizer.swift in Sources */,
|
452314A01F7E9E18003A428C /* DirectionalPanGestureRecognizer.swift in Sources */,
|
||||||
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */,
|
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */,
|
||||||
45D2AC02204885170033C692 /* OWS2FAReminderViewController.swift in Sources */,
|
45D2AC02204885170033C692 /* OWS2FAReminderViewController.swift in Sources */,
|
||||||
|
4542DF54208D40AC007B4E76 /* LoadingViewController.swift in Sources */,
|
||||||
34D5CCA91EAE3D30005515DB /* AvatarViewHelper.m in Sources */,
|
34D5CCA91EAE3D30005515DB /* AvatarViewHelper.m in Sources */,
|
||||||
34D1F0B71F87F8850066283D /* OWSGenericAttachmentView.m in Sources */,
|
34D1F0B71F87F8850066283D /* OWSGenericAttachmentView.m in Sources */,
|
||||||
34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */,
|
34B3F8801E8DF1700035BE1A /* InviteFlow.swift in Sources */,
|
||||||
|
|
|
@ -62,6 +62,8 @@ static NSString *const kInitialViewControllerIdentifier = @"UserInitialViewContr
|
||||||
static NSString *const kURLSchemeSGNLKey = @"sgnl";
|
static NSString *const kURLSchemeSGNLKey = @"sgnl";
|
||||||
static NSString *const kURLHostVerifyPrefix = @"verify";
|
static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
|
|
||||||
|
static NSTimeInterval launchStartedAt;
|
||||||
|
|
||||||
@interface AppDelegate ()
|
@interface AppDelegate ()
|
||||||
|
|
||||||
@property (nonatomic) BOOL hasInitialRootViewController;
|
@property (nonatomic) BOOL hasInitialRootViewController;
|
||||||
|
@ -105,6 +107,8 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
// This should be the first thing we do.
|
// This should be the first thing we do.
|
||||||
SetCurrentAppContext([MainAppContext new]);
|
SetCurrentAppContext([MainAppContext new]);
|
||||||
|
|
||||||
|
launchStartedAt = CACurrentMediaTime();
|
||||||
|
|
||||||
BOOL isLoggingEnabled;
|
BOOL isLoggingEnabled;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Specified at Product -> Scheme -> Edit Scheme -> Test -> Arguments -> Environment to avoid things like
|
// Specified at Product -> Scheme -> Edit Scheme -> Test -> Arguments -> Environment to avoid things like
|
||||||
|
@ -177,8 +181,8 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
UIWindow *mainWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
UIWindow *mainWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
self.window = mainWindow;
|
self.window = mainWindow;
|
||||||
CurrentAppContext().mainWindow = mainWindow;
|
CurrentAppContext().mainWindow = mainWindow;
|
||||||
// Show the launch screen until the async database view registrations are complete.
|
// Show LoadingViewController until the async database view registrations are complete.
|
||||||
mainWindow.rootViewController = [self loadingRootViewController];
|
mainWindow.rootViewController = [LoadingViewController new];
|
||||||
[mainWindow makeKeyAndVisible];
|
[mainWindow makeKeyAndVisible];
|
||||||
|
|
||||||
// Accept push notification when app is not open
|
// Accept push notification when app is not open
|
||||||
|
@ -311,11 +315,9 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
|
|
||||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
|
|
||||||
// Show the launch screen until the async database view registrations are complete.
|
// Show the launch screen
|
||||||
//
|
self.window.rootViewController =
|
||||||
// Note: we void using loadingRootViewController, since it will indirectly try to
|
[[UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil] instantiateInitialViewController];
|
||||||
// instantiate primary storage, which will fail.
|
|
||||||
self.window.rootViewController = [self loadingRootViewControllerWithShowUpgradeWarning:NO];
|
|
||||||
|
|
||||||
[self.window makeKeyAndVisible];
|
[self.window makeKeyAndVisible];
|
||||||
|
|
||||||
|
@ -412,75 +414,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
DDLogInfo(@"iPhone Version: %@", platform);
|
DDLogInfo(@"iPhone Version: %@", platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIViewController *)loadingRootViewController
|
|
||||||
{
|
|
||||||
NSString *lastLaunchedAppVersion = AppVersion.instance.lastAppVersion;
|
|
||||||
NSString *lastCompletedLaunchAppVersion = AppVersion.instance.lastCompletedLaunchAppVersion;
|
|
||||||
// Every time we change or add a database view to a large collection or
|
|
||||||
// add a database migration to a large collection, this can delay launch
|
|
||||||
// so we need to bump this constant.
|
|
||||||
//
|
|
||||||
// We added a database migration around all outgoing messages in v2.25.0.
|
|
||||||
NSString *kLastVersionWithDatabaseViewChange = @"2.25.0";
|
|
||||||
BOOL mayNeedUpgrade = ([TSAccountManager isRegistered] && lastLaunchedAppVersion
|
|
||||||
&& (!lastCompletedLaunchAppVersion ||
|
|
||||||
[VersionMigrations isVersion:lastCompletedLaunchAppVersion
|
|
||||||
lessThan:kLastVersionWithDatabaseViewChange]));
|
|
||||||
DDLogInfo(@"%@ mayNeedUpgrade: %d", self.logTag, mayNeedUpgrade);
|
|
||||||
|
|
||||||
return [self loadingRootViewControllerWithShowUpgradeWarning:mayNeedUpgrade];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIViewController *)loadingRootViewControllerWithShowUpgradeWarning:(BOOL)showUpgradeWarning
|
|
||||||
{
|
|
||||||
UIViewController *viewController =
|
|
||||||
[[UIStoryboard storyboardWithName:@"Launch Screen" bundle:nil] instantiateInitialViewController];
|
|
||||||
|
|
||||||
if (!showUpgradeWarning) {
|
|
||||||
return viewController;
|
|
||||||
}
|
|
||||||
|
|
||||||
UIView *rootView = viewController.view;
|
|
||||||
UIImageView *iconView = nil;
|
|
||||||
for (UIView *subview in viewController.view.subviews) {
|
|
||||||
if ([subview isKindOfClass:[UIImageView class]]) {
|
|
||||||
iconView = (UIImageView *)subview;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!iconView) {
|
|
||||||
OWSFail(@"Database view registration overlay has unexpected contents.");
|
|
||||||
return viewController;
|
|
||||||
}
|
|
||||||
|
|
||||||
UILabel *bottomLabel = [UILabel new];
|
|
||||||
bottomLabel.text = NSLocalizedString(
|
|
||||||
@"DATABASE_VIEW_OVERLAY_SUBTITLE", @"Subtitle shown while the app is updating its database.");
|
|
||||||
bottomLabel.font = [UIFont ows_mediumFontWithSize:16.f];
|
|
||||||
bottomLabel.textColor = [UIColor whiteColor];
|
|
||||||
bottomLabel.numberOfLines = 0;
|
|
||||||
bottomLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
||||||
bottomLabel.textAlignment = NSTextAlignmentCenter;
|
|
||||||
[rootView addSubview:bottomLabel];
|
|
||||||
|
|
||||||
UILabel *topLabel = [UILabel new];
|
|
||||||
topLabel.text
|
|
||||||
= NSLocalizedString(@"DATABASE_VIEW_OVERLAY_TITLE", @"Title shown while the app is updating its database.");
|
|
||||||
topLabel.font = [UIFont ows_mediumFontWithSize:20.f];
|
|
||||||
topLabel.textColor = [UIColor whiteColor];
|
|
||||||
topLabel.numberOfLines = 0;
|
|
||||||
topLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
||||||
topLabel.textAlignment = NSTextAlignmentCenter;
|
|
||||||
[rootView addSubview:topLabel];
|
|
||||||
|
|
||||||
[bottomLabel autoPinWidthToSuperviewWithMargin:20.f];
|
|
||||||
[topLabel autoPinWidthToSuperviewWithMargin:20.f];
|
|
||||||
[bottomLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:topLabel withOffset:10.f];
|
|
||||||
[iconView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:bottomLabel withOffset:40.f];
|
|
||||||
|
|
||||||
return viewController;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
||||||
{
|
{
|
||||||
OWSAssertIsOnMainThread();
|
OWSAssertIsOnMainThread();
|
||||||
|
@ -1145,7 +1078,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
[self enableBackgroundRefreshIfNecessary];
|
[self enableBackgroundRefreshIfNecessary];
|
||||||
|
|
||||||
if ([TSAccountManager isRegistered]) {
|
if ([TSAccountManager isRegistered]) {
|
||||||
DDLogInfo(@"localNumber: %@", [TSAccountManager localNumber]);
|
DDLogInfo(@"%@ localNumber: %@", [TSAccountManager localNumber], self.logTag);
|
||||||
|
|
||||||
[[OWSPrimaryStorage sharedManager].newDatabaseConnection
|
[[OWSPrimaryStorage sharedManager].newDatabaseConnection
|
||||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||||
|
@ -1177,7 +1110,8 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||||
}
|
}
|
||||||
self.hasInitialRootViewController = YES;
|
self.hasInitialRootViewController = YES;
|
||||||
|
|
||||||
DDLogInfo(@"%@ Presenting initial root view controller", self.logTag);
|
NSTimeInterval startupDuration = CACurrentMediaTime() - launchStartedAt;
|
||||||
|
DDLogInfo(@"%@ Presenting app %.2f seconds after launch started.", self.logTag, startupDuration);
|
||||||
|
|
||||||
if ([TSAccountManager isRegistered]) {
|
if ([TSAccountManager isRegistered]) {
|
||||||
HomeViewController *homeView = [HomeViewController new];
|
HomeViewController *homeView = [HomeViewController new];
|
||||||
|
|
102
Signal/src/ViewControllers/LoadingViewController.swift
Normal file
102
Signal/src/ViewControllers/LoadingViewController.swift
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import PromiseKit
|
||||||
|
|
||||||
|
// The initial presentation is intended to be indistinguishable from the Launch Screen.
|
||||||
|
// After a delay we present some "loading" UI so the user doesn't think the app is frozen.
|
||||||
|
@objc
|
||||||
|
public class LoadingViewController: UIViewController {
|
||||||
|
|
||||||
|
var logoView: UIImageView!
|
||||||
|
var topLabel: UILabel!
|
||||||
|
var bottomLabel: UILabel!
|
||||||
|
|
||||||
|
override public func loadView() {
|
||||||
|
self.view = UIView()
|
||||||
|
view.backgroundColor = UIColor.ows_materialBlue
|
||||||
|
|
||||||
|
self.logoView = UIImageView(image: #imageLiteral(resourceName: "logoSignal"))
|
||||||
|
view.addSubview(logoView)
|
||||||
|
|
||||||
|
logoView.autoCenterInSuperview()
|
||||||
|
logoView.autoPinToSquareAspectRatio()
|
||||||
|
logoView.autoMatch(.width, to: .width, of: view, withMultiplier: 1/3)
|
||||||
|
|
||||||
|
self.topLabel = buildLabel()
|
||||||
|
topLabel.alpha = 0
|
||||||
|
topLabel.font = UIFont.ows_dynamicTypeTitle2
|
||||||
|
topLabel.text = NSLocalizedString("DATABASE_VIEW_OVERLAY_TITLE", comment: "Title shown while the app is updating its database.")
|
||||||
|
|
||||||
|
self.bottomLabel = buildLabel()
|
||||||
|
bottomLabel.alpha = 0
|
||||||
|
bottomLabel.font = UIFont.ows_dynamicTypeBody
|
||||||
|
bottomLabel.text = NSLocalizedString("DATABASE_VIEW_OVERLAY_SUBTITLE", comment: "Subtitle shown while the app is updating its database.")
|
||||||
|
|
||||||
|
let labelStack = UIStackView(arrangedSubviews: [topLabel, bottomLabel])
|
||||||
|
labelStack.axis = .vertical
|
||||||
|
labelStack.alignment = .center
|
||||||
|
labelStack.spacing = 8
|
||||||
|
view.addSubview(labelStack)
|
||||||
|
|
||||||
|
labelStack.autoPinEdge(.top, to: .bottom, of: logoView, withOffset: 20)
|
||||||
|
labelStack.autoPinLeadingToSuperviewMargin()
|
||||||
|
labelStack.autoPinTrailingToSuperviewMargin()
|
||||||
|
labelStack.setCompressionResistanceHigh()
|
||||||
|
labelStack.setContentHuggingHigh()
|
||||||
|
}
|
||||||
|
|
||||||
|
var isShowingTopLabel = false
|
||||||
|
var isShowingBottomLabel = false
|
||||||
|
override public func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
// We only show the "loading" UI if it's a slow launch. Otherwise this ViewController
|
||||||
|
// should be indistinguishable from the launch screen.
|
||||||
|
let kTopLabelThreshold: TimeInterval = 5
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + kTopLabelThreshold) { [weak self] in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !strongSelf.isShowingTopLabel else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.isShowingTopLabel = true
|
||||||
|
UIView.animate(withDuration: 0.1) {
|
||||||
|
strongSelf.topLabel.alpha = 1
|
||||||
|
}
|
||||||
|
UIView.animate(withDuration: 0.9, delay: 2, options: [.autoreverse, .repeat, .curveEaseInOut], animations: {
|
||||||
|
strongSelf.topLabel.alpha = 0.2
|
||||||
|
}, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
let kBottomLabelThreshold: TimeInterval = 15
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + kBottomLabelThreshold) { [weak self] in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard !strongSelf.isShowingBottomLabel else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.isShowingBottomLabel = true
|
||||||
|
UIView.animate(withDuration: 0.1) {
|
||||||
|
strongSelf.bottomLabel.alpha = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func buildLabel() -> UILabel {
|
||||||
|
let label = UILabel()
|
||||||
|
|
||||||
|
label.textColor = .white
|
||||||
|
label.numberOfLines = 0
|
||||||
|
label.lineBreakMode = .byWordWrapping
|
||||||
|
|
||||||
|
return label
|
||||||
|
}
|
||||||
|
}
|
|
@ -506,7 +506,7 @@
|
||||||
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "This can take a few minutes.";
|
"DATABASE_VIEW_OVERLAY_SUBTITLE" = "This can take a few minutes.";
|
||||||
|
|
||||||
/* Title shown while the app is updating its database. */
|
/* Title shown while the app is updating its database. */
|
||||||
"DATABASE_VIEW_OVERLAY_TITLE" = "Updating Database";
|
"DATABASE_VIEW_OVERLAY_TITLE" = "Optimizing Database";
|
||||||
|
|
||||||
/* The current day. */
|
/* The current day. */
|
||||||
"DATE_TODAY" = "Today";
|
"DATE_TODAY" = "Today";
|
||||||
|
|
Loading…
Reference in a new issue