mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 05:26:48 +00:00
Merge commit 'f82e4c1c7cb2aeea71aff222ec247eae880960b6'
This commit is contained in:
commit
4e7b02568e
BIN
Images.xcassets/Call/CallRouteBluetooth.imageset/CallRouteBluetooth@2x.png
vendored
Normal file
BIN
Images.xcassets/Call/CallRouteBluetooth.imageset/CallRouteBluetooth@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 644 B |
BIN
Images.xcassets/Call/CallRouteBluetooth.imageset/CallRouteBluetooth@3x.png
vendored
Normal file
BIN
Images.xcassets/Call/CallRouteBluetooth.imageset/CallRouteBluetooth@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 814 B |
22
Images.xcassets/Call/CallRouteBluetooth.imageset/Contents.json
vendored
Normal file
22
Images.xcassets/Call/CallRouteBluetooth.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CallRouteBluetooth@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CallRouteBluetooth@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Images.xcassets/Call/CallRouteSpeaker.imageset/CallRouteSpeaker@2x.png
vendored
Normal file
BIN
Images.xcassets/Call/CallRouteSpeaker.imageset/CallRouteSpeaker@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 655 B |
BIN
Images.xcassets/Call/CallRouteSpeaker.imageset/CallRouteSpeaker@3x.png
vendored
Normal file
BIN
Images.xcassets/Call/CallRouteSpeaker.imageset/CallRouteSpeaker@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
22
Images.xcassets/Call/CallRouteSpeaker.imageset/Contents.json
vendored
Normal file
22
Images.xcassets/Call/CallRouteSpeaker.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CallRouteSpeaker@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "CallRouteSpeaker@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@ -36,6 +36,7 @@
|
||||
09874E592107BD4100E190B8 /* GenericEmbedImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09874E4021075C1700E190B8 /* GenericEmbedImplementation.swift */; };
|
||||
09AE3823214C110900850BFD /* LegacySecureIdScanController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AE3822214C110800850BFD /* LegacySecureIdScanController.swift */; };
|
||||
09C500242142BA6400EF253E /* ItemListWebsiteItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09C500232142BA6400EF253E /* ItemListWebsiteItem.swift */; };
|
||||
09FE756D2153F5F900A3120F /* CallRouteActionSheetItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FE756C2153F5F900A3120F /* CallRouteActionSheetItem.swift */; };
|
||||
D007019C2029E8F2006B9E34 /* LegqacyICloudFileController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D007019B2029E8F2006B9E34 /* LegqacyICloudFileController.swift */; };
|
||||
D007019E2029EFDD006B9E34 /* ICloudResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = D007019D2029EFDD006B9E34 /* ICloudResources.swift */; };
|
||||
D00701A12029F6D0006B9E34 /* TGMimeTypeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = D007019F2029F6D0006B9E34 /* TGMimeTypeMap.h */; };
|
||||
@ -1053,6 +1054,7 @@
|
||||
09874E4421075C3F00E190B8 /* StreamableEmbedImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamableEmbedImplementation.swift; sourceTree = "<group>"; };
|
||||
09AE3822214C110800850BFD /* LegacySecureIdScanController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySecureIdScanController.swift; sourceTree = "<group>"; };
|
||||
09C500232142BA6400EF253E /* ItemListWebsiteItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListWebsiteItem.swift; sourceTree = "<group>"; };
|
||||
09FE756C2153F5F900A3120F /* CallRouteActionSheetItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallRouteActionSheetItem.swift; sourceTree = "<group>"; };
|
||||
D00219051DDD1C9E00BE708A /* ImageContainingNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageContainingNode.swift; sourceTree = "<group>"; };
|
||||
D002A0D01E9B99F500A81812 /* SoftwareVideoSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoftwareVideoSource.swift; sourceTree = "<group>"; };
|
||||
D002A0D21E9BBE6700A81812 /* MultiplexedSoftwareVideoSourceManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiplexedSoftwareVideoSourceManager.swift; sourceTree = "<group>"; };
|
||||
@ -3711,6 +3713,7 @@
|
||||
D0F0AAE31EC21AAA005EE2A5 /* CallControllerButtonsNode.swift */,
|
||||
D0F0AAE51EC21B68005EE2A5 /* CallControllerButton.swift */,
|
||||
D0ACCB191EC5E0C20079D8BF /* CallControllerKeyPreviewNode.swift */,
|
||||
09FE756C2153F5F900A3120F /* CallRouteActionSheetItem.swift */,
|
||||
);
|
||||
name = Call;
|
||||
sourceTree = "<group>";
|
||||
@ -5202,6 +5205,7 @@
|
||||
D0EC6DD81EB9F58900EBF1C3 /* VerticalListContextResultsChatInputPanelButtonItem.swift in Sources */,
|
||||
D04281F4200E5AB0009DDE36 /* ChatRecentActionsController.swift in Sources */,
|
||||
D0B2F76220506E2A00D3BFB9 /* MediaInputSettings.swift in Sources */,
|
||||
09FE756D2153F5F900A3120F /* CallRouteActionSheetItem.swift in Sources */,
|
||||
D0BFAE4E20AB1D7B00793CF2 /* DisabledContextResultsChatInputContextPanelNode.swift in Sources */,
|
||||
D064EF871F69A06F00AC0398 /* MessageContentKind.swift in Sources */,
|
||||
D020A9DA1FEAE675008C66F7 /* OverlayPlayerController.swift in Sources */,
|
||||
|
||||
@ -119,17 +119,22 @@ public final class CallController: ViewController {
|
||||
var items: [ActionSheetItem] = []
|
||||
for output in availableOutputs {
|
||||
let title: String
|
||||
var icon: UIImage?
|
||||
switch output {
|
||||
case .builtin:
|
||||
title = UIDevice.current.model
|
||||
case .speaker:
|
||||
title = strongSelf.presentationData.strings.Call_AudioRouteSpeaker
|
||||
icon = UIImage(bundleImageName: "Call/CallRouteSpeaker")
|
||||
case .headphones:
|
||||
title = strongSelf.presentationData.strings.Call_AudioRouteHeadphones
|
||||
case let .port(port):
|
||||
title = port.name
|
||||
if port.type == .bluetooth {
|
||||
icon = UIImage(bundleImageName: "Call/CallRouteBluetooth")
|
||||
}
|
||||
}
|
||||
items.append(ActionSheetButtonItem(title: title, color: .accent, action: { [weak actionSheet] in
|
||||
items.append(CallRouteActionSheetItem(title: title, icon: icon, selected: output == currentOutput, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
self?.call.setCurrentAudioOutput(output)
|
||||
}))
|
||||
|
||||
142
TelegramUI/CallRouteActionSheetItem.swift
Normal file
142
TelegramUI/CallRouteActionSheetItem.swift
Normal file
@ -0,0 +1,142 @@
|
||||
import Foundation
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
|
||||
public class CallRouteActionSheetItem: ActionSheetItem {
|
||||
public let title: String
|
||||
public let icon: UIImage?
|
||||
public let selected: Bool
|
||||
public let action: () -> Void
|
||||
|
||||
public init(title: String, icon: UIImage?, selected: Bool, action: @escaping () -> Void) {
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
self.selected = selected
|
||||
self.action = action
|
||||
}
|
||||
|
||||
public func node(theme: ActionSheetControllerTheme) -> ActionSheetItemNode {
|
||||
let node = CallRouteActionSheetItemNode(theme: theme)
|
||||
node.setItem(self)
|
||||
return node
|
||||
}
|
||||
|
||||
public func updateNode(_ node: ActionSheetItemNode) {
|
||||
guard let node = node as? CallRouteActionSheetItemNode else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
node.setItem(self)
|
||||
}
|
||||
}
|
||||
|
||||
public class CallRouteActionSheetItemNode: ActionSheetItemNode {
|
||||
private let theme: ActionSheetControllerTheme
|
||||
|
||||
public static let defaultFont: UIFont = Font.regular(20.0)
|
||||
|
||||
private var item: CallRouteActionSheetItem?
|
||||
|
||||
private let button: HighlightTrackingButton
|
||||
private let label: ASTextNode
|
||||
private let iconNode: ASImageNode
|
||||
private let checkNode: ASImageNode
|
||||
|
||||
override public init(theme: ActionSheetControllerTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.button = HighlightTrackingButton()
|
||||
|
||||
self.label = ASTextNode()
|
||||
self.label.isLayerBacked = true
|
||||
self.label.maximumNumberOfLines = 1
|
||||
self.label.displaysAsynchronously = false
|
||||
self.label.truncationMode = .byTruncatingTail
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.isUserInteractionEnabled = false
|
||||
self.iconNode.displayWithoutProcessing = true
|
||||
self.iconNode.displaysAsynchronously = false
|
||||
|
||||
self.checkNode = ASImageNode()
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
self.checkNode.displayWithoutProcessing = true
|
||||
self.checkNode.displaysAsynchronously = false
|
||||
self.checkNode.image = generateImage(CGSize(width: 14.0, height: 11.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setStrokeColor(theme.controlAccentColor.cgColor)
|
||||
context.setLineWidth(2.0)
|
||||
context.move(to: CGPoint(x: 12.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: 4.16482734, y: 9.0))
|
||||
context.addLine(to: CGPoint(x: 1.0, y: 5.81145833))
|
||||
context.strokePath()
|
||||
})
|
||||
|
||||
super.init(theme: theme)
|
||||
|
||||
self.view.addSubview(self.button)
|
||||
|
||||
self.label.isUserInteractionEnabled = false
|
||||
self.addSubnode(self.label)
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.checkNode)
|
||||
|
||||
self.button.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.backgroundNode.backgroundColor = strongSelf.theme.itemHighlightedBackgroundColor
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
strongSelf.backgroundNode.backgroundColor = strongSelf.theme.itemBackgroundColor
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.button.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside)
|
||||
}
|
||||
|
||||
func setItem(_ item: CallRouteActionSheetItem) {
|
||||
self.item = item
|
||||
|
||||
self.label.attributedText = NSAttributedString(string: item.title, font: ActionSheetButtonNode.defaultFont, textColor: self.theme.standardActionTextColor)
|
||||
if let icon = item.icon {
|
||||
self.iconNode.image = generateTintedImage(image: icon, color: self.theme.standardActionTextColor)
|
||||
} else {
|
||||
self.iconNode.isHidden = true
|
||||
}
|
||||
self.checkNode.isHidden = !item.selected
|
||||
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
public override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
return CGSize(width: constrainedSize.width, height: 57.0)
|
||||
}
|
||||
|
||||
public override func layout() {
|
||||
super.layout()
|
||||
|
||||
let size = self.bounds.size
|
||||
|
||||
self.button.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
let labelSize = self.label.measure(CGSize(width: max(1.0, size.width - 10.0), height: size.height))
|
||||
self.label.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - labelSize.width) / 2.0), y: floorToScreenPixels((size.height - labelSize.height) / 2.0)), size: labelSize)
|
||||
|
||||
if let image = self.iconNode.image {
|
||||
self.iconNode.frame = CGRect(origin: CGPoint(x: 12.0, y: floor((size.height - image.size.height) / 2.0)), size: image.size)
|
||||
}
|
||||
|
||||
if let image = self.checkNode.image {
|
||||
self.checkNode.frame = CGRect(origin: CGPoint(x: size.width - image.size.width - 13.0, y: floor((size.height - image.size.height) / 2.0)), size: image.size)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func buttonPressed() {
|
||||
if let item = self.item {
|
||||
item.action()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -503,10 +503,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
var preferredAction = ShareControllerPreferredAction.default
|
||||
if let generalMessageContentKind = generalMessageContentKind {
|
||||
switch generalMessageContentKind {
|
||||
case .image, .video:
|
||||
preferredAction = .saveToCameraRoll
|
||||
default:
|
||||
break
|
||||
case .image, .video:
|
||||
preferredAction = .saveToCameraRoll
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,13 +517,17 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
subject = .image(image.representations)
|
||||
} else if let webpage = m as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let _ = content.image {
|
||||
preferredAction = .saveToCameraRoll
|
||||
} else if let file = m as? TelegramMediaFile, file.isAnimated {
|
||||
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let message = messages[0]
|
||||
let _ = addSavedGif(postbox: strongSelf.account.postbox, fileReference: .message(message: MessageReference(message), media: file)).start()
|
||||
}
|
||||
}))
|
||||
} else if let file = m as? TelegramMediaFile {
|
||||
if file.isAnimated {
|
||||
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let message = messages[0]
|
||||
let _ = addSavedGif(postbox: strongSelf.account.postbox, fileReference: .message(message: MessageReference(message), media: file)).start()
|
||||
}
|
||||
}))
|
||||
} else if file.mimeType.hasPrefix("image/") || file.mimeType.hasPrefix("video/") {
|
||||
preferredAction = .saveToCameraRoll
|
||||
}
|
||||
}
|
||||
}
|
||||
let shareController = ShareController(account: strongSelf.account, subject: subject, preferredAction: preferredAction)
|
||||
|
||||
@ -1471,8 +1471,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
||||
switch gesture {
|
||||
case .tap:
|
||||
if let avatarNode = self.accessoryItemNode as? ChatMessageAvatarAccessoryItemNode, avatarNode.frame.contains(location) {
|
||||
|
||||
if let avatarNode = self.accessoryItemNode as? ChatMessageAvatarAccessoryItemNode, avatarNode.frame.contains(location) {
|
||||
if let item = self.item, let author = item.content.firstMessage.author {
|
||||
let navigate: ChatControllerInteractionNavigateToPeer
|
||||
if item.content.firstMessage.id.peerId == item.account.peerId {
|
||||
|
||||
@ -70,8 +70,8 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
var textString: NSAttributedString?
|
||||
var updatedContactInfo: String?
|
||||
|
||||
var displayName: String = ""
|
||||
if let selectedContact = selectedContact {
|
||||
let displayName: String
|
||||
if !selectedContact.firstName.isEmpty && !selectedContact.lastName.isEmpty {
|
||||
displayName = "\(selectedContact.firstName) \(selectedContact.lastName)"
|
||||
} else if !selectedContact.firstName.isEmpty {
|
||||
@ -79,13 +79,16 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
} else {
|
||||
displayName = selectedContact.lastName
|
||||
}
|
||||
titleString = NSAttributedString(string: displayName, font: titleFont, textColor: item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingAccentTextColor : item.presentationData.theme.theme.chat.bubble.outgoingAccentTextColor)
|
||||
|
||||
let info: String
|
||||
if let previousContact = previousContact, previousContact.isEqual(to: selectedContact), let contactInfo = previousContactInfo {
|
||||
info = contactInfo
|
||||
} else {
|
||||
if let vCard = selectedContact.vCardData, let vCardData = vCard.data(using: .utf8), let contactData = DeviceContactExtendedData(vcard: vCardData) {
|
||||
if displayName.isEmpty && !contactData.organization.isEmpty {
|
||||
displayName = contactData.organization
|
||||
}
|
||||
|
||||
let infoLineLimit = 5
|
||||
var infoComponents: [String] = []
|
||||
if !contactData.basicData.phoneNumbers.isEmpty {
|
||||
@ -105,7 +108,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
}
|
||||
if infoComponents.count < infoLineLimit {
|
||||
if !contactData.organization.isEmpty && (!contactData.basicData.firstName.isEmpty || !contactData.basicData.lastName.isEmpty) {
|
||||
if !contactData.organization.isEmpty && displayName != contactData.organization {
|
||||
infoComponents.append(contactData.organization)
|
||||
}
|
||||
}
|
||||
@ -117,6 +120,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
updatedContactInfo = info
|
||||
|
||||
titleString = NSAttributedString(string: displayName, font: titleFont, textColor: item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingAccentTextColor : item.presentationData.theme.theme.chat.bubble.outgoingAccentTextColor)
|
||||
textString = NSAttributedString(string: info, font: textFont, textColor: item.message.effectivelyIncoming(item.account.peerId) ? item.presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : item.presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor)
|
||||
} else {
|
||||
updatedContactInfo = nil
|
||||
@ -230,6 +234,8 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
customLetters = [String(firstName[..<firstName.index(after: firstName.startIndex)]).uppercased()]
|
||||
} else if !lastName.isEmpty {
|
||||
customLetters = [String(lastName[..<lastName.index(after: lastName.startIndex)]).uppercased()]
|
||||
} else {
|
||||
customLetters = [String(displayName[..<displayName.index(after: displayName.startIndex)]).uppercased()]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -330,9 +330,12 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
return result
|
||||
}
|
||||
|
||||
if let webPage = self.webPage, case let .Loaded(content) = webPage.content {
|
||||
if content.instantPage != nil {
|
||||
return .instantPage
|
||||
if let webPage = self.webPage, case let .Loaded(content) = webPage.content, content.instantPage != nil {
|
||||
switch instantPageType(of: content) {
|
||||
case .album:
|
||||
return .none
|
||||
default:
|
||||
return .instantPage
|
||||
}
|
||||
}
|
||||
if self.contentNode.hasActionAtPoint(point.offsetBy(dx: -contentNodeFrame.minX, dy: -contentNodeFrame.minY)) {
|
||||
|
||||
@ -65,7 +65,7 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
let contentRightInset: CGFloat = 18.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: 14.0), size: closeButtonSize))
|
||||
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: width - contentRightInset - closeButtonSize.width, y: floorToScreenPixels((panelHeight - closeButtonSize.height) / 2.0)), size: closeButtonSize))
|
||||
|
||||
let updatedButtons: [ChatReportPeerTitleButton]
|
||||
if let _ = interfaceState.renderedPeer?.peer {
|
||||
|
||||
@ -308,16 +308,21 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
self.infoNode.attributedText = string
|
||||
shouldUpdateLayout = true
|
||||
}
|
||||
} else if let peer = peerViewMainPeer(peerView), let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence {
|
||||
} else if let peer = peerViewMainPeer(peerView) {
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: self.strings, timeFormat: self.timeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
let userPresence: TelegramUserPresence
|
||||
if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence {
|
||||
userPresence = presence
|
||||
self.presenceManager?.reset(presence: presence)
|
||||
} else {
|
||||
userPresence = TelegramUserPresence(status: .none)
|
||||
}
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: self.strings, timeFormat: self.timeFormat, presence: userPresence, relativeTo: Int32(timestamp))
|
||||
let attributedString = NSAttributedString(string: string, font: Font.regular(13.0), textColor: activity ? self.theme.rootController.navigationBar.accentTextColor : self.theme.rootController.navigationBar.secondaryTextColor)
|
||||
if self.infoNode.attributedText == nil || !self.infoNode.attributedText!.isEqual(to: attributedString) {
|
||||
self.infoNode.attributedText = attributedString
|
||||
shouldUpdateLayout = true
|
||||
}
|
||||
|
||||
self.presenceManager?.reset(presence: presence)
|
||||
} else {
|
||||
let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)
|
||||
if self.infoNode.attributedText == nil || !self.infoNode.attributedText!.isEqual(to: string) {
|
||||
|
||||
@ -468,12 +468,11 @@ class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
case .none:
|
||||
break
|
||||
case let .presence(presence, timeFormat):
|
||||
if let presence = presence as? TelegramUserPresence {
|
||||
userPresence = presence
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.strings, timeFormat: timeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
statusAttributedString = NSAttributedString(string: string, font: statusFont, textColor: activity ? item.theme.list.itemAccentColor : item.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
let presence = (presence as? TelegramUserPresence) ?? TelegramUserPresence(status: .none)
|
||||
userPresence = presence
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.strings, timeFormat: timeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
statusAttributedString = NSAttributedString(string: string, font: statusFont, textColor: activity ? item.theme.list.itemAccentColor : item.theme.list.itemSecondaryTextColor)
|
||||
case let .addressName(suffix):
|
||||
if let addressName = peer.addressName {
|
||||
let addressNameString = NSAttributedString(string: "@" + addressName, font: statusFont, textColor: item.theme.list.itemAccentColor)
|
||||
|
||||
@ -14,7 +14,7 @@ final class DateSelectionActionSheetController: ActionSheetController {
|
||||
return self._ready
|
||||
}
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, currentValue: Int32, minimumDate: Date? = nil, maximumDate: Date? = nil, emptyTitle: String? = nil, applyValue: @escaping (Int32?) -> Void) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, title: String?, currentValue: Int32, minimumDate: Date? = nil, maximumDate: Date? = nil, emptyTitle: String? = nil, applyValue: @escaping (Int32?) -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
||||
@ -24,6 +24,9 @@ final class DateSelectionActionSheetController: ActionSheetController {
|
||||
|
||||
var updatedValue = currentValue
|
||||
var items: [ActionSheetItem] = []
|
||||
if let title = title {
|
||||
items.append(ActionSheetTextItem(title: title))
|
||||
}
|
||||
items.append(DateSelectionActionSheetItem(strings: strings, currentValue: currentValue, minimumDate: minimumDate, maximumDate: maximumDate, valueChanged: { value in
|
||||
updatedValue = value
|
||||
}))
|
||||
|
||||
@ -315,7 +315,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
func item(_ arguments: DeviceContactInfoControllerArguments) -> ListViewItem {
|
||||
switch self {
|
||||
case let .info(_, theme, strings, peer, state, jobSummary):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, mode: .generic, peer: peer, presence: nil, label: jobSummary, cachedData: nil, state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, mode: .contact, peer: peer, presence: nil, label: jobSummary, cachedData: nil, state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
}, context: nil, call: nil)
|
||||
|
||||
@ -137,6 +137,8 @@ final class FormControllerTextInputItemNode: FormBlockItemNode<FormControllerTex
|
||||
self.textField.textField.returnKeyType = item.returnKeyType
|
||||
}
|
||||
|
||||
self.textField.textField.keyboardAppearance = theme.chatList.searchBarKeyboardColor.keyboardAppearance
|
||||
|
||||
let attributedPlaceholder = NSAttributedString(string: item.placeholder, font: textFont, textColor: theme.list.itemPlaceholderTextColor)
|
||||
if !(self.textField.textField.attributedPlaceholder?.isEqual(to: attributedPlaceholder) ?? false) {
|
||||
self.textField.textField.attributedPlaceholder = attributedPlaceholder
|
||||
|
||||
@ -2,14 +2,14 @@ import Foundation
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
|
||||
enum InstantPageThemeType: Int32 {
|
||||
public enum InstantPageThemeType: Int32 {
|
||||
case light = 0
|
||||
case dark = 1
|
||||
case sepia = 2
|
||||
case gray = 3
|
||||
}
|
||||
|
||||
enum InstantPagePresentationFontSize: Int32 {
|
||||
public enum InstantPagePresentationFontSize: Int32 {
|
||||
case small = 0
|
||||
case standard = 1
|
||||
case large = 2
|
||||
@ -17,36 +17,36 @@ enum InstantPagePresentationFontSize: Int32 {
|
||||
case xxlarge = 4
|
||||
}
|
||||
|
||||
final class InstantPagePresentationSettings: PreferencesEntry, Equatable {
|
||||
static var defaultSettings = InstantPagePresentationSettings(themeType: .light, fontSize: .standard, forceSerif: false, autoNightMode: true)
|
||||
public final class InstantPagePresentationSettings: PreferencesEntry, Equatable {
|
||||
public static var defaultSettings = InstantPagePresentationSettings(themeType: .light, fontSize: .standard, forceSerif: false, autoNightMode: true)
|
||||
|
||||
let themeType: InstantPageThemeType
|
||||
let fontSize: InstantPagePresentationFontSize
|
||||
let forceSerif: Bool
|
||||
let autoNightMode: Bool
|
||||
public var themeType: InstantPageThemeType
|
||||
public var fontSize: InstantPagePresentationFontSize
|
||||
public var forceSerif: Bool
|
||||
public var autoNightMode: Bool
|
||||
|
||||
init(themeType: InstantPageThemeType, fontSize: InstantPagePresentationFontSize, forceSerif: Bool, autoNightMode: Bool) {
|
||||
public init(themeType: InstantPageThemeType, fontSize: InstantPagePresentationFontSize, forceSerif: Bool, autoNightMode: Bool) {
|
||||
self.themeType = themeType
|
||||
self.fontSize = fontSize
|
||||
self.forceSerif = forceSerif
|
||||
self.autoNightMode = autoNightMode
|
||||
}
|
||||
|
||||
init(decoder: PostboxDecoder) {
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.themeType = InstantPageThemeType(rawValue: decoder.decodeInt32ForKey("themeType", orElse: 0))!
|
||||
self.fontSize = InstantPagePresentationFontSize(rawValue: decoder.decodeInt32ForKey("fontSize", orElse: 0))!
|
||||
self.forceSerif = decoder.decodeInt32ForKey("forceSerif", orElse: 0) != 0
|
||||
self.autoNightMode = decoder.decodeInt32ForKey("autoNightMode", orElse: 0) != 0
|
||||
}
|
||||
|
||||
func encode(_ encoder: PostboxEncoder) {
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.themeType.rawValue, forKey: "themeType")
|
||||
encoder.encodeInt32(self.fontSize.rawValue, forKey: "fontSize")
|
||||
encoder.encodeInt32(self.forceSerif ? 1 : 0, forKey: "forceSerif")
|
||||
encoder.encodeInt32(self.autoNightMode ? 1 : 0, forKey: "autoNightMode")
|
||||
}
|
||||
|
||||
func isEqual(to: PreferencesEntry) -> Bool {
|
||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||
if let to = to as? InstantPagePresentationSettings {
|
||||
return self == to
|
||||
} else {
|
||||
@ -54,7 +54,7 @@ final class InstantPagePresentationSettings: PreferencesEntry, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: InstantPagePresentationSettings, rhs: InstantPagePresentationSettings) -> Bool {
|
||||
public static func ==(lhs: InstantPagePresentationSettings, rhs: InstantPagePresentationSettings) -> Bool {
|
||||
if lhs.themeType != rhs.themeType {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -143,6 +143,7 @@ enum ItemListAvatarAndNameInfoItemUpdatingAvatar: Equatable {
|
||||
|
||||
enum ItemListAvatarAndNameInfoItemMode {
|
||||
case generic
|
||||
case contact
|
||||
case settings
|
||||
case editSettings
|
||||
}
|
||||
@ -402,14 +403,15 @@ class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, Ite
|
||||
statusText += "@\(username)"
|
||||
}
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
case .generic, .editSettings:
|
||||
case .generic, .contact, .editSettings:
|
||||
if let label = item.label {
|
||||
statusText = label
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
} else if let _ = peer.botInfo {
|
||||
statusText = item.strings.Bot_GenericBotStatus
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
} else if let presence = item.presence as? TelegramUserPresence {
|
||||
} else if case .generic = item.mode {
|
||||
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))
|
||||
statusText = string
|
||||
|
||||
@ -175,7 +175,7 @@ final class ListMessageSnippetItemNode: ListMessageNode {
|
||||
selectedMedia = webpage
|
||||
|
||||
if case let .Loaded(content) = webpage.content {
|
||||
if content.instantPage != nil {
|
||||
if content.instantPage != nil && instantPageType(of: content) != .album {
|
||||
isInstantView = true
|
||||
}
|
||||
|
||||
|
||||
@ -24,9 +24,9 @@ public enum AudioPlaybackRate: Int32 {
|
||||
}
|
||||
|
||||
public struct MusicPlaybackSettings: PreferencesEntry, Equatable {
|
||||
public let order: MusicPlaybackSettingsOrder
|
||||
public let looping: MusicPlaybackSettingsLooping
|
||||
public let voicePlaybackRate: AudioPlaybackRate
|
||||
public var order: MusicPlaybackSettingsOrder
|
||||
public var looping: MusicPlaybackSettingsLooping
|
||||
public var voicePlaybackRate: AudioPlaybackRate
|
||||
|
||||
public static var defaultSettings: MusicPlaybackSettings {
|
||||
return MusicPlaybackSettings(order: .regular, looping: .none, voicePlaybackRate: .x1)
|
||||
|
||||
@ -15,8 +15,6 @@ public enum PresentationPersonNameOrder {
|
||||
case lastFirst
|
||||
}
|
||||
|
||||
|
||||
|
||||
public final class PresentationData: Equatable {
|
||||
public let strings: PresentationStrings
|
||||
public let theme: PresentationTheme
|
||||
@ -370,3 +368,12 @@ public func updatedPresentationData(postbox: Postbox) -> Signal<PresentationData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func defaultPresentationData() -> PresentationData {
|
||||
let timeFormat = currentTimeFormat()
|
||||
let nameDisplayOrder = currentPersonNameDisplayOrder()
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
|
||||
let themeSettings = PresentationThemeSettings.defaultSettings
|
||||
return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, chatWallpaper: .builtin, fontSize: themeSettings.fontSize, timeFormat: timeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder)
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ struct PresentationResourcesChat {
|
||||
|
||||
static func chatInputPanelEncircledCloseIconImage(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.chatInputPanelEncircledCloseIconImage.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/EncircledCloseButton"), color: theme.chat.serviceMessage.serviceMessagePrimaryTextColor)
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/EncircledCloseButton"), color: theme.chat.inputPanel.panelControlAccentColor)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12,8 +12,9 @@ private final class ProxySettingsControllerArguments {
|
||||
let removeServer: (ProxyServerSettings) -> Void
|
||||
let setServerWithRevealedOptions: (ProxyServerSettings?, ProxyServerSettings?) -> Void
|
||||
let toggleUseForCalls: (Bool) -> Void
|
||||
let shareProxyList: () -> Void
|
||||
|
||||
init(toggleEnabled: @escaping (Bool) -> Void, addNewServer: @escaping () -> Void, activateServer: @escaping (ProxyServerSettings) -> Void, editServer: @escaping (ProxyServerSettings) -> Void, removeServer: @escaping (ProxyServerSettings) -> Void, setServerWithRevealedOptions: @escaping (ProxyServerSettings?, ProxyServerSettings?) -> Void, toggleUseForCalls: @escaping (Bool) -> Void) {
|
||||
init(toggleEnabled: @escaping (Bool) -> Void, addNewServer: @escaping () -> Void, activateServer: @escaping (ProxyServerSettings) -> Void, editServer: @escaping (ProxyServerSettings) -> Void, removeServer: @escaping (ProxyServerSettings) -> Void, setServerWithRevealedOptions: @escaping (ProxyServerSettings?, ProxyServerSettings?) -> Void, toggleUseForCalls: @escaping (Bool) -> Void, shareProxyList: @escaping () -> Void) {
|
||||
self.toggleEnabled = toggleEnabled
|
||||
self.addNewServer = addNewServer
|
||||
self.activateServer = activateServer
|
||||
@ -21,6 +22,7 @@ private final class ProxySettingsControllerArguments {
|
||||
self.removeServer = removeServer
|
||||
self.setServerWithRevealedOptions = setServerWithRevealedOptions
|
||||
self.toggleUseForCalls = toggleUseForCalls
|
||||
self.shareProxyList = shareProxyList
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +54,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
case serversHeader(PresentationTheme, String)
|
||||
case addServer(PresentationTheme, String, Bool)
|
||||
case server(Int, PresentationTheme, PresentationStrings, ProxyServerSettings, Bool, DisplayProxyServerStatus, ProxySettingsServerItemEditing, Bool)
|
||||
case shareProxyList(PresentationTheme, String)
|
||||
case useForCalls(PresentationTheme, String, Bool)
|
||||
case useForCallsInfo(PresentationTheme, String)
|
||||
|
||||
@ -59,7 +62,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
switch self {
|
||||
case .enabled:
|
||||
return ProxySettingsControllerSection.enabled.rawValue
|
||||
case .serversHeader, .addServer, .server:
|
||||
case .serversHeader, .addServer, .server, .shareProxyList:
|
||||
return ProxySettingsControllerSection.servers.rawValue
|
||||
case .useForCalls, .useForCallsInfo:
|
||||
return ProxySettingsControllerSection.calls.rawValue
|
||||
@ -76,10 +79,12 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
return .index(2)
|
||||
case let .server(_, _, _, settings, _, _, _, _):
|
||||
return .server(settings.host, settings.port, settings.connection)
|
||||
case .useForCalls:
|
||||
case .shareProxyList:
|
||||
return .index(3)
|
||||
case .useForCallsInfo:
|
||||
case .useForCalls:
|
||||
return .index(4)
|
||||
case .useForCallsInfo:
|
||||
return .index(5)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +114,12 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .shareProxyList(lhsTheme, lhsText):
|
||||
if case let .shareProxyList(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .useForCalls(lhsTheme, lhsText, lhsValue):
|
||||
if case let .useForCalls(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||
return true
|
||||
@ -156,12 +167,19 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .useForCalls:
|
||||
case .shareProxyList:
|
||||
switch rhs {
|
||||
case .enabled, .serversHeader, .addServer, .server, .useForCalls:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .useForCalls:
|
||||
switch rhs {
|
||||
case .enabled, .serversHeader, .addServer, .server, .shareProxyList, .useForCalls:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .useForCallsInfo:
|
||||
return false
|
||||
@ -181,7 +199,7 @@ 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: editing, action: {
|
||||
return ProxySettingsActionItem(theme: theme, title: text, sectionId: self.section, editing: false, action: {
|
||||
arguments.addNewServer()
|
||||
})
|
||||
case let .server(_, theme, strings, settings, active, status, editing, enabled):
|
||||
@ -194,6 +212,10 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
}, removeServer: { _ in
|
||||
arguments.removeServer(settings)
|
||||
})
|
||||
case let .shareProxyList(theme, text):
|
||||
return ProxySettingsActionItem(theme: theme, title: text, sectionId: self.section, editing: false, action: {
|
||||
arguments.shareProxyList()
|
||||
})
|
||||
case let .useForCalls(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleUseForCalls(value)
|
||||
@ -229,19 +251,32 @@ private func proxySettingsControllerEntries(theme: PresentationTheme, strings: P
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: true)
|
||||
}
|
||||
} else {
|
||||
var text: String
|
||||
switch server.connection {
|
||||
case .socks5:
|
||||
text = strings.ChatSettings_ConnectionType_UseSocks5
|
||||
case .mtp:
|
||||
text = strings.SocksProxySetup_ProxyTelegram
|
||||
}
|
||||
switch status {
|
||||
case .notAvailable:
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: strings.SocksProxySetup_ProxyStatusUnavailable, textActive: false)
|
||||
text = text + ", " + strings.SocksProxySetup_ProxyStatusUnavailable
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: false)
|
||||
case .checking:
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: strings.SocksProxySetup_ProxyStatusChecking, textActive: false)
|
||||
text = text + ", " + strings.SocksProxySetup_ProxyStatusChecking
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: false)
|
||||
case let .available(rtt):
|
||||
let pingTime: Int = Int(rtt * 1000.0)
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0, textActive: false)
|
||||
text = text + ", \(strings.SocksProxySetup_ProxyStatusPing("\(pingTime)").0)"
|
||||
displayStatus = DisplayProxyServerStatus(activity: false, text: text, textActive: false)
|
||||
}
|
||||
}
|
||||
entries.append(.server(index, theme, strings, server, server == proxySettings.activeServer, displayStatus, ProxySettingsServerItemEditing(editable: true, editing: state.editing, revealed: state.revealedServer == server), proxySettings.enabled))
|
||||
index += 1
|
||||
}
|
||||
if !proxySettings.servers.isEmpty {
|
||||
entries.append(.shareProxyList(theme, strings.SocksProxySetup_ShareProxyList))
|
||||
}
|
||||
|
||||
if let activeServer = proxySettings.activeServer, case .socks5 = activeServer.connection {
|
||||
entries.append(.useForCalls(theme, strings.SocksProxySetup_UseForCalls, proxySettings.useForCalls))
|
||||
@ -285,6 +320,8 @@ public func proxySettingsController(postbox: Postbox, network: Network, mode: Pr
|
||||
}
|
||||
}
|
||||
|
||||
var shareProxyListImpl: (() -> Void)?
|
||||
|
||||
let arguments = ProxySettingsControllerArguments(toggleEnabled: { value in
|
||||
let _ = updateProxySettingsInteractively(postbox: postbox, network: network, { current in
|
||||
var current = current
|
||||
@ -332,17 +369,19 @@ public func proxySettingsController(postbox: Postbox, network: Network, mode: Pr
|
||||
current.useForCalls = value
|
||||
return current
|
||||
}).start()
|
||||
}, shareProxyList: {
|
||||
shareProxyListImpl?()
|
||||
})
|
||||
|
||||
let proxySettings = Promise<ProxySettings>()
|
||||
proxySettings.set(postbox.preferencesView(keys: [PreferencesKeys.proxySettings])
|
||||
|> map { preferencesView -> ProxySettings in
|
||||
if let value = preferencesView.values[PreferencesKeys.proxySettings] as? ProxySettings {
|
||||
return value
|
||||
} else {
|
||||
return ProxySettings.defaultSettings
|
||||
}
|
||||
})
|
||||
|> map { preferencesView -> ProxySettings in
|
||||
if let value = preferencesView.values[PreferencesKeys.proxySettings] as? ProxySettings {
|
||||
return value
|
||||
} else {
|
||||
return ProxySettings.defaultSettings
|
||||
}
|
||||
})
|
||||
|
||||
let statusesContext = ProxyServersStatuses(network: network, servers: proxySettings.get()
|
||||
|> map { proxySettings -> [ProxyServerSettings] in
|
||||
@ -444,5 +483,45 @@ public func proxySettingsController(postbox: Postbox, network: Network, mode: Pr
|
||||
return current
|
||||
}).start()
|
||||
}
|
||||
|
||||
shareProxyListImpl = { [weak controller] in
|
||||
guard let strongController = controller else {
|
||||
return
|
||||
}
|
||||
let _ = (proxySettings.get()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { settings in
|
||||
var result = ""
|
||||
for server in settings.servers {
|
||||
if !result.isEmpty {
|
||||
result += "\n\n"
|
||||
}
|
||||
|
||||
var string: String
|
||||
switch server.connection {
|
||||
case let .mtp(secret):
|
||||
let secret = hexString(secret)
|
||||
string = "https://t.me/proxy?server=\(server.host)&port=\(server.port)"
|
||||
string += "&secret=\((secret as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")"
|
||||
case let .socks5(username, password):
|
||||
string = "https://t.me/socks?server=\(server.host)&port=\(server.port)"
|
||||
if let username = username, let password = password {
|
||||
string += "&user=\((username as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")&pass=\((password as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")"
|
||||
}
|
||||
}
|
||||
|
||||
result += string
|
||||
}
|
||||
|
||||
let activityController = UIActivityViewController(activityItems: [result], applicationActivities: nil)
|
||||
|
||||
if let window = strongController.view.window, let rootViewController = window.rootViewController {
|
||||
activityController.popoverPresentationController?.sourceView = window
|
||||
activityController.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint(x: window.bounds.width / 2.0, y: window.bounds.size.height - 1.0), size: CGSize(width: 1.0, height: 1.0))
|
||||
rootViewController.present(activityController, animated: true, completion: nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
@ -268,28 +268,12 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
|
||||
var presentImpl: ((ViewController, Any?) -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
|
||||
var shareImpl: (() -> Void)?
|
||||
|
||||
let arguments = proxyServerSettingsControllerArguments(updateState: { f in
|
||||
updateState(f)
|
||||
}, share: {
|
||||
let state = stateValue.with { $0 }
|
||||
if state.isComplete {
|
||||
let presentationData: (theme: PresentationTheme, strings: PresentationStrings) = (theme, strings)
|
||||
var result: String
|
||||
switch state.mode {
|
||||
case .mtp:
|
||||
result = "https://t.me/proxy?server=\(state.host)&port=\(state.port)"
|
||||
result += "&secret=\((state.secret as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")"
|
||||
case .socks5:
|
||||
result = "https://t.me/socks?server=\(state.host)&port=\(state.port)"
|
||||
if !state.username.isEmpty {
|
||||
result += "&user=\((state.username as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")&pass=\((state.password as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")"
|
||||
}
|
||||
}
|
||||
|
||||
UIPasteboard.general.string = result
|
||||
|
||||
presentImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Username_LinkCopied, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
}
|
||||
shareImpl?()
|
||||
}, usePasteboardSettings: {
|
||||
if let pasteboardSettings = pasteboardSettings {
|
||||
updateState { state in
|
||||
@ -371,6 +355,36 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati
|
||||
dismissImpl = { [weak controller] in
|
||||
let _ = controller?.dismiss()
|
||||
}
|
||||
|
||||
shareImpl = { [weak controller] in
|
||||
guard let strongController = controller else {
|
||||
return
|
||||
}
|
||||
|
||||
let state = stateValue.with { $0 }
|
||||
if state.isComplete {
|
||||
var result: String
|
||||
switch state.mode {
|
||||
case .mtp:
|
||||
result = "https://t.me/proxy?server=\(state.host)&port=\(state.port)"
|
||||
result += "&secret=\((state.secret as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")"
|
||||
case .socks5:
|
||||
result = "https://t.me/socks?server=\(state.host)&port=\(state.port)"
|
||||
if !state.username.isEmpty {
|
||||
result += "&user=\((state.username as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")&pass=\((state.password as NSString).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryValueAllowed) ?? "")"
|
||||
}
|
||||
}
|
||||
|
||||
let activityController = UIActivityViewController(activityItems: [result], applicationActivities: nil)
|
||||
|
||||
if let window = strongController.view.window, let rootViewController = window.rootViewController {
|
||||
activityController.popoverPresentationController?.sourceView = window
|
||||
activityController.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint(x: window.bounds.width / 2.0, y: window.bounds.size.height - 1.0), size: CGSize(width: 1.0, height: 1.0))
|
||||
rootViewController.present(activityController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return controller
|
||||
}
|
||||
|
||||
|
||||
@ -176,7 +176,9 @@ final class SecureIdAuthController: ViewController {
|
||||
|
||||
if appUpdateRequired {
|
||||
let errorText = strongSelf.presentationData.strings.Passport_UpdateRequiredError
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Application_Update, action: {})]), in: .window(.root))
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Application_Update, action: {
|
||||
account.telegramApplicationContext.applicationBindings.openAppStorePage()
|
||||
})]), in: .window(.root))
|
||||
} else if let callbackUrl = callbackUrl, let peerId = peerId {
|
||||
let errorText = strongSelf.presentationData.strings.Login_UnknownError
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
|
||||
@ -724,27 +724,27 @@ final class SecureIdAuthControllerNode: ViewControllerTracingNode {
|
||||
let primaryLanguageByCountry = list.primaryLanguageByCountry ?? [:]
|
||||
switch field {
|
||||
case .personalDetails:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: ParsedRequestedPersonalDetails(nativeNames: true), document: nil, selfie: false, translations: false), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: ParsedRequestedPersonalDetails(nativeNames: false), document: nil, selfie: false, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .passport:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .passport, selfie: true, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .passport, selfie: false, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .internalPassport:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .internalPassport, selfie: true, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .internalPassport, selfie: false, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .driversLicense:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .driversLicense, selfie: true, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .driversLicense, selfie: false, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .idCard:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .idCard, selfie: true, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .passportRegistration:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .passportRegistration, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .temporaryRegistration:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .temporaryRegistration, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .identity(details: nil, document: .idCard, selfie: false, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .address:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: true, document: nil, translations: false), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .utilityBill:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .utilityBill, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .utilityBill, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .bankStatement:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .bankStatement, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .bankStatement, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .rentalAgreement:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .rentalAgreement, translations: true), primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .rentalAgreement, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .passportRegistration:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .passportRegistration, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .temporaryRegistration:
|
||||
strongSelf.interaction.present(SecureIdDocumentFormController(account: strongSelf.account, context: context, requestedData: .address(details: false, document: .temporaryRegistration, translations: false), requestOptionalData: true, primaryLanguageByCountry: primaryLanguageByCountry, values: values, updatedValues: updatedValues(field)), nil)
|
||||
case .phone:
|
||||
break
|
||||
case .email:
|
||||
|
||||
@ -584,17 +584,12 @@ private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings:
|
||||
if let filledDocument = filledDocument, isOneOf {
|
||||
text = stringForDocumentType(filledDocument.0, strings: strings)
|
||||
}
|
||||
if let personalDetails = personalDetails {
|
||||
if let _ = personalDetails {
|
||||
if let value = findValue(values, key: .personalDetails), case let .personalDetails(personalDetailsValue) = value.1.value {
|
||||
if !text.isEmpty {
|
||||
text.append(", ")
|
||||
}
|
||||
let fullName: String
|
||||
if let nativeName = personalDetailsValue.nativeName, !nativeName.firstName.isEmpty, personalDetails.nativeNames {
|
||||
fullName = nativeName.firstName + " " + nativeName.lastName
|
||||
} else {
|
||||
fullName = personalDetailsValue.latinName.firstName + " " + personalDetailsValue.latinName.lastName
|
||||
}
|
||||
let fullName = personalDetailsValue.latinName.firstName + " " + personalDetailsValue.latinName.lastName
|
||||
text.append(fieldsText(fullName, countryName(code: personalDetailsValue.countryCode, strings: strings)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +66,8 @@ final class SecureIdAuthListContentNode: ASDisplayNode, SecureIdAuthContentNode,
|
||||
fieldNode.updateValues(values)
|
||||
}
|
||||
|
||||
self.deleteNode.isHidden = values.isEmpty
|
||||
|
||||
self.requestLayout()
|
||||
}
|
||||
|
||||
|
||||
@ -17,16 +17,18 @@ final class SecureIdDocumentFormController: FormController<SecureIdDocumentFormS
|
||||
|
||||
private let context: SecureIdAccessContext
|
||||
private let requestedData: SecureIdDocumentFormRequestedData
|
||||
private let requestOptionalData: Bool
|
||||
private let primaryLanguageByCountry: [String: String]
|
||||
private var values: [SecureIdValueWithContext]
|
||||
|
||||
private var doneItem: UIBarButtonItem?
|
||||
|
||||
init(account: Account, context: SecureIdAccessContext, requestedData: SecureIdDocumentFormRequestedData, primaryLanguageByCountry: [String: String], values: [SecureIdValueWithContext], updatedValues: @escaping ([SecureIdValueWithContext]) -> Void) {
|
||||
init(account: Account, context: SecureIdAccessContext, requestedData: SecureIdDocumentFormRequestedData, requestOptionalData: Bool = false, primaryLanguageByCountry: [String: String], values: [SecureIdValueWithContext], updatedValues: @escaping ([SecureIdValueWithContext]) -> Void) {
|
||||
self.account = account
|
||||
self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
self.context = context
|
||||
self.requestedData = requestedData
|
||||
self.requestOptionalData = requestOptionalData
|
||||
self.primaryLanguageByCountry = primaryLanguageByCountry
|
||||
self.values = values
|
||||
self.updatedValues = updatedValues
|
||||
@ -132,6 +134,6 @@ final class SecureIdDocumentFormController: FormController<SecureIdDocumentFormS
|
||||
for value in self.values {
|
||||
values[value.value.key] = value
|
||||
}
|
||||
self.controllerNode.updateInnerState(transition: .immediate, with: SecureIdDocumentFormState(requestedData: self.requestedData, values: values, primaryLanguageByCountry: self.primaryLanguageByCountry))
|
||||
self.controllerNode.updateInnerState(transition: .immediate, with: SecureIdDocumentFormState(requestedData: self.requestedData, values: values, requestOptionalData: self.requestOptionalData, primaryLanguageByCountry: self.primaryLanguageByCountry))
|
||||
}
|
||||
}
|
||||
|
||||
@ -433,6 +433,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
fileprivate var translationsRequired: Bool
|
||||
fileprivate var translations: [SecureIdVerificationDocument]
|
||||
fileprivate var actionState: SecureIdDocumentFormActionState
|
||||
fileprivate var requestOptionalData: Bool
|
||||
|
||||
func isEqual(to: SecureIdDocumentFormState) -> Bool {
|
||||
if !self.documentState.isEqual(to: to.documentState) {
|
||||
@ -472,6 +473,9 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if self.requestOptionalData != to.requestOptionalData {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -506,7 +510,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
result.append(.entry(SecureIdDocumentFormEntry.countryCode(.identity, details.countryCode, self.previousValues[.personalDetails]?.errors[.field(.personalDetails(.countryCode))])))
|
||||
result.append(.entry(SecureIdDocumentFormEntry.residenceCountryCode(details.residenceCountryCode, self.previousValues[.personalDetails]?.errors[.field(.personalDetails(.residenceCountryCode))])))
|
||||
|
||||
if details.nativeNameRequired && !details.residenceCountryCode.isEmpty && details.primaryLanguageByCountry[details.residenceCountryCode] != "en" {
|
||||
if (details.nativeNameRequired || self.requestOptionalData) && !details.residenceCountryCode.isEmpty && details.primaryLanguageByCountry[details.residenceCountryCode] != "en" {
|
||||
if let last = result.last, case .spacer = last {
|
||||
} else {
|
||||
result.append(.spacer)
|
||||
@ -561,7 +565,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
result.append(.entry(SecureIdDocumentFormEntry.expiryDate(document.expiryDate, expiryDateError)))
|
||||
}
|
||||
|
||||
if self.selfieRequired || self.frontSideRequired || self.backSideRequired {
|
||||
if (self.selfieRequired || self.requestOptionalData) || self.frontSideRequired || self.backSideRequired {
|
||||
let type = identity.document?.type
|
||||
|
||||
if let last = result.last, case .spacer = last {
|
||||
@ -624,7 +628,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
}
|
||||
}
|
||||
|
||||
if self.selfieRequired {
|
||||
if self.selfieRequired || self.requestOptionalData {
|
||||
if let document = self.selfieDocument {
|
||||
var error: String?
|
||||
if case let .remote(file) = document {
|
||||
@ -655,7 +659,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
result.append(.entry(SecureIdDocumentFormEntry.scansInfo(.identity)))
|
||||
}
|
||||
|
||||
if let document = identity.document, self.translationsRequired {
|
||||
if let document = identity.document, self.translationsRequired || self.requestOptionalData {
|
||||
if let last = result.last, case .spacer = last {
|
||||
} else {
|
||||
result.append(.spacer)
|
||||
@ -846,7 +850,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
result.append(.spacer)
|
||||
}
|
||||
|
||||
if self.translationsRequired, let document = address.document {
|
||||
if let document = address.document, self.translationsRequired || self.requestOptionalData {
|
||||
if let last = result.last, case .spacer = last {
|
||||
} else {
|
||||
result.append(.spacer)
|
||||
@ -1013,7 +1017,7 @@ struct SecureIdDocumentFormState: FormControllerInnerState {
|
||||
}
|
||||
|
||||
extension SecureIdDocumentFormState {
|
||||
init(requestedData: SecureIdDocumentFormRequestedData, values: [SecureIdValueKey: SecureIdValueWithContext], primaryLanguageByCountry: [String: String]) {
|
||||
init(requestedData: SecureIdDocumentFormRequestedData, values: [SecureIdValueKey: SecureIdValueWithContext], requestOptionalData: Bool, primaryLanguageByCountry: [String: String]) {
|
||||
switch requestedData {
|
||||
case let .identity(details, document, selfie, translations):
|
||||
var previousValues: [SecureIdValueKey: SecureIdValueWithContext] = [:]
|
||||
@ -1090,7 +1094,7 @@ extension SecureIdDocumentFormState {
|
||||
documentState = SecureIdDocumentFormIdentityDocumentState(type: document, identifier: identifier, expiryDate: expiryDate)
|
||||
}
|
||||
let formState = SecureIdDocumentFormIdentityState(details: detailsState, document: documentState)
|
||||
self.init(previousValues: previousValues, documentState: .identity(formState), documents: verificationDocuments, selfieRequired: selfie, selfieDocument: selfieDocument, frontSideRequired: frontSideRequired, frontSideDocument: frontSideDocument, backSideRequired: backSideRequired, backSideDocument: backSideDocument, translationsRequired: translations, translations: translationDocuments, actionState: .none)
|
||||
self.init(previousValues: previousValues, documentState: .identity(formState), documents: verificationDocuments, selfieRequired: selfie, selfieDocument: selfieDocument, frontSideRequired: frontSideRequired, frontSideDocument: frontSideDocument, backSideRequired: backSideRequired, backSideDocument: backSideDocument, translationsRequired: translations, translations: translationDocuments, actionState: .none, requestOptionalData: requestOptionalData)
|
||||
case let .address(details, document, translations):
|
||||
var previousValues: [SecureIdValueKey: SecureIdValueWithContext] = [:]
|
||||
var detailsState: SecureIdDocumentFormAddressDetailsState?
|
||||
@ -1142,7 +1146,7 @@ extension SecureIdDocumentFormState {
|
||||
documentState = document
|
||||
}
|
||||
let formState = SecureIdDocumentFormAddressState(details: detailsState, document: documentState)
|
||||
self.init(previousValues: previousValues, documentState: .address(formState), documents: verificationDocuments, selfieRequired: false, selfieDocument: nil, frontSideRequired: false, frontSideDocument: nil, backSideRequired: false, backSideDocument: nil, translationsRequired: translations, translations: translationDocuments, actionState: .none)
|
||||
self.init(previousValues: previousValues, documentState: .address(formState), documents: verificationDocuments, selfieRequired: false, selfieDocument: nil, frontSideRequired: false, frontSideDocument: nil, backSideRequired: false, backSideDocument: nil, translationsRequired: translations, translations: translationDocuments, actionState: .none, requestOptionalData: requestOptionalData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2233,12 +2237,16 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
var maximumDate: Date? = nil
|
||||
let calendar = Calendar(identifier: .gregorian)
|
||||
let now = Date()
|
||||
var title: String? = nil
|
||||
if case .expiry = field {
|
||||
title = strings.Passport_Identity_ExpiryDate
|
||||
emptyTitle = strings.Passport_Identity_DoesNotExpire
|
||||
var deltaComponents = DateComponents()
|
||||
deltaComponents.month = 6
|
||||
minimumDate = calendar.date(byAdding: deltaComponents, to: now)
|
||||
|
||||
} else if case .birthdate = field {
|
||||
title = strings.Passport_Identity_DateOfBirth
|
||||
var components = calendar.dateComponents([.year, .month, .day], from: now)
|
||||
if let year = components.year {
|
||||
components.year = year - 18
|
||||
@ -2248,7 +2256,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
}
|
||||
}
|
||||
|
||||
let controller = DateSelectionActionSheetController(theme: theme, strings: strings, currentValue: current ?? Int32(Date().timeIntervalSince1970), minimumDate: minimumDate, maximumDate: maximumDate, emptyTitle: emptyTitle, applyValue: { value in
|
||||
let controller = DateSelectionActionSheetController(theme: theme, strings: strings, title: title, currentValue: current ?? Int32(Date().timeIntervalSince1970), minimumDate: minimumDate, maximumDate: maximumDate, emptyTitle: emptyTitle, applyValue: { value in
|
||||
if let strongSelf = self, var innerState = strongSelf.innerState {
|
||||
innerState.documentState.updateDateField(type: field, value: value.flatMap(SecureIdDate.init))
|
||||
var valueKey: SecureIdValueKey?
|
||||
|
||||
@ -25,8 +25,9 @@ public final class TelegramApplicationBindings {
|
||||
public let clearMessageNotifications: ([MessageId]) -> Void
|
||||
public let pushIdleTimerExtension: () -> Disposable
|
||||
public let openSettings: () -> Void
|
||||
public let openAppStorePage: () -> Void
|
||||
|
||||
public init(isMainApp: Bool, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal<Bool, NoError>, applicationIsActive: Signal<Bool, NoError>, clearMessageNotifications: @escaping ([MessageId]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void) {
|
||||
public init(isMainApp: Bool, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal<Bool, NoError>, applicationIsActive: Signal<Bool, NoError>, clearMessageNotifications: @escaping ([MessageId]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void, openAppStorePage: @escaping () -> Void) {
|
||||
self.isMainApp = isMainApp
|
||||
self.openUrl = openUrl
|
||||
self.openUniversalUrl = openUniversalUrl
|
||||
@ -38,6 +39,7 @@ public final class TelegramApplicationBindings {
|
||||
self.clearMessageNotifications = clearMessageNotifications
|
||||
self.pushIdleTimerExtension = pushIdleTimerExtension
|
||||
self.openSettings = openSettings
|
||||
self.openAppStorePage = openAppStorePage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ private final class UserInfoControllerArguments {
|
||||
self.openChat = openChat
|
||||
self.addContact = addContact
|
||||
self.shareContact = shareContact
|
||||
self.shareMyContact = shareContact
|
||||
self.shareMyContact = shareMyContact
|
||||
self.startSecretChat = startSecretChat
|
||||
self.changeNotificationMuteSettings = changeNotificationMuteSettings
|
||||
self.changeNotificationSoundSettings = changeNotificationSoundSettings
|
||||
|
||||
@ -91,7 +91,7 @@ private final class WebEmbedVideoContentNode: ASDisplayNode, UniversalVideoConte
|
||||
|
||||
super.init()
|
||||
|
||||
//self.addSubnode(self.playerNode)
|
||||
self.addSubnode(self.playerNode)
|
||||
self.addSubnode(self.imageNode)
|
||||
|
||||
self._preloadCompleted.set(true)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user