Merge branch 'dev' of https://github.com/loki-project/session-ios into notification-bugs

This commit is contained in:
Ryan ZHAO 2020-07-31 13:03:21 +10:00
commit 04c6610e10
10 changed files with 128 additions and 129 deletions

View File

@ -574,7 +574,6 @@
C31A6C5A247F214E001123EF /* UIView+Glow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31A6C59247F214E001123EF /* UIView+Glow.swift */; };
C31A6C5C247F2CF3001123EF /* CGRect+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */; };
C34C8F7423A7830B00D82669 /* SpaceMono-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */; };
C353F8F7244808E90011121A /* PNModeSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C353F8F6244808E90011121A /* PNModeSheet.swift */; };
C353F8F9244809150011121A /* PNOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C353F8F8244809150011121A /* PNOptionView.swift */; };
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; };
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */; };
@ -584,6 +583,7 @@
C35E8AA92485C85800ACB629 /* GeoLite2-Country-Blocks-IPv4.csv in Resources */ = {isa = PBXBuildFile; fileRef = C35E8AA62485C85600ACB629 /* GeoLite2-Country-Blocks-IPv4.csv */; };
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35E8AAD2485E51D00ACB629 /* IP2Country.swift */; };
C3638C0524C7F0B500AF29BC /* LK002RemoveFriendRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3638C0424C7F0B500AF29BC /* LK002RemoveFriendRequests.swift */; };
C369549D24D27A3500CEB4E3 /* MultiDeviceRemovalSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C369549C24D27A3500CEB4E3 /* MultiDeviceRemovalSheet.swift */; };
C36B8707243C50C60049991D /* SignalMessaging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 453518921FC63DBF00210559 /* SignalMessaging.framework */; };
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */; };
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */; };
@ -1362,7 +1362,6 @@
C31A6C59247F214E001123EF /* UIView+Glow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Glow.swift"; sourceTree = "<group>"; };
C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGRect+Utilities.swift"; sourceTree = "<group>"; };
C34C8F7323A7830A00D82669 /* SpaceMono-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Bold.ttf"; sourceTree = "<group>"; };
C353F8F6244808E90011121A /* PNModeSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeSheet.swift; sourceTree = "<group>"; };
C353F8F8244809150011121A /* PNOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNOptionView.swift; sourceTree = "<group>"; };
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = "<group>"; };
@ -1372,6 +1371,7 @@
C35E8AA62485C85600ACB629 /* GeoLite2-Country-Blocks-IPv4.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "GeoLite2-Country-Blocks-IPv4.csv"; sourceTree = "<group>"; };
C35E8AAD2485E51D00ACB629 /* IP2Country.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IP2Country.swift; sourceTree = "<group>"; };
C3638C0424C7F0B500AF29BC /* LK002RemoveFriendRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LK002RemoveFriendRequests.swift; sourceTree = "<group>"; };
C369549C24D27A3500CEB4E3 /* MultiDeviceRemovalSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiDeviceRemovalSheet.swift; sourceTree = "<group>"; };
C3AA6BB824CE8F1B002358B6 /* Migrating Translations from Android.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Migrating Translations from Android.md"; sourceTree = "<group>"; };
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
C3DFFAC523E96F0D0058DAF8 /* Sheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sheet.swift; sourceTree = "<group>"; };
@ -2710,12 +2710,12 @@
B85357C423A1F13800AAF6CD /* LinkDeviceVC.swift */,
B85357C623A1FB5100AAF6CD /* LinkDeviceVCDelegate.swift */,
B86BD08323399ACF000F5AE3 /* Modal.swift */,
C369549C24D27A3500CEB4E3 /* MultiDeviceRemovalSheet.swift */,
B80A579E23DFF1F300876683 /* NewClosedGroupVC.swift */,
B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */,
B894D0742339EDCF00B4D94D /* NukeDataModal.swift */,
C3DFFAC723E970080058DAF8 /* OpenGroupSuggestionSheet.swift */,
B879D448247E1BE300DB3608 /* PathVC.swift */,
C353F8F6244808E90011121A /* PNModeSheet.swift */,
C3548F0524456447009433A8 /* PNModeVC.swift */,
B886B4A62398B23E00211ABE /* QRCodeVC.swift */,
B82B408B239A068800A248E7 /* RegisterVC.swift */,
@ -3801,7 +3801,6 @@
4C4AEC4520EC343B0020E72B /* DismissableTextField.swift in Sources */,
4CB5F26720F6E1E2004D1B42 /* MenuActionsViewController.swift in Sources */,
3496955E219B605E00DCFE74 /* PhotoLibrary.swift in Sources */,
C353F8F7244808E90011121A /* PNModeSheet.swift in Sources */,
45D231771DC7E8F10034FA89 /* SessionResetJob.swift in Sources */,
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */,
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */,
@ -3848,6 +3847,7 @@
4C21D5D8223AC60F00EF8A77 /* PhotoCapture.swift in Sources */,
4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */,
4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */,
C369549D24D27A3500CEB4E3 /* MultiDeviceRemovalSheet.swift in Sources */,
34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */,
B8CCF639239721E20091D419 /* TabBar.swift in Sources */,
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,

