no message

This commit is contained in:
Ilya Laktyushin 2018-09-21 09:04:02 +01:00
parent f82e4c1c7c
commit f7963c166c
31 changed files with 376 additions and 215 deletions

View File

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
091BEAB3214552D9003AEA30 /* Vision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D02DADBE2138D76F00116225 /* Vision.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
092F368D2154AAEA001A9F49 /* SFCompactRounded-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 092F368C2154AAE9001A9F49 /* SFCompactRounded-Semibold.otf */; };
09310D2C213ED5FB0020033A /* anim_read.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D14213BC5DE0020033A /* anim_read.json */; };
09310D2D213ED5FB0020033A /* anim_pin.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D15213BC5DE0020033A /* anim_pin.json */; };
09310D2E213ED5FB0020033A /* anim_unmute.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D16213BC5DE0020033A /* anim_unmute.json */; };
@ -1022,6 +1023,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
092F368C2154AAE9001A9F49 /* SFCompactRounded-Semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SFCompactRounded-Semibold.otf"; sourceTree = "<group>"; };
09310D14213BC5DE0020033A /* anim_read.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_read.json; sourceTree = "<group>"; };
09310D15213BC5DE0020033A /* anim_pin.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_pin.json; sourceTree = "<group>"; };
09310D16213BC5DE0020033A /* anim_unmute.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_unmute.json; sourceTree = "<group>"; };
@ -2164,6 +2166,15 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
092F368B2154AAD6001A9F49 /* Fonts */ = {
isa = PBXGroup;
children = (
092F368C2154AAE9001A9F49 /* SFCompactRounded-Semibold.otf */,
);
name = Fonts;
path = TelegramUI/Resources/Fonts;
sourceTree = "<group>";
};
09310D13213BC5DE0020033A /* Animations */ = {
isa = PBXGroup;
children = (
@ -2520,6 +2531,7 @@
isa = PBXGroup;
children = (
09310D13213BC5DE0020033A /* Animations */,
092F368B2154AAD6001A9F49 /* Fonts */,
D0C12A1B1F33964900B3F66D /* ChatWallpaperBuiltin0.jpg */,
D0E9BA681F056F4C00F079A4 /* Stripe */,
D0E9B9E91F00853C00F079A4 /* PhoneCountries.txt */,
@ -4637,6 +4649,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
092F368D2154AAEA001A9F49 /* SFCompactRounded-Semibold.otf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -168,7 +168,7 @@ class CallListCallItem: ListViewItem {
private let separatorHeight = 1.0 / UIScreen.main.scale
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 15.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
class CallListCallItemNode: ItemListRevealOptionsItemNode {
private let backgroundNode: ASDisplayNode

View File

@ -2,8 +2,8 @@ import Foundation
import AsyncDisplayKit
import Display
private let normalFont = UIFont(name: "ArialRoundedMTBold", size: 16.0)!
private let smallFont = UIFont(name: "ArialRoundedMTBold", size: 12.0)!
private let normalFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
private let smallFont = UIFont(name: ".SFCompactRounded-Semibold", size: 12.0)!
final class ChatAvatarNavigationNode: ASDisplayNode {
let avatarNode: AvatarNode

View File

@ -205,7 +205,7 @@ private func leftRevealOptions(strings: PresentationStrings, theme: Presentation
private let separatorHeight = 1.0 / UIScreen.main.scale
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 26.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 26.0)!
class ChatListItemNode: ItemListRevealOptionsItemNode {
var item: ChatListItem?

View File

@ -146,7 +146,8 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
if let user = primaryPeer as? TelegramUser {
if let _ = user.botInfo {
status = .custom(strings.Bot_GenericBotStatus)
} else if user.id != account.peerId, let presence = peer.presence {
} else if user.id != account.peerId {
let presence = peer.presence ?? TelegramUserPresence(status: .none)
status = .presence(presence, timeFormat)
} else {
status = .none

View File

@ -56,7 +56,7 @@ final class ChatMediaInputPeerSpecificItem: ListViewItem {
}
}
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 10.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 10.0)!
private let boundingSize = CGSize(width: 41.0, height: 41.0)
private let boundingImageSize = CGSize(width: 28.0, height: 28.0)
private let highlightSize = CGSize(width: 35.0, height: 35.0)

View File

@ -3,7 +3,7 @@ import Postbox
import Display
import TelegramCore
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 15.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
final class ChatMessageAvatarAccessoryItem: ListViewAccessoryItem {
private let account: Account

View File

@ -5,7 +5,7 @@ import SwiftSignalKit
import Postbox
import TelegramCore
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 15.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
private let titleFont = Font.medium(14.0)
private let textFont = Font.regular(14.0)

View File

@ -3,7 +3,7 @@ import Display
import TelegramCore
import Postbox
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 24.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 24.0)!
private let avatarBackgroundImage = UIImage(bundleImageName: "Chat/Message/LocationPin")?.precomposed()
private func addPulseAnimations(layer: CALayer) {

View File

@ -2,7 +2,7 @@ import Foundation
import AsyncDisplayKit
import Display
private let textFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 13.0)!
private let textFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 13.0)!
private class ChatMessageLiveLocationTimerNodeParams: NSObject {
let backgroundColor: UIColor

View File

@ -45,7 +45,7 @@ public final class ChatMessageNotificationItem: NotificationItem {
}
}
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 24.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 24.0)!
final class ChatMessageNotificationItemNode: NotificationItemNode {
private var item: ChatMessageNotificationItem?

View File

@ -62,7 +62,7 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
let panelHeight: CGFloat = 40.0
let contentRightInset: CGFloat = 18.0 + rightInset
let contentRightInset: CGFloat = 14.0 + rightInset
let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0))
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: width - contentRightInset - closeButtonSize.width, y: floorToScreenPixels((panelHeight - closeButtonSize.height) / 2.0)), size: closeButtonSize))

View File

@ -72,7 +72,7 @@ final class CommandChatInputPanelItem: ListViewItem {
}
}
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 16.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
private let textFont = Font.medium(14.0)
private let descriptionFont = Font.regular(14.0)

View File

@ -151,10 +151,9 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
case let .peer(peer, isGlobal):
if isGlobal, let _ = peer.addressName {
status = .addressName("")
} else if let presence = presence {
status = .presence(presence, timeFormat)
} else {
status = .none
let presence = presence ?? TelegramUserPresence(status: .none)
status = .presence(presence, timeFormat)
}
itemPeer = .peer(peer: peer, chatPeer: peer)
case let .deviceContact(id, contact):

View File

@ -270,7 +270,7 @@ class ContactsPeerItem: ListViewItem {
private let separatorHeight = 1.0 / UIScreen.main.scale
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 15.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
private let backgroundNode: ASDisplayNode

View File

@ -240,7 +240,7 @@ class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
}
}
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 28.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 28.0)!
private let nameFont = Font.medium(19.0)
private let statusFont = Font.regular(15.0)
@ -410,7 +410,7 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite
} else if let _ = peer.botInfo {
statusText = item.strings.Bot_GenericBotStatus
statusColor = item.theme.list.itemSecondaryTextColor
} else if case .generic = item.mode {
} else if case .generic = item.mode, !(peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id == 777000) {
let presence = (item.presence as? TelegramUserPresence) ?? TelegramUserPresence(status: .none)
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
let (string, activity) = stringAndActivityForUserPresence(strings: item.strings, timeFormat: .regular, presence: presence, relativeTo: Int32(timestamp))

View File

@ -151,7 +151,7 @@ private let titleBoldFont = Font.medium(17.0)
private let statusFont = Font.regular(14.0)
private let labelFont = Font.regular(13.0)
private let labelDisclosureFont = Font.regular(17.0)
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 17.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 17.0)!
class ItemListPeerItemNode: ItemListRevealOptionsItemNode {
private let backgroundNode: ASDisplayNode

View File

@ -4,7 +4,7 @@ import Display
import Postbox
import TelegramCore
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 26.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 26.0)!
private final class MoreNode: ASDisplayNode {
private let avatarNode = AvatarNode(font: Font.regular(24.0))

View File

@ -39,7 +39,7 @@ public class LocationBroadcastActionSheetItem: ActionSheetItem {
}
}
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 15.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 15.0)!
public class LocationBroadcastActionSheetItemNode: ActionSheetItemNode {
private let theme: ActionSheetControllerTheme

View File

@ -74,7 +74,7 @@ final class MentionChatInputPanelItem: ListViewItem {
}
}
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 16.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 16.0)!
private let primaryFont = Font.medium(14.0)
private let secondaryFont = Font.regular(14.0)

View File

@ -4,7 +4,7 @@ import AsyncDisplayKit
import Postbox
import TelegramCore
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 13.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 13.0)!
final class MultipleAvatarsNode: ASDisplayNode {
private var nodes: [(Peer, AvatarNode)] = []

View File

@ -198,8 +198,8 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
})
case let .serversHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .addServer(theme, text, editing):
return ProxySettingsActionItem(theme: theme, title: text, sectionId: self.section, editing: false, action: {
case let .addServer(theme, text, _):
return ProxySettingsActionItem(theme: theme, title: text, icon: .add, sectionId: self.section, editing: false, action: {
arguments.addNewServer()
})
case let .server(_, theme, strings, settings, active, status, editing, enabled):

View File

@ -3,16 +3,23 @@ import Display
import AsyncDisplayKit
import SwiftSignalKit
enum ProxySettingsActionIcon {
case none
case add
}
class ProxySettingsActionItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let title: String
let icon: ProxySettingsActionIcon
let editing: Bool
let sectionId: ItemListSectionId
let action: () -> Void
init(theme: PresentationTheme, title: String, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) {
init(theme: PresentationTheme, title: String, icon: ProxySettingsActionIcon = .none, sectionId: ItemListSectionId, editing: Bool, action: @escaping () -> Void) {
self.theme = theme
self.title = title
self.icon = icon
self.editing = editing
self.sectionId = sectionId
self.action = action
@ -117,7 +124,7 @@ class ProxySettingsActionItemNode: ListViewItemNode {
if currentItem?.theme !== item.theme {
updatedTheme = item.theme
}
let leftInset: CGFloat = 50.0 + params.leftInset
let leftInset: CGFloat = (item.icon != .none ? 50.0 : 16.0) + params.leftInset
let editingOffset: CGFloat = (item.editing ? 38.0 : 0.0)
@ -131,7 +138,7 @@ class ProxySettingsActionItemNode: ListViewItemNode {
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
let layoutSize = layout.size
let icon = PresentationResourcesItemList.plusIconImage(item.theme)
let icon = item.icon == .add ? PresentationResourcesItemList.plusIconImage(item.theme) : nil
return (layout, { [weak self] animated in
if let strongSelf = self {

View File

@ -425,6 +425,15 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
}
}
let hasErrors: (SecureIdValueWithContext, SecureIdValueKey) -> Bool = { value, key in
for error in value.errors {
if case let .value(valueKey) = error.key, valueKey != key {
return value.errors.count > 1
}
}
return !value.errors.isEmpty
}
switch field {
case let .identity(personalDetails, document, selfie, translations):
if let document = document {
@ -446,23 +455,34 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
}
}
case let .oneOf(types):
var chosenByError = false
outer: for type in types {
if let value = findValue(formData.values, key: type.valueKey)?.1 {
switch value.value {
case .passport:
hasValueType = .passport
break outer
case .idCard:
hasValueType = .idCard
break outer
case .driversLicense:
hasValueType = .driversLicense
break outer
case .internalPassport:
hasValueType = .internalPassport
break outer
default:
break
let hasErrors = hasErrors(value, type.valueKey)
let data = extractSecureIdValueAdditionalData(value.value)
var dataFilled = true
if selfie && !data.selfie {
dataFilled = false
}
if translations && !data.translation {
dataFilled = false
}
if hasValueType == nil || ((hasErrors || dataFilled) && !chosenByError) {
chosenByError = hasErrors
switch value.value {
case .passport:
hasValueType = .passport
case .idCard:
hasValueType = .idCard
case .driversLicense:
hasValueType = .driversLicense
case .internalPassport:
hasValueType = .internalPassport
default:
break
}
}
}
}
@ -506,26 +526,38 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
}
}
case let .oneOf(types):
var chosenByError = false
outer: for type in types {
if let value = findValue(formData.values, key: type.valueKey)?.1 {
switch value.value {
case .utilityBill:
hasValueType = .utilityBill
break outer
case .bankStatement:
hasValueType = .bankStatement
break outer
case .rentalAgreement:
hasValueType = .rentalAgreement
break outer
case .passportRegistration:
hasValueType = .passportRegistration
break outer
case .temporaryRegistration:
hasValueType = .temporaryRegistration
break outer
default:
break
let hasErrors = hasErrors(value, type.valueKey)
let data = extractSecureIdValueAdditionalData(value.value)
var dataFilled = true
if translation && !data.translation {
dataFilled = false
}
if hasValueType == nil || ((hasErrors || dataFilled) && !chosenByError) {
chosenByError = hasErrors
switch value.value {
case .utilityBill:
hasValueType = .utilityBill
break outer
case .bankStatement:
hasValueType = .bankStatement
break outer
case .rentalAgreement:
hasValueType = .rentalAgreement
break outer
case .passportRegistration:
hasValueType = .passportRegistration
break outer
case .temporaryRegistration:
hasValueType = .temporaryRegistration
break outer
default:
break
}
}
}
}

View File

@ -204,6 +204,9 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
if personalDetails != nil {
if let value = findValue(values, key: .personalDetails)?.1 {
result.append(value)
if !value.errors.isEmpty {
filled = false
}
} else {
filled = false
}
@ -213,13 +216,16 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
result.append(value)
let data = extractValueAdditionalData(value.value)
let data = extractSecureIdValueAdditionalData(value.value)
if selfie && !data.selfie {
filled = false
}
if translation && !data.translation {
filled = false
}
if !value.errors.isEmpty {
filled = false
}
} else {
filled = false
}
@ -231,7 +237,7 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
if bestMatchingValue == nil {
bestMatchingValue = value
}
let data = extractValueAdditionalData(value.value)
let data = extractSecureIdValueAdditionalData(value.value)
var dataFilled = true
if selfie && !data.selfie {
dataFilled = false
@ -251,6 +257,9 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
}
if let bestMatchingValue = bestMatchingValue {
result.append(bestMatchingValue)
if !bestMatchingValue.errors.isEmpty {
filled = false
}
}
}
}
@ -261,6 +270,9 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
if addressDetails {
if let value = findValue(values, key: .address)?.1 {
result.append(value)
if !value.errors.isEmpty {
filled = false
}
} else {
filled = false
}
@ -270,10 +282,13 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
result.append(value)
let data = extractValueAdditionalData(value.value)
let data = extractSecureIdValueAdditionalData(value.value)
if translation && !data.translation {
filled = false
}
if !value.errors.isEmpty {
filled = false
}
} else {
filled = false
}
@ -285,7 +300,7 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
if bestMatchingValue == nil {
bestMatchingValue = value
}
let data = extractValueAdditionalData(value.value)
let data = extractSecureIdValueAdditionalData(value.value)
var dataFilled = true
if translation && !data.translation {
dataFilled = false
@ -302,6 +317,9 @@ private func findValuesForField(field: SecureIdParsedRequestedFormField, values:
}
if let bestMatchingValue = bestMatchingValue {
result.append(bestMatchingValue)
if !bestMatchingValue.errors.isEmpty {
filled = false
}
}
}
}
@ -673,43 +691,72 @@ private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings:
return (title, text.isEmpty ? placeholder : text)
}
private struct ValueAdditionalData {
var nativeNames: Bool = false
var selfie: Bool = false
var translation: Bool = false
}
private func extractValueAdditionalData(_ value: SecureIdValue) -> ValueAdditionalData {
var data = ValueAdditionalData()
switch value {
case let .personalDetails(value):
data.nativeNames = value.nativeName != nil
case let .passport(value):
data.selfie = value.selfieDocument != nil
data.translation = !value.translations.isEmpty
case let .internalPassport(value):
data.selfie = value.selfieDocument != nil
data.translation = !value.translations.isEmpty
case let .idCard(value):
data.selfie = value.selfieDocument != nil
data.translation = !value.translations.isEmpty
case let .driversLicense(value):
data.selfie = value.selfieDocument != nil
data.translation = !value.translations.isEmpty
case let .utilityBill(value):
data.translation = !value.translations.isEmpty
case let .rentalAgreement(value):
data.translation = !value.translations.isEmpty
case let .bankStatement(value):
data.translation = !value.translations.isEmpty
case let .temporaryRegistration(value):
data.translation = !value.translations.isEmpty
case let .passportRegistration(value):
data.translation = !value.translations.isEmpty
private func fieldErrorText(field: SecureIdParsedRequestedFormField, values: [SecureIdValueWithContext]) -> String? {
switch field {
case let .identity(personalDetails, document, _, _):
if let _ = personalDetails, let value = findValue(values, key: .personalDetails)?.1 {
if let error = value.errors[.value(.personalDetails)] {
return error
} else if let error = value.errors.first?.value {
return error
}
}
if let document = document {
switch document {
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
if let error = value.errors[.value(type.valueKey)] {
return error
} else if let error = value.errors.first?.value {
return error
}
}
case let .oneOf(types):
for type in types {
if let value = findValue(values, key: type.valueKey)?.1 {
if let error = value.errors[.value(type.valueKey)] {
return error
} else if let error = value.errors.first?.value {
return error
}
}
}
}
}
case let .address(addressDetails, document, _):
if addressDetails, let value = findValue(values, key: .address)?.1 {
if let error = value.errors[.value(.address)] {
return error
} else if let error = value.errors.first?.value {
return error
}
}
if let document = document {
switch document {
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
if let error = value.errors[.value(type.valueKey)] {
return error
} else if let error = value.errors.first?.value {
return error
}
}
case let .oneOf(types):
for type in types {
if let value = findValue(values, key: type.valueKey)?.1 {
if let error = value.errors[.value(type.valueKey)] {
return error
} else if let error = value.errors.first?.value {
return error
}
}
}
}
}
default:
break
return nil
}
return data
return nil
}
final class SecureIdAuthFormFieldNode: ASDisplayNode {
@ -805,116 +852,128 @@ final class SecureIdAuthFormFieldNode: ASDisplayNode {
func updateValues(_ values: [SecureIdValueWithContext]) {
var (title, text) = fieldTitleAndText(field: self.field, strings: self.strings, values: values)
let textColor = self.theme.list.itemSecondaryTextColor
/*switch self.field {
case .identity:
if let error = errors[.personalDetails]?.first {
text = error
textColor = self.theme.list.itemDestructiveColor
}
default:
break
}*/
var textColor = self.theme.list.itemSecondaryTextColor
var filled = true
switch self.field {
case let .identity(personalDetails, document, selfie, translation):
if let personalDetails = personalDetails {
if let value = findValue(values, key: .personalDetails)?.1 {
let data = extractValueAdditionalData(value.value)
if personalDetails.nativeNames && !data.nativeNames {
if let errorText = fieldErrorText(field: self.field, values: values) {
filled = false
textColor = self.theme.list.itemDestructiveColor
text = errorText
} else {
switch self.field {
case let .identity(personalDetails, document, selfie, translation):
if let personalDetails = personalDetails {
if let value = findValue(values, key: .personalDetails)?.1 {
let data = extractSecureIdValueAdditionalData(value.value)
if personalDetails.nativeNames && !data.nativeNames {
filled = false
text = strings.Passport_FieldIdentityDetailsHelp
}
} else {
filled = false
text = strings.Passport_FieldIdentityDetailsHelp
}
} else {
filled = false
text = strings.Passport_FieldIdentityDetailsHelp
}
}
if let document = document {
switch document {
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractValueAdditionalData(value.value)
if selfie && !data.selfie {
filled = false
text = strings.Passport_FieldIdentitySelfieHelp
}
if translation && !data.translation {
filled = false
text = strings.Passport_FieldIdentityTranslationHelp
}
} else {
filled = false
}
case let .oneOf(types):
var anyDocument = false
for type in types {
if let document = document {
switch document {
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractValueAdditionalData(value.value)
var dataFilled = true
let data = extractSecureIdValueAdditionalData(value.value)
if selfie && !data.selfie {
dataFilled = false
filled = false
text = strings.Passport_FieldIdentitySelfieHelp
}
if translation && !data.translation {
dataFilled = false
filled = false
text = strings.Passport_FieldIdentityTranslationHelp
}
if dataFilled {
anyDocument = true
}
}
}
if !anyDocument {
filled = false
}
}
}
case let .address(addressDetails, document, translation):
if addressDetails {
if findValue(values, key: .address) == nil {
filled = false
text = strings.Passport_FieldAddressHelp
}
}
if let document = document {
switch document {
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractValueAdditionalData(value.value)
if translation && !data.translation {
} else {
filled = false
text = strings.Passport_FieldAddressTranslationHelp
}
} else {
filled = false
}
case let .oneOf(types):
var anyDocument = false
for type in types {
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractValueAdditionalData(value.value)
var dataFilled = true
if translation && !data.translation {
dataFilled = false
}
if dataFilled {
anyDocument = true
case let .oneOf(types):
var anyDocument = false
var missingSelfie = false
var missingTranslation = false
for type in types {
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractSecureIdValueAdditionalData(value.value)
var dataFilled = true
if selfie && !data.selfie {
dataFilled = false
missingSelfie = true
}
if translation && !data.translation {
dataFilled = false
missingTranslation = true
}
if dataFilled {
anyDocument = true
}
}
}
}
if !anyDocument {
filled = false
}
if !anyDocument {
filled = false
if missingSelfie {
text = strings.Passport_FieldIdentitySelfieHelp
} else if missingTranslation {
text = strings.Passport_FieldIdentityTranslationHelp
}
}
}
}
}
case .phone:
if findValue(values, key: .phone) == nil {
filled = false
}
case .email:
if findValue(values, key: .email) == nil {
filled = false
}
case let .address(addressDetails, document, translation):
if addressDetails {
if findValue(values, key: .address) == nil {
filled = false
text = strings.Passport_FieldAddressHelp
}
}
if let document = document {
switch document {
case let .just(type):
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractSecureIdValueAdditionalData(value.value)
if translation && !data.translation {
filled = false
text = strings.Passport_FieldAddressTranslationHelp
}
} else {
filled = false
}
case let .oneOf(types):
var anyDocument = false
var missingTranslation = false
for type in types {
if let value = findValue(values, key: type.valueKey)?.1 {
let data = extractSecureIdValueAdditionalData(value.value)
var dataFilled = true
if translation && !data.translation {
dataFilled = false
missingTranslation = true
}
if dataFilled {
anyDocument = true
}
}
}
if !anyDocument {
filled = false
if missingTranslation {
text = strings.Passport_FieldIdentityTranslationHelp
}
}
}
}
case .phone:
if findValue(values, key: .phone) == nil {
filled = false
}
case .email:
if findValue(values, key: .email) == nil {
filled = false
}
}
}
self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.theme.list.itemPrimaryTextColor)

View File

@ -5,7 +5,7 @@ import Postbox
import TelegramCore
import SwiftSignalKit
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 26.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 26.0)!
private let titleFont: UIFont = Font.semibold(14.0)
private let textFont: UIFont = Font.regular(14.0)

View File

@ -74,7 +74,7 @@ final class SecureIdDocumentFormController: FormController<SecureIdDocumentFormS
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
self.doneItem = UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.donePressed))
self.navigationItem.rightBarButtonItem = doneItem
self.navigationItem.rightBarButtonItem = self.doneItem
}
required init(coder aDecoder: NSCoder) {

View File

@ -942,6 +942,24 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
break
}
var badHashes: Set<Data> = []
var badFileHashes: Set<Data>?
var badTranslationHashes: Set<Data>?
for value in self.previousValues {
for error in value.value.errors {
switch error.key {
case .value, .field:
return .saveNotAvailable
case let .file(hash), let .selfie(hash), let .frontSide(hash), let .backSide(hash), let .translationFile(hash):
badHashes.insert(hash)
case let .files(hashes):
badFileHashes = hashes
case let .translationFiles(hashes):
badTranslationHashes = hashes
}
}
}
var documentsRequired = false
switch self.documentState {
@ -958,7 +976,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
}
}
func isDocumentReady(_ document: SecureIdVerificationDocument?) -> Bool {
func isDocumentReady(_ document: SecureIdVerificationDocument?, badHashes: Set<Data>? = nil) -> Bool {
if let document = document {
switch document {
case let .local(local):
@ -968,8 +986,12 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
case .uploaded:
return true
}
case .remote:
return true
case let .remote(reference):
if let badHashes = badHashes {
return !badHashes.contains(reference.fileHash)
} else {
return true
}
}
} else {
return false
@ -977,40 +999,64 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
}
if self.frontSideRequired {
guard isDocumentReady(self.frontSideDocument) else {
guard isDocumentReady(self.frontSideDocument, badHashes: badHashes) else {
return .saveNotAvailable
}
}
if self.backSideRequired {
guard isDocumentReady(self.backSideDocument) else {
guard isDocumentReady(self.backSideDocument, badHashes: badHashes) else {
return .saveNotAvailable
}
}
if self.selfieRequired {
guard isDocumentReady(self.selfieDocument) else {
guard isDocumentReady(self.selfieDocument, badHashes: badHashes) else {
return .saveNotAvailable
}
}
var fileHashes: Set<Data> = []
for document in self.documents {
guard isDocumentReady(document) else {
return .saveNotAvailable
}
switch document {
case let .remote(reference):
fileHashes.insert(reference.fileHash)
case let .local(document):
if case let .uploaded(file) = document.state {
fileHashes.insert(file.fileHash)
}
}
}
if documentsRequired && self.documents.isEmpty {
return .saveNotAvailable
}
if let badFileHashes = badFileHashes, badFileHashes == fileHashes {
return .saveNotAvailable
}
var translationHashes: Set<Data> = []
for document in self.translations {
guard isDocumentReady(document) else {
return .saveNotAvailable
}
switch document {
case let .remote(reference):
translationHashes.insert(reference.fileHash)
case let .local(document):
if case let .uploaded(file) = document.state {
translationHashes.insert(file.fileHash)
}
}
}
if self.translationsRequired && self.translations.isEmpty {
return .saveNotAvailable
}
if let badTranslationHashes = badTranslationHashes, badTranslationHashes == translationHashes {
return .saveNotAvailable
}
return .saveAvailable
}
@ -2145,8 +2191,9 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
}
}
if let valueKey = valueKey, let errorKey = errorKey {
let valueErrorKey: SecureIdValueContentErrorKey = .value(valueKey)
if let previousValue = innerState.previousValues[valueKey] {
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey])
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey, valueErrorKey])
}
}
strongSelf.updateInnerState(transition: .immediate, with: innerState)
@ -2198,8 +2245,9 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
errorKey = .field(.address(.countryCode))
}
if let valueKey = valueKey, let errorKey = errorKey {
let valueErrorKey: SecureIdValueContentErrorKey = .value(valueKey)
if let previousValue = innerState.previousValues[valueKey] {
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey])
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey, valueErrorKey])
}
}
strongSelf.updateInnerState(transition: .immediate, with: innerState)
@ -2222,8 +2270,9 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
break
}
if let valueKey = valueKey, let errorKey = errorKey {
let valueErrorKey: SecureIdValueContentErrorKey = .value(valueKey)
if let previousValue = innerState.previousValues[valueKey] {
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey])
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey, valueErrorKey])
}
}
strongSelf.updateInnerState(transition: .immediate, with: innerState)
@ -2289,9 +2338,11 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
case .address:
break
}
if let valueKey = valueKey, let errorKey = errorKey {
let valueErrorKey: SecureIdValueContentErrorKey = .value(valueKey)
if let previousValue = innerState.previousValues[valueKey] {
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey])
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey, valueErrorKey])
}
}
strongSelf.updateInnerState(transition: .immediate, with: innerState)
@ -2312,8 +2363,9 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
valueKey = .personalDetails
errorKey = .field(.personalDetails(.gender))
if let valueKey = valueKey, let errorKey = errorKey {
let valueErrorKey: SecureIdValueContentErrorKey = .value(valueKey)
if let previousValue = innerState.previousValues[valueKey] {
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey])
innerState.previousValues[valueKey] = previousValue.withRemovedErrors([errorKey, valueErrorKey])
}
}
strongSelf.updateInnerState(transition: .immediate, with: innerState)

View File

@ -7,7 +7,7 @@ import SwiftSignalKit
import LegacyComponents
private let avatarFont: UIFont = UIFont(name: "ArialRoundedMTBold", size: 24.0)!
private let avatarFont: UIFont = UIFont(name: ".SFCompactRounded-Semibold", size: 24.0)!
private let textFont = Font.regular(11.0)
final class SelectablePeerNodeTheme {

View File

@ -1146,13 +1146,11 @@ public func userInfoController(account: Account, peerId: PeerId) -> ViewControll
})
}
shareMyContactImpl = { [weak controller] in
let _ = (peerView.get()
|> take(1)
|> deliverOnMainQueue).start(next: { view in
guard let peer = peerViewMainPeer(view) as? TelegramUser, let phone = peer.phone else {
let _ = (getUserPeer(postbox: account.postbox, peerId: account.peerId)
|> deliverOnMainQueue).start(next: { peer in
guard let peer = peer as? TelegramUser, let phone = peer.phone else {
return
}
let contact = TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)
let _ = (enqueueMessages(account: account, peerId: peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: contact), replyToMessageId: nil, localGroupingKey: nil)])