mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-25 01:22:41 +00:00
Merge branch 'master' of github.com:peter-iakovlev/TelegramUI
This commit is contained in:
commit
c2149ecd2e
@ -90,7 +90,7 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr
|
||||
self.contactsNode.requestShareTelegram = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let url = strongSelf.presentationData.strings.InviteText_URL
|
||||
var body = strongSelf.presentationData.strings.InviteText_SingleContact(url).0
|
||||
let body = strongSelf.presentationData.strings.InviteText_SingleContact(url).0
|
||||
|
||||
let shareController = ShareController(account: strongSelf.account, subject: .text(body), externalShare: true, immediateExternalShare: true)
|
||||
strongSelf.present(shareController, in: .window(.root))
|
||||
@ -110,8 +110,8 @@ public class InviteContactsController: ViewController, MFMessageComposeViewContr
|
||||
let url = strongSelf.presentationData.strings.InviteText_URL
|
||||
var body = strongSelf.presentationData.strings.InviteText_SingleContact(url).0
|
||||
if numbers.count == 1, numbers[0].1 > 0 {
|
||||
body = strongSelf.presentationData.strings.InviteText_ContactsCount(numbers[0].1)
|
||||
body = body.replacingOccurrences(of: "(null)", with: url)
|
||||
body = strongSelf.presentationData.strings.InviteText_ContactsCountText(numbers[0].1)
|
||||
body = body.replacingOccurrences(of: "{url}", with: url)
|
||||
}
|
||||
composer.body = body
|
||||
strongSelf.composer = composer
|
||||
|
||||
@ -340,18 +340,18 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
self.addSubnode(self.countPanelNode)
|
||||
|
||||
self.presentationDataDisposable = (account.telegramApplicationContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
let previousStrings = strongSelf.presentationData.strings
|
||||
|
||||
strongSelf.presentationData = presentationData
|
||||
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||
strongSelf.updateThemeAndStrings()
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
let previousStrings = strongSelf.presentationData.strings
|
||||
|
||||
strongSelf.presentationData = presentationData
|
||||
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||
strongSelf.updateThemeAndStrings()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let account = self.account
|
||||
var firstTime: Int32 = 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -299,6 +299,10 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
self?.interaction.openUrl(url)
|
||||
}, openMention: { [weak self] mention in
|
||||
self?.interaction.openMention(mention)
|
||||
}, requestLayout: { [weak self] in
|
||||
if let strongSelf = self, let (layout, navigationHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
})
|
||||
contentNode = current
|
||||
}
|
||||
@ -363,6 +367,10 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
self?.openListField(field)
|
||||
}, deleteAll: { [weak self] in
|
||||
self?.deleteAllValues()
|
||||
}, requestLayout: { [weak self] in
|
||||
if let strongSelf = self, let (layout, navigationHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
})
|
||||
current.updateValues(values)
|
||||
contentNode = current
|
||||
|
||||
@ -15,9 +15,12 @@ final class SecureIdAuthFormContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
||||
private let headerNode: ImmediateTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
|
||||
private let requestLayout: () -> Void
|
||||
private var validLayout: CGFloat?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, peer: Peer, privacyPolicyUrl: String?, form: SecureIdForm, openField: @escaping (SecureIdParsedRequestedFormField) -> Void, openURL: @escaping (String) -> Void, openMention: @escaping (TelegramPeerMention) -> Void) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, peer: Peer, privacyPolicyUrl: String?, form: SecureIdForm, openField: @escaping (SecureIdParsedRequestedFormField) -> Void, openURL: @escaping (String) -> Void, openMention: @escaping (TelegramPeerMention) -> Void, requestLayout: @escaping () -> Void) {
|
||||
self.requestLayout = requestLayout
|
||||
|
||||
self.requestedFields = form.requestedFields
|
||||
self.fieldBackgroundNode = ASDisplayNode()
|
||||
self.fieldBackgroundNode.isLayerBacked = true
|
||||
@ -91,6 +94,7 @@ final class SecureIdAuthFormContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
self.requestLayout()
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> SecureIdAuthContentLayout {
|
||||
|
||||
@ -15,9 +15,10 @@ final class SecureIdAuthListContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
||||
private let deleteItem: FormControllerActionItem
|
||||
private let deleteNode: FormControllerActionItemNode
|
||||
|
||||
private let requestLayout: () -> Void
|
||||
private var validLayout: CGFloat?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, openField: @escaping (SecureIdAuthListContentField) -> Void, deleteAll: @escaping () -> Void) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, openField: @escaping (SecureIdAuthListContentField) -> Void, deleteAll: @escaping () -> Void, requestLayout: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
||||
@ -50,6 +51,8 @@ final class SecureIdAuthListContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
||||
})
|
||||
self.deleteNode = self.deleteItem.node() as! FormControllerActionItemNode
|
||||
|
||||
self.requestLayout = requestLayout
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.headerNode)
|
||||
@ -62,6 +65,8 @@ final class SecureIdAuthListContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
||||
for fieldNode in self.fieldNodes {
|
||||
fieldNode.updateValues(values)
|
||||
}
|
||||
|
||||
self.requestLayout()
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> SecureIdAuthContentLayout {
|
||||
|
||||
@ -420,6 +420,13 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
}
|
||||
|
||||
result.append(.entry(SecureIdDocumentFormEntry.infoHeader(.identity)))
|
||||
|
||||
let previousValue: SecureIdValueWithContext? = self.previousValues[.personalDetails]
|
||||
let valueErrorKey: SecureIdValueContentErrorKey = .value(.personalDetails)
|
||||
|
||||
if let previousValue = previousValue {
|
||||
maybeAddError(key: valueErrorKey, value: previousValue, entries: &result, errorIndex: &errorIndex)
|
||||
}
|
||||
result.append(.entry(SecureIdDocumentFormEntry.firstName(details.firstName, self.previousValues[.personalDetails]?.errors[.field(.personalDetails(.firstName))])))
|
||||
result.append(.entry(SecureIdDocumentFormEntry.middleName(details.middleName, self.previousValues[.personalDetails]?.errors[.field(.personalDetails(.middleName))])))
|
||||
result.append(.entry(SecureIdDocumentFormEntry.lastName(details.lastName, self.previousValues[.personalDetails]?.errors[.field(.personalDetails(.lastName))])))
|
||||
@ -448,23 +455,38 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
result.append(.entry(SecureIdDocumentFormEntry.infoHeader(.identity)))
|
||||
}
|
||||
|
||||
let previousValue: SecureIdValueWithContext?
|
||||
let valueErrorKey: SecureIdValueContentErrorKey
|
||||
|
||||
var identifierError: String?
|
||||
var expiryDateError: String?
|
||||
|
||||
switch document.type {
|
||||
case .passport:
|
||||
previousValue = self.previousValues[.passport]
|
||||
valueErrorKey = .value(.passport)
|
||||
identifierError = self.previousValues[.passport]?.errors[.field(.passport(.documentId))]
|
||||
expiryDateError = self.previousValues[.passport]?.errors[.field(.passport(.expiryDate))]
|
||||
case .internalPassport:
|
||||
previousValue = self.previousValues[.internalPassport]
|
||||
valueErrorKey = .value(.internalPassport)
|
||||
identifierError = self.previousValues[.internalPassport]?.errors[.field(.internalPassport(.documentId))]
|
||||
expiryDateError = self.previousValues[.internalPassport]?.errors[.field(.internalPassport(.expiryDate))]
|
||||
case .driversLicense:
|
||||
previousValue = self.previousValues[.driversLicense]
|
||||
valueErrorKey = .value(.driversLicense)
|
||||
identifierError = self.previousValues[.driversLicense]?.errors[.field(.driversLicense(.documentId))]
|
||||
expiryDateError = self.previousValues[.driversLicense]?.errors[.field(.driversLicense(.expiryDate))]
|
||||
case .idCard:
|
||||
previousValue = self.previousValues[.idCard]
|
||||
valueErrorKey = .value(.idCard)
|
||||
identifierError = self.previousValues[.idCard]?.errors[.field(.idCard(.documentId))]
|
||||
expiryDateError = self.previousValues[.idCard]?.errors[.field(.idCard(.expiryDate))]
|
||||
}
|
||||
|
||||
if let previousValue = previousValue {
|
||||
maybeAddError(key: valueErrorKey, value: previousValue, entries: &result, errorIndex: &errorIndex)
|
||||
}
|
||||
result.append(.entry(SecureIdDocumentFormEntry.identifier(document.identifier, identifierError)))
|
||||
result.append(.entry(SecureIdDocumentFormEntry.expiryDate(document.expiryDate, expiryDateError)))
|
||||
}
|
||||
@ -736,6 +758,12 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
if let details = address.details {
|
||||
|
||||
result.append(.entry(SecureIdDocumentFormEntry.infoHeader(.address)))
|
||||
|
||||
let previousValue: SecureIdValueWithContext? = self.previousValues[.address]
|
||||
let valueErrorKey: SecureIdValueContentErrorKey = .value(.address)
|
||||
if let previousValue = previousValue {
|
||||
maybeAddError(key: valueErrorKey, value: previousValue, entries: &result, errorIndex: &errorIndex)
|
||||
}
|
||||
result.append(.entry(SecureIdDocumentFormEntry.street1(details.street1, self.previousValues[.address]?.errors[.field(.address(.streetLine1))])))
|
||||
result.append(.entry(SecureIdDocumentFormEntry.street2(details.street2, self.previousValues[.address]?.errors[.field(.address(.streetLine2))])))
|
||||
result.append(.entry(SecureIdDocumentFormEntry.city(details.city, self.previousValues[.address]?.errors[.field(.address(.city))])))
|
||||
@ -1189,6 +1217,38 @@ extension SecureIdDocumentFormState {
|
||||
}
|
||||
}
|
||||
|
||||
private func removeDocumentWithId(_ innerState: SecureIdDocumentFormState, id: SecureIdVerificationDocumentId) -> SecureIdDocumentFormState {
|
||||
var innerState = innerState
|
||||
|
||||
if let selfieDocument = innerState.selfieDocument, selfieDocument.id == id {
|
||||
innerState.selfieDocument = nil
|
||||
}
|
||||
|
||||
if let frontSideDocument = innerState.frontSideDocument, frontSideDocument.id == id {
|
||||
innerState.frontSideDocument = nil
|
||||
}
|
||||
|
||||
if let backSideDocument = innerState.backSideDocument, backSideDocument.id == id {
|
||||
innerState.backSideDocument = nil
|
||||
}
|
||||
|
||||
for i in 0 ..< innerState.documents.count {
|
||||
if innerState.documents[i].id == id {
|
||||
innerState.documents.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0 ..< innerState.translations.count {
|
||||
if innerState.translations[i].id == id {
|
||||
innerState.translations.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return innerState
|
||||
}
|
||||
|
||||
enum SecureIdDocumentFormEntryId: Hashable {
|
||||
case scanYourPassport
|
||||
case scanYourPassportInfo
|
||||
@ -1892,7 +1952,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
}
|
||||
}, openDocument: { [weak self] document in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentGallery(document: document)
|
||||
strongSelf.openDocument(document: document)
|
||||
}
|
||||
}, updateText: { [weak self] field, value in
|
||||
if let strongSelf = self, var innerState = strongSelf.innerState {
|
||||
@ -1908,6 +1968,18 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
case .lastName:
|
||||
valueKey = .personalDetails
|
||||
errorKey = .field(.personalDetails(.lastName))
|
||||
case .middleName:
|
||||
valueKey = .personalDetails
|
||||
errorKey = .field(.personalDetails(.middleName))
|
||||
case .nativeFirstName:
|
||||
valueKey = .personalDetails
|
||||
errorKey = .field(.personalDetails(.firstNameNative))
|
||||
case .nativeLastName:
|
||||
valueKey = .personalDetails
|
||||
errorKey = .field(.personalDetails(.lastNameNative))
|
||||
case .nativeMiddleName:
|
||||
valueKey = .personalDetails
|
||||
errorKey = .field(.personalDetails(.middleNameNative))
|
||||
case .identifier:
|
||||
if let document = identity.document {
|
||||
switch document.type {
|
||||
@ -2202,7 +2274,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
self.actionDisposable.dispose()
|
||||
}
|
||||
|
||||
private func presentAssetPicker(_ type: AddFileTarget) {
|
||||
private func presentAssetPicker(_ type: AddFileTarget, replaceDocumentId: SecureIdVerificationDocumentId? = nil) {
|
||||
guard let validLayout = self.layoutState?.layout else {
|
||||
return
|
||||
}
|
||||
@ -2244,45 +2316,77 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
self?.view.endEditing(true)
|
||||
self?.present(c, nil)
|
||||
}, validLayout: validLayout, type: attachmentType, recognizeDocumentData: recognizeDocumentData, completion: { [weak self] resources, recognizedData in
|
||||
self?.addDocuments(type: type, resources: resources, recognizedData: recognizedData)
|
||||
self?.addDocuments(type: type, resources: resources, recognizedData: recognizedData, removeDocumentId: replaceDocumentId)
|
||||
})
|
||||
}
|
||||
|
||||
private func addDocuments(type: AddFileTarget, resources: [TelegramMediaResource], recognizedData: SecureIdRecognizedDocumentData?) {
|
||||
private func addDocuments(type: AddFileTarget, resources: [TelegramMediaResource], recognizedData: SecureIdRecognizedDocumentData?, removeDocumentId: SecureIdVerificationDocumentId?) {
|
||||
guard var innerState = self.innerState else {
|
||||
return
|
||||
}
|
||||
|
||||
switch type {
|
||||
case .scan:
|
||||
var addIndex = innerState.documents.count
|
||||
if let removeDocumentId = removeDocumentId {
|
||||
for i in 0 ..< innerState.documents.count {
|
||||
if innerState.documents[i].id == removeDocumentId {
|
||||
innerState.documents.remove(at: i)
|
||||
addIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for resource in resources {
|
||||
let id = arc4random64()
|
||||
innerState.documents.append(.local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0))))
|
||||
innerState.documents.insert(.local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0))), at: addIndex)
|
||||
addIndex += 1
|
||||
}
|
||||
if innerState.documents.count > 20 {
|
||||
innerState.documents = Array(innerState.documents[0 ..< 20])
|
||||
}
|
||||
case .selfie:
|
||||
if let removeDocumentId = removeDocumentId {
|
||||
innerState = removeDocumentWithId(innerState, id: removeDocumentId)
|
||||
}
|
||||
loop: for resource in resources {
|
||||
let id = arc4random64()
|
||||
innerState.selfieDocument = .local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0)))
|
||||
break loop
|
||||
}
|
||||
case .frontSide:
|
||||
if let removeDocumentId = removeDocumentId {
|
||||
innerState = removeDocumentWithId(innerState, id: removeDocumentId)
|
||||
}
|
||||
loop: for resource in resources {
|
||||
let id = arc4random64()
|
||||
innerState.frontSideDocument = .local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0)))
|
||||
break loop
|
||||
}
|
||||
case .backSide:
|
||||
if let removeDocumentId = removeDocumentId {
|
||||
innerState = removeDocumentWithId(innerState, id: removeDocumentId)
|
||||
}
|
||||
loop: for resource in resources {
|
||||
let id = arc4random64()
|
||||
innerState.backSideDocument = .local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0)))
|
||||
break loop
|
||||
}
|
||||
case .translation:
|
||||
var addIndex = innerState.translations.count
|
||||
if let removeDocumentId = removeDocumentId {
|
||||
for i in 0 ..< innerState.translations.count {
|
||||
if innerState.translations[i].id == removeDocumentId {
|
||||
innerState.translations.remove(at: i)
|
||||
addIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for resource in resources {
|
||||
let id = arc4random64()
|
||||
innerState.translations.append(.local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0))))
|
||||
innerState.translations.insert(.local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0))), at: addIndex)
|
||||
addIndex += 1
|
||||
}
|
||||
if innerState.translations.count > 20 {
|
||||
innerState.translations = Array(innerState.documents[0 ..< 20])
|
||||
@ -2483,6 +2587,95 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
self.present(controller, nil)
|
||||
}
|
||||
|
||||
private func openDocument(document: SecureIdVerificationDocument) {
|
||||
let controller = ActionSheetController(presentationTheme: theme)
|
||||
let dismissAction: () -> Void = { [weak controller] in
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
controller.setItemGroups([
|
||||
ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strings.Passport_Identity_FilesView, action: { [weak self] in
|
||||
dismissAction()
|
||||
self?.presentGallery(document: document)
|
||||
}),
|
||||
ActionSheetButtonItem(title: strings.Passport_Identity_FilesUploadNew, action: { [weak self] in
|
||||
dismissAction()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let innerState = strongSelf.innerState else {
|
||||
return
|
||||
}
|
||||
|
||||
var target: AddFileTarget?
|
||||
|
||||
let id = document.id
|
||||
|
||||
if let selfieDocument = innerState.selfieDocument, selfieDocument.id == id {
|
||||
target = .selfie
|
||||
}
|
||||
|
||||
if let frontSideDocument = innerState.frontSideDocument, frontSideDocument.id == id {
|
||||
switch innerState.documentState {
|
||||
case let .identity(identity):
|
||||
if let document = identity.document {
|
||||
target = .frontSide(document.type)
|
||||
}
|
||||
case .address:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if let backSideDocument = innerState.backSideDocument, backSideDocument.id == id {
|
||||
switch innerState.documentState {
|
||||
case let .identity(identity):
|
||||
if let document = identity.document {
|
||||
target = .backSide(document.type)
|
||||
}
|
||||
case .address:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0 ..< innerState.documents.count {
|
||||
if innerState.documents[i].id == id {
|
||||
target = .scan
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0 ..< innerState.translations.count {
|
||||
if innerState.translations[i].id == id {
|
||||
target = .translation
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if let target = target {
|
||||
strongSelf.view.endEditing(true)
|
||||
strongSelf.presentAssetPicker(target, replaceDocumentId: document.id)
|
||||
}
|
||||
}),
|
||||
ActionSheetButtonItem(title: strings.Common_Delete, action: { [weak self] in
|
||||
dismissAction()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard var innerState = strongSelf.innerState else {
|
||||
return
|
||||
}
|
||||
|
||||
innerState = removeDocumentWithId(innerState, id: document.id)
|
||||
|
||||
strongSelf.updateInnerState(transition: .immediate, with: innerState)
|
||||
})
|
||||
]),
|
||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: self.strings.Common_Cancel, action: { dismissAction() })])
|
||||
])
|
||||
self.view.endEditing(true)
|
||||
self.present(controller, nil)
|
||||
}
|
||||
|
||||
private func presentGallery(document: SecureIdVerificationDocument) {
|
||||
guard let innerState = self.innerState else {
|
||||
return
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user