View File

@ -5,9 +5,9 @@
<key>BuildDetails</key>
<dict>
<key>CarthageVersion</key>
<string>0.34.0</string>
<string>0.35.0</string>
<key>OSXVersion</key>
<string>10.15.5</string>
<string>10.15.6</string>
<key>WebRTCCommit</key>
<string>1445d719bf05280270e9f77576f80f973fd847f8 M73</string>
</dict>

View File

@ -179,12 +179,16 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
isViewVisible = true
let hasSeenPNModeSheet = UserDefaults.standard[.hasSeenPNModeSheet]
if !hasSeenPNModeSheet {
let pnModeSheet = PNModeSheet()
pnModeSheet.modalPresentationStyle = .overFullScreen
pnModeSheet.modalTransitionStyle = .crossDissolve
present(pnModeSheet, animated: true, completion: nil)
let hasSeenMultiDeviceRemovalSheet = UserDefaults.standard[.hasSeenMultiDeviceRemovalSheet]
if !hasSeenMultiDeviceRemovalSheet {
let _ = FileServerAPI.getDeviceLinks(associatedWith: getUserHexEncodedPublicKey()).done(on: DispatchQueue.main) { [weak self] deviceLinks in
guard !deviceLinks.isEmpty else { return }
let multiDeviceRemovalSheet = MultiDeviceRemovalSheet()
multiDeviceRemovalSheet.modalPresentationStyle = .overFullScreen
multiDeviceRemovalSheet.modalTransitionStyle = .crossDissolve
self?.present(multiDeviceRemovalSheet, animated: true, completion: nil)
}
UserDefaults.standard[.hasSeenMultiDeviceRemovalSheet] = true
}
UserDefaults.standard[.hasLaunchedOnce] = true
}
@ -214,21 +218,17 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
isObservingDatabase = isViewVisible && CurrentAppContext().isAppForegroundAndActive()
}
private func updateYDBThreadMapping() {
private func reload() {
AssertIsOnMainThread()
uiDatabaseConnection.beginLongLivedReadTransaction()
uiDatabaseConnection.read { transaction in
self.threads.update(with: transaction)
}
}
private func reload() {
AssertIsOnMainThread()
updateYDBThreadMapping()
threadViewModelCache.removeAll()
tableView.reloadData()
emptyStateView.isHidden = (threadCount != 0)
}
@objc private func handleYapDatabaseModifiedNotification(_ notification: Notification) {
AssertIsOnMainThread()
let notifications = uiDatabaseConnection.beginLongLivedReadTransaction()
@ -244,17 +244,13 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
}
return
}
// Guard for changes made in Notification Service Extension
// Crashes may happen if there is some modification in NSE
// The YapDBModificationNotification cannot cross process
// So the thread mapping won't update itself if DB modification happened in other process like NSE
// With these code we can sync the mapping before asking for changes from YapDB
if (notifications.count > 0) {
if let firstChangeset = notifications[0].userInfo {
let firstSnapshot = firstChangeset[YapDatabaseSnapshotKey] as! UInt64
if (self.threads.snapshotOfLastUpdate != firstSnapshot - 1) {
reload()
return
// If changes were made in a different process (e.g. the Notification Service Extension) the thread mapping can be out of date
// at this point, causing the app to crash. The code below prevents that by force syncing the database before proceeding.
if notifications.count > 0 {
if let firstChangeSet = notifications[0].userInfo {
let firstSnapshot = firstChangeSet[YapDatabaseSnapshotKey] as! UInt64
if threads.snapshotOfLastUpdate != firstSnapshot - 1 {
return reload()
}
}
}

View File

@ -59,11 +59,11 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
// Set up link button container
let linkButtonContainer = UIView()
linkButtonContainer.set(.height, to: Values.onboardingButtonBottomOffset)
linkButtonContainer.addSubview(linkButton)
linkButton.pin(.leading, to: .leading, of: linkButtonContainer, withInset: Values.massiveSpacing)
linkButton.pin(.top, to: .top, of: linkButtonContainer)
linkButtonContainer.pin(.trailing, to: .trailing, of: linkButton, withInset: Values.massiveSpacing)
linkButtonContainer.pin(.bottom, to: .bottom, of: linkButton, withInset: isIPhone5OrSmaller ? 6 : 10)
// linkButtonContainer.addSubview(linkButton)
// linkButton.pin(.leading, to: .leading, of: linkButtonContainer, withInset: Values.massiveSpacing)
// linkButton.pin(.top, to: .top, of: linkButtonContainer)
// linkButtonContainer.pin(.trailing, to: .trailing, of: linkButton, withInset: Values.massiveSpacing)
// linkButtonContainer.pin(.bottom, to: .bottom, of: linkButton, withInset: isIPhone5OrSmaller ? 6 : 10)
// Set up button stack view
let buttonStackView = UIStackView(arrangedSubviews: [ registerButton, restoreButton ])
buttonStackView.axis = .vertical

View File

@ -0,0 +1,93 @@
import PromiseKit
final class MultiDeviceRemovalSheet : Sheet {
private lazy var removalDate: Date = {
let calendar = Calendar(identifier: .gregorian)
let timezone = TimeZone(identifier: "Australia/Melbourne")
let components = DateComponents(calendar: calendar, timeZone: timezone, year: 2020, month: 8, day: 6, hour: 17)
return calendar.date(from: components)!
}()
private lazy var removalDateDescription: String = {
let formatter = DateFormatter()
formatter.dateFormat = "MMMM d"
return formatter.string(from: removalDate)
}()
private lazy var explanation: String = {
if UserDefaults.standard[.masterHexEncodedPublicKey] != nil {
let format = """
Youre seeing this because this is a secondary device in a multi-device setup. To improve reliability and stability, weve decided to temporarily disable Sessions multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on %@.
To read more about this change, visit the Session FAQ at getsession.org/faq.
"""
return String(format: format, removalDateDescription)
} else {
let format = """
Youre seeing this because you have a secondary device linked to your Session ID. To improve reliability and stability, weve decided to temporarily disable Sessions multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on %@.
To read more about this change, visit the Session FAQ at getsession.org/faq
"""
return String(format: format, removalDateDescription)
}
}()
private lazy var attributedExplanation: NSAttributedString = {
let result = NSMutableAttributedString(string: explanation)
result.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.smallFontSize), range: (explanation as NSString).range(of: removalDateDescription))
result.addAttribute(.foregroundColor, value: Colors.accent, range: (explanation as NSString).range(of: removalDateDescription))
result.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.smallFontSize), range: (explanation as NSString).range(of: "getsession.org/faq"))
result.addAttribute(.foregroundColor, value: Colors.accent, range: (explanation as NSString).range(of: "getsession.org/faq"))
return result
}()
private lazy var explanationLabel: UILabel = {
let result = UILabel()
result.textColor = Colors.text
result.font = .systemFont(ofSize: Values.smallFontSize)
result.attributedText = attributedExplanation
result.numberOfLines = 0
result.lineBreakMode = .byWordWrapping
return result
}()
override func populateContentView() {
// Set up title label
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
titleLabel.text = "Changes to Multi-Device"
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
// Set up explanation label
explanationLabel.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleExplanationLabelTapped))
explanationLabel.addGestureRecognizer(tapGestureRecognizer)
// Set up OK button
let okButton = Button(style: .prominentOutline, size: .large)
okButton.set(.width, to: 240)
okButton.setTitle(NSLocalizedString("OK", comment: ""), for: UIControl.State.normal)
okButton.addTarget(self, action: #selector(close), for: UIControl.Event.touchUpInside)
// Set up main stack view
let stackView = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel, okButton ])
stackView.axis = .vertical
stackView.spacing = Values.veryLargeSpacing
stackView.alignment = .center
// Set up constraints
contentView.addSubview(stackView)
stackView.pin(.leading, to: .leading, of: contentView, withInset: Values.veryLargeSpacing)
stackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing)
contentView.pin(.trailing, to: .trailing, of: stackView, withInset: Values.veryLargeSpacing)
contentView.pin(.bottom, to: .bottom, of: stackView, withInset: Values.veryLargeSpacing + overshoot)
}
@objc private func handleExplanationLabelTapped(_ tapGestureRecognizer: UITapGestureRecognizer) {
let range = (explanationLabel.text! as NSString).range(of: "getsession.org/faq")
let touchInExplanationLabelCoordinates = tapGestureRecognizer.location(in: explanationLabel)
let characterIndex = explanationLabel.characterIndex(for: touchInExplanationLabelCoordinates)
guard range.contains(characterIndex) else { return }
let url = URL(string: "https://getsession.org/faq")!
UIApplication.shared.open(url)
}
}

