mirror of
https://github.com/twofas/2fas-ios.git
synced 2024-11-24 19:30:14 +01:00
TF-1368 Cloud info window
This commit is contained in:
parent
45aab4ca03
commit
9cfa59738e
@ -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 */,
|
||||||
|
3027
TwoFAS/TwoFAS/Other/Assets.xcassets/CloudBackup.imageset/CloudBackupDark.pdf
vendored
Normal file
3027
TwoFAS/TwoFAS/Other/Assets.xcassets/CloudBackup.imageset/CloudBackupDark.pdf
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3027
TwoFAS/TwoFAS/Other/Assets.xcassets/CloudBackup.imageset/CloudBackupLight.pdf
vendored
Normal file
3027
TwoFAS/TwoFAS/Other/Assets.xcassets/CloudBackup.imageset/CloudBackupLight.pdf
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
TwoFAS/TwoFAS/Other/Assets.xcassets/CloudBackup.imageset/Contents.json
vendored
Normal file
25
TwoFAS/TwoFAS/Other/Assets.xcassets/CloudBackup.imageset/Contents.json
vendored
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
@ -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")
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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() {
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user