TF-1368 Cloud info window

This commit is contained in:
Zbigniew Cisiński 2023-11-19 18:51:57 +01:00
parent 45aab4ca03
commit 9cfa59738e
18 changed files with 6191 additions and 17 deletions

View File

@ -325,6 +325,7 @@
C25C91CF2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91CE2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift */; }; C25C91CF2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91CE2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift */; };
C25C91D52B0A632500E58729 /* IntroductionNavigationFlowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91D42B0A632500E58729 /* IntroductionNavigationFlowController.swift */; }; C25C91D52B0A632500E58729 /* IntroductionNavigationFlowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91D42B0A632500E58729 /* IntroductionNavigationFlowController.swift */; };
C25C91D72B0A6DE600E58729 /* IntroductionModuleInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91D62B0A6DE600E58729 /* IntroductionModuleInteractor.swift */; }; C25C91D72B0A6DE600E58729 /* IntroductionModuleInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91D62B0A6DE600E58729 /* IntroductionModuleInteractor.swift */; };
C25C91DA2B0A75B100E58729 /* IntroductionCloudInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25C91D92B0A75B100E58729 /* IntroductionCloudInfoViewController.swift */; };
C25D5E782A64908200CA359B /* CameraLastPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25D5E772A64908200CA359B /* CameraLastPass.swift */; }; C25D5E782A64908200CA359B /* CameraLastPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25D5E772A64908200CA359B /* CameraLastPass.swift */; };
C25E898E2663DF9700A60CE5 /* TokensSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25E898D2663DF9700A60CE5 /* TokensSectionHeader.swift */; }; C25E898E2663DF9700A60CE5 /* TokensSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25E898D2663DF9700A60CE5 /* TokensSectionHeader.swift */; };
C25E89902663F11900A60CE5 /* SectionData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25E898F2663F11900A60CE5 /* SectionData.swift */; }; C25E89902663F11900A60CE5 /* SectionData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25E898F2663F11900A60CE5 /* SectionData.swift */; };
@ -1683,6 +1684,7 @@
C25C91CE2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddingServiceManuallyNavigationFlowController.swift; sourceTree = "<group>"; }; C25C91CE2B08E84800E58729 /* AddingServiceManuallyNavigationFlowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddingServiceManuallyNavigationFlowController.swift; sourceTree = "<group>"; };
C25C91D42B0A632500E58729 /* IntroductionNavigationFlowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroductionNavigationFlowController.swift; sourceTree = "<group>"; }; C25C91D42B0A632500E58729 /* IntroductionNavigationFlowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroductionNavigationFlowController.swift; sourceTree = "<group>"; };
C25C91D62B0A6DE600E58729 /* IntroductionModuleInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroductionModuleInteractor.swift; sourceTree = "<group>"; }; C25C91D62B0A6DE600E58729 /* IntroductionModuleInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroductionModuleInteractor.swift; sourceTree = "<group>"; };
C25C91D92B0A75B100E58729 /* IntroductionCloudInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntroductionCloudInfoViewController.swift; sourceTree = "<group>"; };
C25D5E752A64863000CA359B /* Code+LastPass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Code+LastPass.swift"; sourceTree = "<group>"; }; C25D5E752A64863000CA359B /* Code+LastPass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Code+LastPass.swift"; sourceTree = "<group>"; };
C25D5E772A64908200CA359B /* CameraLastPass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraLastPass.swift; sourceTree = "<group>"; }; C25D5E772A64908200CA359B /* CameraLastPass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraLastPass.swift; sourceTree = "<group>"; };
C25E898D2663DF9700A60CE5 /* TokensSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokensSectionHeader.swift; sourceTree = "<group>"; }; C25E898D2663DF9700A60CE5 /* TokensSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokensSectionHeader.swift; sourceTree = "<group>"; };
@ -4544,6 +4546,7 @@
C25C91D22B0A4FDA00E58729 /* View */ = { C25C91D22B0A4FDA00E58729 /* View */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
C25C91D82B0A759700E58729 /* CloudInfo */,
C2BD85E326403EE80087D087 /* IntroductionViewController.swift */, C2BD85E326403EE80087D087 /* IntroductionViewController.swift */,
C2F6BAFF264869B7002A9747 /* IntroductionCommons.swift */, C2F6BAFF264869B7002A9747 /* IntroductionCommons.swift */,
C2F6BB012648826F002A9747 /* Components */, C2F6BB012648826F002A9747 /* Components */,
@ -4560,6 +4563,14 @@
path = Interactor; path = Interactor;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
C25C91D82B0A759700E58729 /* CloudInfo */ = {
isa = PBXGroup;
children = (
C25C91D92B0A75B100E58729 /* IntroductionCloudInfoViewController.swift */,
);
path = CloudInfo;
sourceTree = "<group>";
};
C25E8996266402C500A60CE5 /* Section */ = { C25E8996266402C500A60CE5 /* Section */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -7996,6 +8007,7 @@
C240485E27654C5F0076376E /* ImporterEnterPasswordFlowController.swift in Sources */, C240485E27654C5F0076376E /* ImporterEnterPasswordFlowController.swift in Sources */,
C2A7944D27F795E900E5C641 /* BrowserExtensionPairedService.swift in Sources */, C2A7944D27F795E900E5C641 /* BrowserExtensionPairedService.swift in Sources */,
C287D4FB276A92460001B272 /* AppSecurityExtensions.swift in Sources */, C287D4FB276A92460001B272 /* AppSecurityExtensions.swift in Sources */,
C25C91DA2B0A75B100E58729 /* IntroductionCloudInfoViewController.swift in Sources */,
C2CC0A4C29D0D4FC00677A7B /* ExternalImportService.swift in Sources */, C2CC0A4C29D0D4FC00677A7B /* ExternalImportService.swift in Sources */,
C244718825F4F6900024B4C5 /* ComposeServiceFormRowTitleLabel.swift in Sources */, C244718825F4F6900024B4C5 /* ComposeServiceFormRowTitleLabel.swift in Sources */,
C2D587362650549700D9C4BD /* IntroductionPage4View.swift in Sources */, C2D587362650549700D9C4BD /* IntroductionPage4View.swift in Sources */,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
{
"images" : [
{
"filename" : "CloudBackupLight.pdf",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "CloudBackupDark.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}

View File

@ -46,6 +46,7 @@ internal enum Asset {
internal static let pairingOval3 = ImageAsset(name: "PairingOval3") internal static let pairingOval3 = ImageAsset(name: "PairingOval3")
internal static let pairingOval4 = ImageAsset(name: "PairingOval4") internal static let pairingOval4 = ImageAsset(name: "PairingOval4")
internal static let pairingSuccessful = ImageAsset(name: "PairingSuccessful") internal static let pairingSuccessful = ImageAsset(name: "PairingSuccessful")
internal static let cloudBackup = ImageAsset(name: "CloudBackup")
internal static let copyIcon = ImageAsset(name: "CopyIcon") internal static let copyIcon = ImageAsset(name: "CopyIcon")
internal static let deleteCodeButton = ImageAsset(name: "DeleteCodeButton") internal static let deleteCodeButton = ImageAsset(name: "DeleteCodeButton")
internal static let deleteForeverIcon = ImageAsset(name: "DeleteForeverIcon") internal static let deleteForeverIcon = ImageAsset(name: "DeleteForeverIcon")

View File

@ -61,7 +61,13 @@ extension IntroductionFlowController: IntroductionFlowControlling {
} }
func toCloudInfo() { func toCloudInfo() {
print("SHOW") let vc = IntroductionCloudInfoViewController()
vc.close = { [weak self] in
self?._viewController.dismiss(animated: true)
}
vc.configureAsModal()
_viewController.present(vc, animated: true)
} }
func toTOS() { func toTOS() {

View File

@ -0,0 +1,92 @@
//
// This file is part of the 2FAS iOS app (https://github.com/twofas/2fas-ios)
// Copyright © 2023 Two Factor Authentication Service, Inc.
// Contributed by Zbigniew Cisiński. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>
//
import UIKit
import SwiftUI
import Common
final class IntroductionCloudInfoViewController: UIViewController {
var close: Callback?
override func viewDidLoad() {
super.viewDidLoad()
let vc = UIHostingController(rootView: IntroductionCloudInfoView(close: close))
vc.willMove(toParent: self)
addChild(vc)
view.addSubview(vc.view)
vc.view.pinToParent()
vc.view.backgroundColor = Theme.Colors.Fill.System.third
vc.didMove(toParent: self)
}
}
private struct IntroductionCloudInfoView: View {
let close: Callback?
private let spacing: CGFloat = Theme.Metrics.doubleSpacing
private let image = Asset.cloudBackup.image
var body: some View {
VStack(alignment: .center, spacing: Theme.Metrics.standardSpacing) {
VStack(spacing: spacing) {
Spacer()
Image(uiImage: image)
.frame(width: image.size.width, height: image.size.height)
}
.frame(maxHeight: .infinity, alignment: .center)
VStack(spacing: spacing) {
Text(T.Introduction.backupIcloudTitle)
.font(.title2)
.fontWeight(.bold)
.multilineTextAlignment(.center)
.padding(.top, Theme.Metrics.standardMargin)
if let desc = try? AttributedString(
markdown: T.Introduction.backupIcloudDescription,
options: AttributedString.MarkdownParsingOptions(
interpretedSyntax: .inlineOnlyPreservingWhitespace
)
) {
Text(desc)
.font(.body)
.multilineTextAlignment(.center)
.frame(alignment: .top)
}
}
.frame(alignment: .center)
.layoutPriority(1)
VStack(spacing: 0) {
Button {
close?()
} label: {
Text(T.Commons.ok)
.frame(minWidth: 0, maxWidth: .infinity)
}
.buttonStyle(RoundedFilledButtonStyle())
.padding(EdgeInsets(top: 0, leading: 0, bottom: spacing, trailing: 0))
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
}
.frame(maxWidth: Theme.Metrics.componentWidth)
.navigationBarHidden(true)
}
}

View File

@ -34,7 +34,6 @@ final class IntroductionViewController: UIViewController {
private let backButton = CustomBackButton() private let backButton = CustomBackButton()
private var mainButtonAdditionalAction: Callback? private var mainButtonAdditionalAction: Callback?
private var bottomAnchor: NSLayoutConstraint?
var presenter: IntroductionPresenter! var presenter: IntroductionPresenter!
@ -69,12 +68,6 @@ final class IntroductionViewController: UIViewController {
mainActionButton.heightAnchor.constraint(equalToConstant: Theme.Metrics.buttonHeight) mainActionButton.heightAnchor.constraint(equalToConstant: Theme.Metrics.buttonHeight)
]) ])
let bottomAnchor = mainActionButton
.bottomAnchor
.constraint(equalTo: view.safeBottomAnchor, constant: -2 * singleMargin - Theme.Metrics.buttonHeight)
self.bottomAnchor = bottomAnchor
bottomAnchor.isActive = true
view.addSubview(additionalActionButton, with: [ view.addSubview(additionalActionButton, with: [
additionalActionButton.topAnchor.constraint(equalTo: mainActionButton.bottomAnchor, constant: singleMargin), additionalActionButton.topAnchor.constraint(equalTo: mainActionButton.bottomAnchor, constant: singleMargin),
additionalActionButton.leadingAnchor.constraint( additionalActionButton.leadingAnchor.constraint(
@ -101,7 +94,6 @@ final class IntroductionViewController: UIViewController {
additionalActionButton.apply(MainContainerButtonStyling.textOnly.value) additionalActionButton.apply(MainContainerButtonStyling.textOnly.value)
additionalActionButton.alpha = 0 additionalActionButton.alpha = 0
additionalActionButton.action = { [weak self] in self?.additionalActionButtonAction() } additionalActionButton.action = { [weak self] in self?.additionalActionButtonAction() }
additionalActionButton.isHidden = true
scrollView.didChangePage = { [weak self] in scrollView.didChangePage = { [weak self] in
self?.presenter.handleDidMoveToPage($0) self?.presenter.handleDidMoveToPage($0)
@ -149,20 +141,12 @@ extension IntroductionViewController: IntroductionViewControlling {
if let additionalButtonTitle = scrollView.container.additionalButtonTitle(for: num) { if let additionalButtonTitle = scrollView.container.additionalButtonTitle(for: num) {
additionalActionButton.update(title: additionalButtonTitle) additionalActionButton.update(title: additionalButtonTitle)
additionalActionButton.alpha = 0
additionalActionButton.isHidden = false
UIView.animate(withDuration: IntroductionCommons.shortAnimationTiming) { UIView.animate(withDuration: IntroductionCommons.shortAnimationTiming) {
self.additionalActionButton.alpha = 1 self.additionalActionButton.alpha = 1
} completion: { _ in
self.bottomAnchor?.isActive = false
} }
} else { } else {
additionalActionButton.alpha = 1
UIView.animate(withDuration: IntroductionCommons.shortAnimationTiming) { UIView.animate(withDuration: IntroductionCommons.shortAnimationTiming) {
self.additionalActionButton.alpha = 0 self.additionalActionButton.alpha = 0
} completion: { _ in
self.additionalActionButton.isHidden = true
self.bottomAnchor?.isActive = true
} }
} }