View File

@ -1,89 +0,0 @@
import PromiseKit
final class PNModeSheet : Sheet, OptionViewDelegate {
private var optionViews: [OptionView] {
[ apnsOptionView, backgroundPollingOptionView ]
}
private var selectedOptionView: OptionView? {
return optionViews.first { $0.isSelected }
}
// MARK: Components
private lazy var apnsOptionView = OptionView(title: NSLocalizedString("Apple Push Notification Service", comment: ""), explanation: NSLocalizedString("Session will use the Apple Push Notification service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.", comment: ""), delegate: self, isRecommended: true)
private lazy var backgroundPollingOptionView = OptionView(title: NSLocalizedString("Background Polling", comment: ""), explanation: NSLocalizedString("Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.", comment: ""), delegate: self)
// MARK: Lifecycle
override func populateContentView() {
// Set up title label
let titleLabel = UILabel()
titleLabel.textColor = Colors.text
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
titleLabel.text = NSLocalizedString("Push Notifications", comment: "")
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .byWordWrapping
// Set up explanation label
let explanationLabel = UILabel()
explanationLabel.textColor = Colors.text
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
explanationLabel.text = NSLocalizedString("Session now features two ways to handle push notifications. Make sure to read the descriptions carefully before you choose.", comment: "")
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
// Set up options stack view
let optionsStackView = UIStackView(arrangedSubviews: optionViews)
optionsStackView.axis = .vertical
optionsStackView.spacing = Values.smallSpacing
optionsStackView.alignment = .fill
// Set up confirm button
let confirmButton = Button(style: .prominentOutline, size: .medium)
confirmButton.set(.width, to: 240)
confirmButton.setTitle(NSLocalizedString("Confirm", comment: ""), for: UIControl.State.normal)
confirmButton.addTarget(self, action: #selector(confirm), for: UIControl.Event.touchUpInside)
// Set up dismiss button
let skipButton = Button(style: .regular, size: .medium)
skipButton.set(.width, to: 240)
skipButton.setTitle(NSLocalizedString("Skip", comment: ""), for: UIControl.State.normal)
skipButton.addTarget(self, action: #selector(close), for: UIControl.Event.touchUpInside)
// Set up button stack view
let bottomStackView = UIStackView(arrangedSubviews: [ confirmButton, skipButton ])
bottomStackView.axis = .vertical
bottomStackView.spacing = isIPhone5OrSmaller ? Values.smallSpacing : Values.mediumSpacing
bottomStackView.alignment = .fill
// Set up main stack view
let stackView = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel, optionsStackView, bottomStackView ])
stackView.axis = .vertical
stackView.spacing = isIPhone5OrSmaller ? 12 : Values.largeSpacing
stackView.alignment = .center
// Set up constraints
contentView.addSubview(stackView)
stackView.pin(.leading, to: .leading, of: contentView, withInset: isIPhone5OrSmaller ? Values.mediumSpacing : Values.largeSpacing)
stackView.pin(.top, to: .top, of: contentView, withInset: isIPhone5OrSmaller ? Values.mediumSpacing : Values.largeSpacing)
contentView.pin(.trailing, to: .trailing, of: stackView, withInset: isIPhone5OrSmaller ? Values.mediumSpacing : Values.largeSpacing)
contentView.pin(.bottom, to: .bottom, of: stackView, withInset: (isIPhone5OrSmaller ? Values.mediumSpacing : Values.veryLargeSpacing) + overshoot)
}
// MARK: Interaction
func optionViewDidActivate(_ optionView: OptionView) {
optionViews.filter { $0 != optionView }.forEach { $0.isSelected = false }
}
@objc private func confirm() {
guard selectedOptionView != nil else {
let title = NSLocalizedString("Please Pick an Option", comment: "")
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
return present(alert, animated: true, completion: nil)
}
UserDefaults.standard[.isUsingFullAPNs] = (selectedOptionView == apnsOptionView)
let syncTokensJob = SyncPushTokensJob(accountManager: AppEnvironment.shared.accountManager, preferences: Environment.shared.preferences)
syncTokensJob.uploadOnlyIfStale = false
let _: Promise<Void> = syncTokensJob.run()
close()
}
override func close() {
UserDefaults.standard[.hasSeenPNModeSheet] = true
super.close()
}
}

