mirror of
https://github.com/twofas/2fas-ios.git
synced 2024-11-22 02:10:19 +01:00
Merge branch 'feature/TF-1261_LastSyncDate' into release/v5.3.5
# Conflicts: # TwoFAS/TwoFAS/Root/Modules/Main/Interactor/MainModuleInteractor.swift # TwoFAS/TwoFAS/Root/Modules/Main/Presenter/MainPresenter.swift
This commit is contained in:
commit
9b192591c8
@ -22,6 +22,8 @@ import Foundation
|
||||
public extension Notification.Name {
|
||||
static let servicesWereUpdated = Notification.Name("servicesWereUpdatedNotification")
|
||||
static let sectionsWereUpdated = Notification.Name("sectionsWereUpdatedNotification")
|
||||
static let syncCompletedSuccessfuly = Notification.Name("syncCompletedSuccessfuly")
|
||||
static let clearSyncCompletedSuccessfuly = Notification.Name("clearSyncCompletedSuccessfuly")
|
||||
}
|
||||
|
||||
public extension Notification {
|
||||
|
@ -42,6 +42,10 @@ public protocol CloudBackupStateInteracting: AnyObject {
|
||||
func clearBackup()
|
||||
|
||||
func synchronizeBackup()
|
||||
|
||||
var successSyncDate: Date? { get }
|
||||
func saveSuccessSyncDate()
|
||||
func clearSavesuccessSync()
|
||||
}
|
||||
|
||||
/// Use one instance per use case
|
||||
@ -80,6 +84,10 @@ extension CloudBackupStateInteractor: CloudBackupStateInteracting {
|
||||
var isBackupEnabled: Bool { isEnabled }
|
||||
var isBackupAvailable: Bool { isAvailable }
|
||||
|
||||
var successSyncDate: Date? {
|
||||
mainRepository.successSyncDate
|
||||
}
|
||||
|
||||
func startMonitoring() {
|
||||
Log("CloudBackupStateInteractor - start monitoring, listenerID: \(listenerID)", module: .interactor)
|
||||
saveStates()
|
||||
@ -138,6 +146,16 @@ extension CloudBackupStateInteractor: CloudBackupStateInteracting {
|
||||
Log("CloudBackupStateInteractor - synchronizeBackup", module: .interactor)
|
||||
mainRepository.synchronizeBackup()
|
||||
}
|
||||
|
||||
func saveSuccessSyncDate() {
|
||||
Log("CloudBackupStateInteractor - saveSuccessSync", module: .interactor)
|
||||
mainRepository.saveSuccessSyncDate(Date())
|
||||
}
|
||||
|
||||
func clearSavesuccessSync() {
|
||||
Log("CloudBackupStateInteractor - clearSavesuccessSync", module: .interactor)
|
||||
mainRepository.saveSuccessSyncDate(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private extension CloudBackupStateInteractor {
|
||||
|
@ -122,6 +122,7 @@ protocol MainRepository: AnyObject {
|
||||
// MARK: - Cloud
|
||||
var secretSyncError: ((String) -> Void)? { get set }
|
||||
var isCloudBackupConnected: Bool { get }
|
||||
var successSyncDate: Date? { get }
|
||||
var cloudCurrentState: CloudState { get }
|
||||
func registerForCloudStateChanges(_ listener: @escaping CloudStateListener, id: CloudStateListenerID)
|
||||
func unregisterForCloudStageChanges(with id: CloudStateListenerID)
|
||||
@ -133,6 +134,7 @@ protocol MainRepository: AnyObject {
|
||||
userInfo: [AnyHashable: Any],
|
||||
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
|
||||
)
|
||||
func saveSuccessSyncDate(_ date: Date?)
|
||||
|
||||
// MARK: - Import
|
||||
var fileURL: URL? { get set }
|
||||
|
@ -44,6 +44,10 @@ public enum CloudState: Equatable {
|
||||
}
|
||||
|
||||
extension MainRepositoryImpl {
|
||||
var successSyncDate: Date? {
|
||||
userDefaultsRepository.successSyncDate
|
||||
}
|
||||
|
||||
var secretSyncError: ((String) -> Void)? {
|
||||
get {
|
||||
cloudHandler.secretSyncError
|
||||
@ -89,6 +93,10 @@ extension MainRepositoryImpl {
|
||||
) {
|
||||
SyncInstance.didReceiveRemoteNotification(userInfo: userInfo, fetchCompletionHandler: completionHandler)
|
||||
}
|
||||
|
||||
func saveSuccessSyncDate(_ date: Date?) {
|
||||
userDefaultsRepository.saveSuccessSyncDate(date)
|
||||
}
|
||||
}
|
||||
|
||||
private extension MainRepositoryImpl {
|
||||
|
@ -97,4 +97,7 @@ protocol UserDefaultsRepository: AnyObject {
|
||||
var exchangeToken: String? { get }
|
||||
func setExchangeToken(_ key: String)
|
||||
func clearExchangeToken()
|
||||
|
||||
var successSyncDate: Date? { get }
|
||||
func saveSuccessSyncDate(_ date: Date?)
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ final class UserDefaultsRepositoryImpl: UserDefaultsRepository {
|
||||
case mainMenuPortraitCollapsed
|
||||
case mainMenuLandscapeCollapsed
|
||||
case dateOfFirstRun
|
||||
case syncSuccessDate
|
||||
}
|
||||
private let userDefaults = UserDefaults()
|
||||
private let sharedDefaults = UserDefaults(suiteName: Config.suiteName)!
|
||||
@ -279,6 +280,16 @@ final class UserDefaultsRepositoryImpl: UserDefaultsRepository {
|
||||
userDefaults.bool(forKey: Keys.introductionWasShown.rawValue)
|
||||
}
|
||||
|
||||
// MARK: - Sync success
|
||||
|
||||
var successSyncDate: Date? {
|
||||
userDefaults.object(forKey: Keys.syncSuccessDate.rawValue) as? Date
|
||||
}
|
||||
func saveSuccessSyncDate(_ date: Date?) {
|
||||
userDefaults.set(date, forKey: Keys.syncSuccessDate.rawValue)
|
||||
userDefaults.synchronize()
|
||||
}
|
||||
|
||||
// MARK: - View Path
|
||||
|
||||
func clearViewPath() {
|
||||
|
@ -85,6 +85,8 @@ final class CloudHandler: CloudHandlerType {
|
||||
private let itemHandlerMigrationProxy: ItemHandlerMigrationProxy
|
||||
private let cloudKit: CloudKit
|
||||
|
||||
private let notificationCenter = NotificationCenter.default
|
||||
|
||||
private var isClearing = false
|
||||
|
||||
private var listeners: [String: CloudHandlerStateListener] = [:]
|
||||
@ -313,6 +315,7 @@ final class CloudHandler: CloudHandlerType {
|
||||
private func setDisabled() {
|
||||
Log("Cloud Handler - Set Disabled", module: .cloudSync)
|
||||
ConstStorage.cloudEnabled = false
|
||||
notificationCenter.post(name: .clearSyncCompletedSuccessfuly, object: nil)
|
||||
}
|
||||
|
||||
private var isEnabled: Bool { ConstStorage.cloudEnabled }
|
||||
@ -344,6 +347,8 @@ final class CloudHandler: CloudHandlerType {
|
||||
|
||||
if isClearing {
|
||||
clearBackup()
|
||||
} else {
|
||||
notificationCenter.post(name: .syncCompletedSuccessfuly, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@ protocol MainModuleInteracting: AnyObject {
|
||||
func clearImportedFileURL()
|
||||
|
||||
func savePIN(_ PIN: String, ofType pinType: PINType)
|
||||
func saveSuccessSync()
|
||||
func clearSavesuccessSync()
|
||||
|
||||
// MARK: - New app version
|
||||
func checkForNewAppVersion(completion: @escaping (URL?) -> Void)
|
||||
@ -111,6 +113,14 @@ extension MainModuleInteractor: MainModuleInteracting {
|
||||
func savePIN(_ PIN: String, ofType pinType: PINType) {
|
||||
protectionInteractor.savePIN(PIN, typeOfPIN: pinType)
|
||||
}
|
||||
|
||||
func saveSuccessSync() {
|
||||
cloudBackupStateInteractor.saveSuccessSyncDate()
|
||||
}
|
||||
|
||||
func clearSavesuccessSync() {
|
||||
cloudBackupStateInteractor.clearSavesuccessSync()
|
||||
}
|
||||
|
||||
// MARK: - New app version
|
||||
|
||||
|
@ -84,6 +84,14 @@ final class MainPresenter {
|
||||
viewIsVisible()
|
||||
}
|
||||
|
||||
func handleSyncCompletedSuccessfuly() {
|
||||
interactor.saveSuccessSync()
|
||||
}
|
||||
|
||||
func handleClearSyncCompletedSuccessfuly() {
|
||||
interactor.clearSavesuccessSync()
|
||||
}
|
||||
|
||||
func handleSavePIN(_ PIN: String, pinType: PINType) {
|
||||
interactor.savePIN(PIN, ofType: pinType)
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ final class MainViewController: UIViewController {
|
||||
var presenter: MainPresenter!
|
||||
|
||||
private let settingsEventController = SettingsEventController()
|
||||
private let notificationCenter = NotificationCenter.default
|
||||
|
||||
var splitView: MainSplitViewController?
|
||||
|
||||
@ -48,66 +49,78 @@ final class MainViewController: UIViewController {
|
||||
}
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
notificationCenter.removeObserver(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension MainViewController {
|
||||
private func setupEvents() {
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(refreshAuthList),
|
||||
name: .pushNotificationRefreshAuthList,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(refreshAuthList),
|
||||
name: UIApplication.didBecomeActiveNotification,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(clearAuthList),
|
||||
name: UIApplication.willResignActiveNotification,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(authorizeFromApp),
|
||||
name: .pushNotificationAuthorizeFromApp,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(switchToSetupPIN),
|
||||
name: .switchToSetupPIN,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(switchToBrowserExtension),
|
||||
name: .switchToBrowserExtension,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(fileAwaitsOpening),
|
||||
name: .fileAwaitsOpening,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(tokensVisible),
|
||||
name: .tokensScreenIsVisible,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(tokensVisible),
|
||||
name: .userLoggedIn,
|
||||
object: nil
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(syncCompletedSuccessfuly),
|
||||
name: .syncCompletedSuccessfuly,
|
||||
object: nil
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
self,
|
||||
selector: #selector(clearSyncCompletedSuccessfuly),
|
||||
name: .clearSyncCompletedSuccessfuly,
|
||||
object: nil
|
||||
)
|
||||
}
|
||||
|
||||
@objc
|
||||
@ -151,6 +164,16 @@ extension MainViewController {
|
||||
private func tokensVisible() {
|
||||
presenter.handleViewIsVisible()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func syncCompletedSuccessfuly() {
|
||||
presenter.handleSyncCompletedSuccessfuly()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func clearSyncCompletedSuccessfuly() {
|
||||
presenter.handleClearSyncCompletedSuccessfuly()
|
||||
}
|
||||
}
|
||||
|
||||
extension MainViewController: MainViewControlling {
|
||||
|
@ -35,6 +35,8 @@ protocol BackupMenuModuleInteracting: AnyObject {
|
||||
|
||||
func toggleBackup()
|
||||
func clearBackup()
|
||||
|
||||
var syncSuccessDate: Date? { get }
|
||||
}
|
||||
|
||||
final class BackupMenuModuleInteractor {
|
||||
@ -102,6 +104,10 @@ extension BackupMenuModuleInteractor: BackupMenuModuleInteracting {
|
||||
func clearBackup() {
|
||||
cloudBackup.clearBackup()
|
||||
}
|
||||
|
||||
var syncSuccessDate: Date? {
|
||||
cloudBackup.successSyncDate
|
||||
}
|
||||
}
|
||||
|
||||
private extension BackupMenuModuleInteractor {
|
||||
|
@ -21,6 +21,15 @@ import Foundation
|
||||
|
||||
extension BackupMenuPresenter {
|
||||
func buildMenu() -> [BackupMenuSection] {
|
||||
var footer = T.Backup.sectionDescription
|
||||
let dateStr: String = {
|
||||
if let date = interactor.syncSuccessDate {
|
||||
return dateFormatter.string(from: date)
|
||||
}
|
||||
return "-"
|
||||
}()
|
||||
footer.append("\n\n\(T.backupSettingsSyncTitle): \(dateStr)")
|
||||
|
||||
let cloudBackup = BackupMenuSection(
|
||||
title: T.Backup.cloudBackup,
|
||||
cells: [
|
||||
@ -34,7 +43,7 @@ extension BackupMenuPresenter {
|
||||
)
|
||||
)
|
||||
],
|
||||
footer: T.Backup.sectionDescription
|
||||
footer: footer
|
||||
)
|
||||
|
||||
let exportEnabled = interactor.exportEnabled && interactor.isBackupAllowed
|
||||
|
@ -23,6 +23,12 @@ final class BackupMenuPresenter {
|
||||
weak var view: BackupMenuViewControlling?
|
||||
|
||||
private let flowController: BackupMenuFlowControlling
|
||||
var dateFormatter: DateFormatter = {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateStyle = .short
|
||||
dateFormatter.timeStyle = .short
|
||||
return dateFormatter
|
||||
}()
|
||||
let interactor: BackupMenuModuleInteracting
|
||||
|
||||
init(flowController: BackupMenuFlowControlling, interactor: BackupMenuModuleInteracting) {
|
||||
@ -30,7 +36,7 @@ final class BackupMenuPresenter {
|
||||
self.interactor = interactor
|
||||
interactor.reload = { [weak self] in self?.reload() }
|
||||
}
|
||||
|
||||
|
||||
func viewWillAppear() {
|
||||
interactor.startMonitoring()
|
||||
reload()
|
||||
@ -74,6 +80,10 @@ final class BackupMenuPresenter {
|
||||
func handleBecomeActive() {
|
||||
reload()
|
||||
}
|
||||
|
||||
func handleSyncSuccessDateUpdate() {
|
||||
reload()
|
||||
}
|
||||
}
|
||||
|
||||
private extension BackupMenuPresenter {
|
||||
|
@ -98,6 +98,12 @@ final class BackupMenuViewController: UIViewController {
|
||||
name: .refreshTabContent,
|
||||
object: nil
|
||||
)
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
selector: #selector(updateSyncSuccDate),
|
||||
name: .syncCompletedSuccessfuly,
|
||||
object: nil
|
||||
)
|
||||
|
||||
presenter.viewWillAppear()
|
||||
}
|
||||
@ -113,6 +119,11 @@ final class BackupMenuViewController: UIViewController {
|
||||
presenter.handleBecomeActive()
|
||||
}
|
||||
|
||||
@objc
|
||||
private func updateSyncSuccDate() {
|
||||
presenter.handleSyncSuccessDateUpdate()
|
||||
}
|
||||
|
||||
private func setupConstraints() {
|
||||
switch traitCollection.horizontalSizeClass {
|
||||
case .regular:
|
||||
|
Loading…
Reference in New Issue
Block a user