Scan flows done
This commit is contained in:
parent
fcfca57eed
commit
e5e1eb6e1b
|
@ -65,6 +65,12 @@ public struct AddressBookContactView: View {
|
|||
}
|
||||
store.send(.onAppear)
|
||||
}
|
||||
.alert(
|
||||
store: store.scope(
|
||||
state: \.$alert,
|
||||
action: \.alert
|
||||
)
|
||||
)
|
||||
}
|
||||
.applyScreenBackground()
|
||||
.zashiBack()
|
||||
|
|
|
@ -85,6 +85,7 @@ public struct AddressBook {
|
|||
case deleteId(String)
|
||||
case deleteIdConfirmed
|
||||
case dismissAddContactRequired
|
||||
case dismissDeleteContactRequired
|
||||
case editId(String)
|
||||
case fetchedABContacts(AddressBookContacts, Bool)
|
||||
case fetchABContactsRequested
|
||||
|
@ -188,9 +189,9 @@ public struct AddressBook {
|
|||
state.deleteIdToConfirm = id
|
||||
state.alert = AlertState.confirmDelete()
|
||||
return .none
|
||||
|
||||
// broken
|
||||
|
||||
case .deleteIdConfirmed:
|
||||
state.alert = nil
|
||||
guard let deleteIdToConfirm = state.deleteIdToConfirm, let account = state.zashiWalletAccount else {
|
||||
return .none
|
||||
}
|
||||
|
@ -206,8 +207,8 @@ public struct AddressBook {
|
|||
// TODO: [#1408] error handling https://github.com/Electric-Coin-Company/zashi-ios/issues/1408
|
||||
}
|
||||
return .concatenate(
|
||||
.send(.fetchedABContacts(abContacts, false))
|
||||
// .send(.updateDestination(nil))
|
||||
.send(.fetchedABContacts(abContacts, false)),
|
||||
.send(.dismissDeleteContactRequired)
|
||||
)
|
||||
} catch {
|
||||
// TODO: [#1408] error handling https://github.com/Electric-Coin-Company/zashi-ios/issues/1408
|
||||
|
@ -306,6 +307,9 @@ public struct AddressBook {
|
|||
|
||||
case .dismissAddContactRequired:
|
||||
return .none
|
||||
|
||||
case .dismissDeleteContactRequired:
|
||||
return .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,12 +67,6 @@ public struct AddressBookView: View {
|
|||
)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.applyScreenBackground()
|
||||
.alert(
|
||||
store: store.scope(
|
||||
state: \.$alert,
|
||||
action: \.alert
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ public struct Home {
|
|||
public var moreRequest = false
|
||||
public var syncProgressState: SyncProgress.State
|
||||
public var walletConfig: WalletConfig
|
||||
// public var scanBinding = false
|
||||
// public var scanState = Scan.State.initial
|
||||
@Shared(.inMemory(.selectedWalletAccount)) public var selectedWalletAccount: WalletAccount? = nil
|
||||
public var transactionListState: TransactionList.State
|
||||
public var uAddress: UnifiedAddress? = nil
|
||||
|
@ -98,6 +100,7 @@ public struct Home {
|
|||
case resolveReviewRequest
|
||||
case retrySync
|
||||
case reviewRequestFinished
|
||||
// case scan(Scan.Action)
|
||||
case scanTapped
|
||||
case seeAllTransactionsTapped
|
||||
case sendTapped
|
||||
|
@ -131,6 +134,10 @@ public struct Home {
|
|||
TransactionList()
|
||||
}
|
||||
|
||||
// Scope(state: \.scanState, action: \.scan) {
|
||||
// Scan()
|
||||
// }
|
||||
|
||||
Scope(state: \.syncProgressState, action: \.syncProgress) {
|
||||
SyncProgress()
|
||||
}
|
||||
|
@ -142,6 +149,7 @@ public struct Home {
|
|||
Reduce { state, action in
|
||||
switch action {
|
||||
case .onAppear:
|
||||
// state.scanState.checkers = [.zcashAddressScanChecker, .requestZecScanChecker]
|
||||
state.appId = PartnerKeys.cbProjectId
|
||||
state.walletBalancesState.migratingDatabase = state.migratingDatabase
|
||||
state.migratingDatabase = false
|
||||
|
@ -164,9 +172,13 @@ public struct Home {
|
|||
.cancel(id: CancelEventId)
|
||||
)
|
||||
|
||||
case .receiveTapped, .sendTapped, .scanTapped:
|
||||
case .receiveTapped, .sendTapped:
|
||||
return .none
|
||||
|
||||
case .scanTapped:
|
||||
// state.scanBinding = true
|
||||
return .none
|
||||
|
||||
case .moreTapped:
|
||||
state.moreRequest = true
|
||||
return .none
|
||||
|
@ -261,6 +273,10 @@ public struct Home {
|
|||
state.alert = nil
|
||||
return .none
|
||||
|
||||
// case .scan(.cancelTapped):
|
||||
// state.scanBinding = false
|
||||
// return .none
|
||||
|
||||
case .alert:
|
||||
return .none
|
||||
|
||||
|
@ -273,6 +289,9 @@ public struct Home {
|
|||
case .currencyConversionSetupTapped:
|
||||
return .none
|
||||
|
||||
// case .scan:
|
||||
// return .none
|
||||
|
||||
// Accounts
|
||||
|
||||
case .accountSwitchTapped:
|
||||
|
|
|
@ -9,6 +9,7 @@ import SyncProgress
|
|||
import Utils
|
||||
import Models
|
||||
import WalletBalances
|
||||
import Scan
|
||||
|
||||
public struct HomeView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
@ -225,6 +226,15 @@ public struct HomeView: View {
|
|||
.onAppear {
|
||||
store.send(.onAppear)
|
||||
}
|
||||
// .popover(isPresented: $store.scanBinding) {
|
||||
// ScanView(
|
||||
// store:
|
||||
// store.scope(
|
||||
// state: \.scanState,
|
||||
// action: \.scan
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
.onChange(of: store.canRequestReview) { canRequestReview in
|
||||
if canRequestReview {
|
||||
if let currentScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
|
||||
|
|
|
@ -107,10 +107,26 @@ extension Root {
|
|||
case .path(.element(id: _, action: .addressBook(.addManualButtonTapped))):
|
||||
state.path.append(.addressBookContact(AddressBook.State.initial))
|
||||
return .none
|
||||
|
||||
case .path(.element(id: _, action: .addressBook(.scanButtonTapped))):
|
||||
var scanState = Scan.State.initial
|
||||
scanState.checkers = [.zcashAddressScanChecker]
|
||||
state.path.append(.scan(scanState))
|
||||
return .none
|
||||
|
||||
// MARK: - Address Book Contact
|
||||
|
||||
case .path(.element(id: _, action: .addressBookContact(.dismissAddContactRequired))):
|
||||
let _ = state.path.popLast()
|
||||
for element in state.path {
|
||||
if element.is(\.scan) {
|
||||
let _ = state.path.popLast()
|
||||
return .none
|
||||
}
|
||||
}
|
||||
return .none
|
||||
|
||||
case .path(.element(id: _, action: .addressBookContact(.dismissDeleteContactRequired))):
|
||||
let _ = state.path.popLast()
|
||||
return .none
|
||||
|
||||
|
@ -149,19 +165,25 @@ extension Root {
|
|||
.cancellable(id: CancelFlexaId, cancelInFlight: true)
|
||||
|
||||
// MARK: - Home
|
||||
|
||||
case .home(.receiveTapped):
|
||||
state.path.append(.receive(Receive.State.initial))
|
||||
return .none
|
||||
|
||||
|
||||
case .home(.settingsTapped):
|
||||
state.path.append(.settings(Settings.State.initial))
|
||||
return .none
|
||||
|
||||
case .home(.receiveTapped):
|
||||
state.path.append(.receive(Receive.State.initial))
|
||||
return .none
|
||||
|
||||
case .home(.sendTapped):
|
||||
state.path.append(.sendForm(SendForm.State.initial))
|
||||
return .none
|
||||
|
||||
case .home(.scanTapped):
|
||||
var scanState = Scan.State.initial
|
||||
scanState.checkers = [.zcashAddressScanChecker, .requestZecScanChecker]
|
||||
state.path.append(.scan(scanState))
|
||||
return .none
|
||||
|
||||
case .home(.flexaTapped):
|
||||
return .send(.flexaOpenRequest)
|
||||
|
||||
|
@ -241,6 +263,61 @@ extension Root {
|
|||
}
|
||||
return .none
|
||||
|
||||
case .path(.element(id: _, action: .scan(.found(let address)))):
|
||||
// Handling of scan used in address book to add a contact
|
||||
// This handling must preceed the next one with Send Form check
|
||||
for (id, element) in zip(state.path.ids, state.path) {
|
||||
if element.is(\.addressBook) {
|
||||
var addressBookState = AddressBook.State.initial
|
||||
addressBookState.address = address.data
|
||||
addressBookState.isValidZcashAddress = true
|
||||
addressBookState.isNameFocused = true
|
||||
state.path.append(.addressBookContact(addressBookState))
|
||||
audioServices.systemSoundVibrate()
|
||||
return .none
|
||||
}
|
||||
}
|
||||
// Handling of scan used in the Send Form
|
||||
for (id, element) in zip(state.path.ids, state.path) {
|
||||
if element.is(\.sendForm) {
|
||||
state.path[id: id, case: \.sendForm]?.address = address
|
||||
state.path[id: id, case: \.sendForm]?.isValidAddress = true
|
||||
state.path[id: id, case: \.sendForm]?.isValidTransparentAddress = derivationTool.isTransparentAddress(
|
||||
address.data,
|
||||
zcashSDKEnvironment.network.networkType
|
||||
)
|
||||
state.path[id: id, case: \.sendForm]?.isValidTexAddress = derivationTool.isTexAddress(
|
||||
address.data,
|
||||
zcashSDKEnvironment.network.networkType
|
||||
)
|
||||
audioServices.systemSoundVibrate()
|
||||
let _ = state.path.popLast()
|
||||
return .none
|
||||
}
|
||||
}
|
||||
// Scan from Home, Send Form is the following flow
|
||||
if state.path.ids.count == 1 {
|
||||
var sendFormState = SendForm.State.initial
|
||||
sendFormState.address = address
|
||||
sendFormState.isValidAddress = true
|
||||
sendFormState.isValidTransparentAddress = derivationTool.isTransparentAddress(
|
||||
address.data,
|
||||
zcashSDKEnvironment.network.networkType
|
||||
)
|
||||
sendFormState.isValidTexAddress = derivationTool.isTexAddress(
|
||||
address.data,
|
||||
zcashSDKEnvironment.network.networkType
|
||||
)
|
||||
|
||||
state.path.append(.sendForm(sendFormState))
|
||||
audioServices.systemSoundVibrate()
|
||||
}
|
||||
return .none
|
||||
|
||||
case .path(.element(id: _, action: .scan(.cancelTapped))):
|
||||
let _ = state.path.popLast()
|
||||
return .none
|
||||
|
||||
// MARK: - Send Confirmation
|
||||
|
||||
case .path(.element(id: _, action: .sendConfirmation(.cancelTapped))):
|
||||
|
@ -332,6 +409,12 @@ extension Root {
|
|||
addressBookState.isInSelectMode = true
|
||||
state.path.append(.addressBook(addressBookState))
|
||||
return .none
|
||||
|
||||
case .path(.element(id: _, action: .sendForm(.scanTapped))):
|
||||
var scanState = Scan.State.initial
|
||||
scanState.checkers = [.zcashAddressScanChecker, .requestZecScanChecker]
|
||||
state.path.append(.scan(scanState))
|
||||
return .none
|
||||
|
||||
case .path(.element(id: _, action: .sendForm(.confirmationRequired(let confirmationType)))):
|
||||
var sendConfirmationState = SendConfirmation.State.initial
|
||||
|
|
|
@ -27,79 +27,83 @@ public struct ScanView: View {
|
|||
public var body: some View {
|
||||
WithPerceptionTracking {
|
||||
ZStack {
|
||||
GeometryReader { proxy in
|
||||
QRCodeScanView(
|
||||
rectOfInterest: ScanView.normalizedRectsOfInterest().real,
|
||||
onQRScanningDidFail: { store.send(.scanFailed(.invalidQRCode)) },
|
||||
onQRScanningSucceededWithCode: { store.send(.scan($0.redacted)) }
|
||||
)
|
||||
|
||||
frameOfInterest(proxy.size)
|
||||
|
||||
WithPerceptionTracking {
|
||||
if store.isTorchAvailable {
|
||||
torchButton(size: proxy.size)
|
||||
}
|
||||
if showSheet {
|
||||
ZashiImagePicker(selectedImage: $image, showSheet: $showSheet)
|
||||
} else {
|
||||
GeometryReader { proxy in
|
||||
QRCodeScanView(
|
||||
rectOfInterest: ScanView.normalizedRectsOfInterest().real,
|
||||
onQRScanningDidFail: { store.send(.scanFailed(.invalidQRCode)) },
|
||||
onQRScanningSucceededWithCode: { store.send(.scan($0.redacted)) }
|
||||
)
|
||||
|
||||
if !store.forceLibraryToHide {
|
||||
libraryButton(size: proxy.size)
|
||||
}
|
||||
}
|
||||
|
||||
WithPerceptionTracking {
|
||||
if store.progress != nil {
|
||||
WithPerceptionTracking {
|
||||
progress(size: proxy.size, progress: store.countedProgress)
|
||||
frameOfInterest(proxy.size)
|
||||
|
||||
WithPerceptionTracking {
|
||||
if store.isTorchAvailable {
|
||||
torchButton(size: proxy.size)
|
||||
}
|
||||
|
||||
if !store.forceLibraryToHide {
|
||||
libraryButton(size: proxy.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VStack {
|
||||
WithPerceptionTracking {
|
||||
if let instructions = store.instructions {
|
||||
Text(instructions)
|
||||
.font(.custom(FontFamily.Inter.semiBold.name, size: 20))
|
||||
.foregroundColor(Asset.Colors.ZDesign.shark200.color)
|
||||
.padding(.top, 64)
|
||||
.lineLimit(nil)
|
||||
.multilineTextAlignment(.center)
|
||||
.lineSpacing(3)
|
||||
.screenHorizontalPadding()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
HStack(alignment: .top, spacing: 0) {
|
||||
if !store.info.isEmpty {
|
||||
Asset.Assets.infoOutline.image
|
||||
.zImage(size: 20, color: Asset.Colors.ZDesign.shark200.color)
|
||||
.padding(.trailing, 12)
|
||||
|
||||
Text(store.info)
|
||||
.font(.custom(FontFamily.Inter.medium.name, size: 12))
|
||||
.foregroundColor(Asset.Colors.ZDesign.shark200.color)
|
||||
.padding(.top, 2)
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
}
|
||||
.padding(.bottom, 15)
|
||||
|
||||
if !store.isCameraEnabled {
|
||||
primaryButton(L10n.Scan.openSettings) {
|
||||
if let url = URL(string: UIApplication.openSettingsURLString) {
|
||||
openURL(url)
|
||||
WithPerceptionTracking {
|
||||
if store.progress != nil {
|
||||
WithPerceptionTracking {
|
||||
progress(size: proxy.size, progress: store.countedProgress)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
primaryButton(L10n.General.cancel) {
|
||||
store.send(.cancelTapped)
|
||||
}
|
||||
}
|
||||
|
||||
VStack {
|
||||
WithPerceptionTracking {
|
||||
if let instructions = store.instructions {
|
||||
Text(instructions)
|
||||
.font(.custom(FontFamily.Inter.semiBold.name, size: 20))
|
||||
.foregroundColor(Asset.Colors.ZDesign.shark200.color)
|
||||
.padding(.top, 64)
|
||||
.lineLimit(nil)
|
||||
.multilineTextAlignment(.center)
|
||||
.lineSpacing(3)
|
||||
.screenHorizontalPadding()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
HStack(alignment: .top, spacing: 0) {
|
||||
if !store.info.isEmpty {
|
||||
Asset.Assets.infoOutline.image
|
||||
.zImage(size: 20, color: Asset.Colors.ZDesign.shark200.color)
|
||||
.padding(.trailing, 12)
|
||||
|
||||
Text(store.info)
|
||||
.font(.custom(FontFamily.Inter.medium.name, size: 12))
|
||||
.foregroundColor(Asset.Colors.ZDesign.shark200.color)
|
||||
.padding(.top, 2)
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
}
|
||||
.padding(.bottom, 15)
|
||||
|
||||
if !store.isCameraEnabled {
|
||||
primaryButton(L10n.Scan.openSettings) {
|
||||
if let url = URL(string: UIApplication.openSettingsURLString) {
|
||||
openURL(url)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
primaryButton(L10n.General.cancel) {
|
||||
store.send(.cancelTapped)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.screenHorizontalPadding()
|
||||
}
|
||||
.screenHorizontalPadding()
|
||||
}
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.ignoresSafeArea()
|
||||
|
@ -112,12 +116,16 @@ public struct ScanView: View {
|
|||
store.send(.libraryImage(img))
|
||||
}
|
||||
}
|
||||
.overlay {
|
||||
if showSheet {
|
||||
ZashiImagePicker(selectedImage: $image, showSheet: $showSheet)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
}
|
||||
// .navigationLinkEmpty(isActive: $showSheet) {
|
||||
// ZashiImagePicker(selectedImage: $image, showSheet: $showSheet)
|
||||
// //.ignoresSafeArea()
|
||||
// }
|
||||
// .overlay {
|
||||
// if showSheet {
|
||||
// ZashiImagePicker(selectedImage: $image, showSheet: $showSheet)
|
||||
// .ignoresSafeArea()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,7 @@ struct ZashiImagePicker: UIViewControllerRepresentable {
|
|||
parent.showSheet = false
|
||||
}
|
||||
}
|
||||
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
|
||||
@Binding var selectedImage: UIImage?
|
||||
@Binding var showSheet: Bool
|
||||
|
||||
|
@ -39,7 +38,7 @@ struct ZashiImagePicker: UIViewControllerRepresentable {
|
|||
context: UIViewControllerRepresentableContext<ZashiImagePicker>
|
||||
) -> UIImagePickerController {
|
||||
let imagePicker = UIImagePickerController()
|
||||
|
||||
|
||||
imagePicker.allowsEditing = false
|
||||
imagePicker.sourceType = .photoLibrary
|
||||
imagePicker.delegate = context.coordinator
|
||||
|
|
|
@ -49,6 +49,7 @@ public struct SendForm {
|
|||
public var isCurrencyConversionEnabled = false
|
||||
public var isNotAddressInAddressBook = false
|
||||
public var isPaymentRequestInProgress = false
|
||||
public var isPopToRootBack = false
|
||||
public var isValidAddress = false
|
||||
public var isValidTransparentAddress = false
|
||||
public var isValidTexAddress = false
|
||||
|
@ -212,6 +213,7 @@ public struct SendForm {
|
|||
case requestsAddressFocusResolved
|
||||
case resetForm
|
||||
case reviewTapped
|
||||
case scanTapped
|
||||
// case scan(Scan.Action)
|
||||
case sendFailed(ZcashError, Confirmation)
|
||||
case syncAmounts(Bool)
|
||||
|
@ -494,6 +496,9 @@ public struct SendForm {
|
|||
|
||||
case .dismissRequired:
|
||||
return .none
|
||||
|
||||
case .scanTapped:
|
||||
return .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public struct SendFormView: View {
|
|||
}
|
||||
|
||||
fieldButton(icon: Asset.Assets.Icons.qr.image) {
|
||||
// store.send(.updateDestination(.scanQR))
|
||||
store.send(.scanTapped)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +214,8 @@ public struct SendFormView: View {
|
|||
}
|
||||
.padding(.vertical, 1)
|
||||
.applyScreenBackground()
|
||||
.zashiBack { store.send(.dismissRequired) }
|
||||
.zashiBack(hidden: store.isPopToRootBack) { store.send(.dismissRequired) }
|
||||
.zashiBackV2(hidden: !store.isPopToRootBack) { store.send(.dismissRequired) }
|
||||
.alert(store: store.scope(
|
||||
state: \.$alert,
|
||||
action: \.alert
|
||||
|
|
Loading…
Reference in New Issue