View File

@ -89,7 +89,7 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
return present(alert, animated: true, completion: nil)
}
UserDefaults.standard[.isUsingFullAPNs] = (selectedOptionView == apnsOptionView)
UserDefaults.standard[.hasSeenPNModeSheet] = true // Shouldn't be shown to users who've done the new onboarding
UserDefaults.standard[.hasSeenMultiDeviceRemovalSheet] = true
TSAccountManager.sharedInstance().didRegister()
let homeVC = HomeVC()
navigationController!.setViewControllers([ homeVC ], animated: true)

View File

@ -167,8 +167,8 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
]
let isMasterDevice = UserDefaults.standard.isMasterDevice
if isMasterDevice {
result.append(getSeparator())
result.append(getSettingButton(withTitle: NSLocalizedString("vc_settings_devices_button_title", comment: ""), color: Colors.text, action: #selector(showLinkedDevices)))
// result.append(getSeparator())
// result.append(getSettingButton(withTitle: NSLocalizedString("vc_settings_devices_button_title", comment: ""), color: Colors.text, action: #selector(showLinkedDevices)))
result.append(getSeparator())
result.append(getSettingButton(withTitle: NSLocalizedString("vc_settings_recovery_phrase_button_title", comment: ""), color: Colors.text, action: #selector(showSeed)))
}

View File

@ -157,7 +157,6 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
- (BOOL)isMainAppAndActive
{
if (![NSThread isMainThread]) { return NO; }
return [UIApplication sharedApplication].applicationState == UIApplicationStateActive;
}

View File

@ -5,8 +5,8 @@ public enum LKUserDefaults {
public enum Bool : Swift.String {
case hasLaunchedOnce
case hasSeenGIFMetadataWarning
case hasSeenMultiDeviceRemovalSheet
case hasSeenOpenGroupSuggestionSheet
case hasSeenPNModeSheet
case hasViewedSeed
/// Whether the device was unlinked as a slave device (used to notify the user on the landing screen).
case wasUnlinked