Various Improvements

This commit is contained in:
Ilya Laktyushin 2021-11-19 20:42:44 +04:00
parent 15b708791d
commit 3a42a30454
22 changed files with 3141 additions and 239 deletions

View File

@ -7081,3 +7081,7 @@ Sorry for the inconvenience.";
"Conversation.InviteRequestAdminChannel" = "%1$@ is an admin of %2$@, a channel you requested to join.";
"Conversation.InviteRequestInfo" = "You received this message because you requested to join %1$@ on %2$@.";
"Conversation.InviteRequestInfoConfirm" = "I understand";
"AuthSessions.HeaderInfo" = "Link [Telegram Desktop](desktop) or [Telegram Web](web) by scanning a QR code.";
"AuthSessions.LinkDesktopDevice" = "Link Desktop Device";
"AuthSessions.AddDevice.ScanInstallInfo" = "Go to [getdesktop.telegram.org](desktop) or [web.telegram.org](web) to get the QR code";

View File

@ -24,11 +24,12 @@ swift_library(
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/Markdown:Markdown",
"//submodules/AnimationUI:AnimationUI",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/DeviceAccess:DeviceAccess",
"//submodules/UndoUI:UndoUI",
"//submodules/TextFormat:TextFormat",
"//submodules/Markdown:Markdown",
],
visibility = [
"//visibility:public",

View File

@ -11,6 +11,8 @@ import AlertUI
import TelegramPresentationData
import TelegramCore
import UndoUI
import Markdown
import TextFormat
private func parseAuthTransferUrl(_ url: URL) -> Data? {
var tokenString: String?
@ -160,7 +162,7 @@ public final class AuthTransferScanScreen: ViewController {
}
override public func loadDisplayNode() {
self.displayNode = AuthTransferScanScreenNode(presentationData: self.presentationData)
self.displayNode = AuthTransferScanScreenNode(context: self.context, presentationData: self.presentationData)
self.displayNodeDidLoad()
@ -210,6 +212,7 @@ public final class AuthTransferScanScreen: ViewController {
}
private final class AuthTransferScanScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
private let context: AccountContext
private var presentationData: PresentationData
private let previewNode: CameraPreviewNode
@ -246,7 +249,10 @@ private final class AuthTransferScanScreenNode: ViewControllerTracingNode, UIScr
}
}
init(presentationData: PresentationData) {
private var highlightViews: [UIVisualEffectView] = []
init(context: AccountContext, presentationData: PresentationData) {
self.context = context
self.presentationData = presentationData
self.previewNode = CameraPreviewNode()
@ -287,11 +293,22 @@ private final class AuthTransferScanScreenNode: ViewControllerTracingNode, UIScr
self.titleNode.maximumNumberOfLines = 0
self.titleNode.textAlignment = .center
let textFont = Font.regular(17.0)
let boldFont = Font.bold(17.0)
var text = presentationData.strings.AuthSessions_AddDevice_ScanInstallInfo
text = text.replacingOccurrences(of: " [", with: " [").replacingOccurrences(of: "]() ", with: "]() ")
let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: .white), bold: MarkdownAttributeSet(font: boldFont, textColor: .white), link: MarkdownAttributeSet(font: boldFont, textColor: .white), linkAttribute: { contents in
return (TelegramTextAttributes.URL, contents)
})))
self.textNode = ImmediateTextNode()
self.textNode.displaysAsynchronously = false
self.textNode.attributedText = NSAttributedString(string: presentationData.strings.AuthSessions_AddDevice_ScanInfo, font: Font.regular(16.0), textColor: .white)
self.textNode.attributedText = attributedText
self.textNode.maximumNumberOfLines = 0
self.textNode.textAlignment = .center
self.textNode.lineSpacing = 0.5
self.errorTextNode = ImmediateTextNode()
self.errorTextNode.displaysAsynchronously = false
@ -377,6 +394,39 @@ private final class AuthTransferScanScreenNode: ViewControllerTracingNode, UIScr
strongSelf.updateFocusedRect(nil)
}
}))
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
recognizer.tapActionAtPoint = { _ in
return .waitForSingleTap
}
self.textNode.view.addGestureRecognizer(recognizer)
}
@objc private func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
switch recognizer.state {
case .ended:
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
switch gesture {
case .tap:
if let (_, attributes) = self.textNode.attributesAtPoint(location) {
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
switch url {
case "desktop":
self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: "https://getdesktop.telegram.org", forceExternal: true, presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {})
case "web":
self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: "https://web.telegram.org", forceExternal: true, presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {})
default:
break
}
}
}
default:
break
}
}
default:
break
}
}
func updateFocusedRect(_ rect: CGRect?) {
@ -466,6 +516,19 @@ private final class AuthTransferScanScreenNode: ViewControllerTracingNode, UIScr
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
transition.updateFrameAdditive(node: self.errorTextNode, frame: errorTextFrame)
if self.highlightViews.isEmpty {
let urlAttributesAndRects = self.textNode.cachedLayout?.allAttributeRects(name: "UrlAttributeT") ?? []
for (_, rect) in urlAttributesAndRects {
let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
view.clipsToBounds = true
view.layer.cornerRadius = 5.0
view.frame = rect.offsetBy(dx: self.textNode.frame.minX, dy: self.textNode.frame.minY).insetBy(dx: -4.0, dy: -2.0)
self.view.insertSubview(view, belowSubview: self.textNode.view)
self.highlightViews.append(view)
}
}
}
@objc private func torchPressed() {

View File

@ -564,8 +564,16 @@ public final class TextNodeLayout: NSObject {
rightOffset = ceil(secondaryOffset)
}
}
var lineFrame = CGRect(origin: CGPoint(x: line.frame.origin.x, y: line.frame.origin.y - line.frame.size.height + self.firstLineOffset), size: line.frame.size)
lineFrame = displayLineFrame(frame: lineFrame, isRTL: line.isRTL, boundingRect: CGRect(origin: CGPoint(), size: self.size), cutout: self.cutout)
switch self.resolvedAlignment {
case .center:
lineFrame.origin.x = floor((self.size.width - lineFrame.size.width) / 2.0)
case .natural:
lineFrame = displayLineFrame(frame: lineFrame, isRTL: line.isRTL, boundingRect: CGRect(origin: CGPoint(), size: self.size), cutout: self.cutout)
default:
break
}
let rect = CGRect(origin: CGPoint(x: lineFrame.minX + min(leftOffset, rightOffset) + self.insets.left, y: lineFrame.minY + self.insets.top), size: CGSize(width: abs(rightOffset - leftOffset), height: lineFrame.size.height))
if coveringRect.isEmpty {

View File

@ -110,7 +110,7 @@ final class ItemListRecentSessionItem: ListViewItem, ItemListItem {
}
}
func iconForSession(_ session: RecentAccountSession) -> (UIImage?, UIColor?, String?, [String: UIColor]?) {
func iconForSession(_ session: RecentAccountSession) -> (UIImage?, UIColor?, String?, [String]?) {
let platform = session.platform.lowercased()
let device = session.deviceModel.lowercased()
let systemVersion = session.systemVersion.lowercased()
@ -118,7 +118,7 @@ func iconForSession(_ session: RecentAccountSession) -> (UIImage?, UIColor?, Str
return (UIImage(bundleImageName: "Settings/Devices/Xbox"), UIColor(rgb: 0x35c759), nil, nil)
}
if device.contains("chrome") && !device.contains("chromebook") {
return (UIImage(bundleImageName: "Settings/Devices/Chrome"), UIColor(rgb: 0x35c759), "device_chrome", nil)
return (UIImage(bundleImageName: "Settings/Devices/Chrome"), UIColor(rgb: 0x35c759), "device_chrome", ["Vector 20.Vector 20.Обводка 1", "Ellipse 18.Ellipse 18.Обводка 1"])
}
if device.contains("brave") {
return (UIImage(bundleImageName: "Settings/Devices/Brave"), UIColor(rgb: 0xff9500), nil, nil)
@ -127,7 +127,7 @@ func iconForSession(_ session: RecentAccountSession) -> (UIImage?, UIColor?, Str
return (UIImage(bundleImageName: "Settings/Devices/Vivaldi"), UIColor(rgb: 0xff3c30), nil, nil)
}
if device.contains("safari") {
return (UIImage(bundleImageName: "Settings/Devices/Safari"), UIColor(rgb: 0x0079ff), "device_safari", nil)
return (UIImage(bundleImageName: "Settings/Devices/Safari"), UIColor(rgb: 0x0079ff), "device_safari", ["Com 2.Com 2.Заливка 1"])
}
if device.contains("firefox") {
return (UIImage(bundleImageName: "Settings/Devices/Firefox"), UIColor(rgb: 0xff9500), "device_firefox", nil)
@ -139,7 +139,7 @@ func iconForSession(_ session: RecentAccountSession) -> (UIImage?, UIColor?, Str
return (UIImage(bundleImageName: "Settings/Devices/Android"), UIColor(rgb: 0x35c759), "device_android", nil)
}
if device.contains("iphone") {
return (UIImage(bundleImageName: "Settings/Devices/iPhone"), UIColor(rgb: 0x0079ff), "device_iphone", nil)
return (UIImage(bundleImageName: "Settings/Devices/iPhone"), UIColor(rgb: 0x0079ff), "device_iphone", ["apple.apple.Заливка 1"])
}
if device.contains("ipad") {
return (UIImage(bundleImageName: "Settings/Devices/iPad"), UIColor(rgb: 0x0079ff), "device_ipad", nil)
@ -490,6 +490,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode {
case .sameSection(false):
bottomStripeInset = leftInset + editingOffset
bottomStripeOffset = -separatorHeight
strongSelf.bottomStripeNode.isHidden = false
default:
bottomStripeInset = 0.0
bottomStripeOffset = 0.0

View File

@ -11,6 +11,7 @@ import PresentationDataUtils
import AccountContext
import AuthTransferUI
import ItemListPeerActionItem
import DeviceAccess
private final class RecentSessionsControllerArguments {
let context: AccountContext
@ -315,8 +316,19 @@ private enum RecentSessionsEntry: ItemListNodeEntry {
let arguments = arguments as! RecentSessionsControllerArguments
switch self {
case let .header(_, text):
return RecentSessionsHeaderItem(context: arguments.context, theme: presentationData.theme, text: text, animationName: "Requests", sectionId: self.section, linkAction: { _ in
arguments.openDesktopLink()
return RecentSessionsHeaderItem(context: arguments.context, theme: presentationData.theme, text: text, animationName: "Requests", sectionId: self.section, buttonAction: {
arguments.addDevice()
}, linkAction: { action in
if case let .tap(link) = action {
switch link {
case "desktop":
arguments.openDesktopLink()
case "web":
arguments.openWebLink()
default:
break
}
}
})
case let .currentSessionHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
@ -453,44 +465,46 @@ private struct RecentSessionsControllerState: Equatable {
private func recentSessionsControllerEntries(presentationData: PresentationData, state: RecentSessionsControllerState, sessionsState: ActiveSessionsContextState, enableQRLogin: Bool) -> [RecentSessionsEntry] {
var entries: [RecentSessionsEntry] = []
entries.append(.header(SortIndex(section: 0, item: 0), presentationData.strings.AuthSessions_HeaderInfo))
if !sessionsState.sessions.isEmpty {
var existingSessionIds = Set<Int64>()
entries.append(.currentSessionHeader(SortIndex(section: 0, item: 0), presentationData.strings.AuthSessions_CurrentSession))
entries.append(.currentSessionHeader(SortIndex(section: 1, item: 0), presentationData.strings.AuthSessions_CurrentSession))
if let index = sessionsState.sessions.firstIndex(where: { $0.hash == 0 }) {
existingSessionIds.insert(sessionsState.sessions[index].hash)
entries.append(.currentSession(SortIndex(section: 0, item: 1), presentationData.strings, presentationData.dateTimeFormat, sessionsState.sessions[index]))
entries.append(.currentSession(SortIndex(section: 1, item: 1), presentationData.strings, presentationData.dateTimeFormat, sessionsState.sessions[index]))
}
var hasAddDevice = false
if sessionsState.sessions.count > 1 || enableQRLogin {
if sessionsState.sessions.count > 1 {
entries.append(.terminateOtherSessions(SortIndex(section: 0, item: 2), presentationData.strings.AuthSessions_TerminateOtherSessions))
entries.append(.currentSessionInfo(SortIndex(section: 0, item: 3), presentationData.strings.AuthSessions_TerminateOtherSessionsHelp))
entries.append(.terminateOtherSessions(SortIndex(section: 1, item: 2), presentationData.strings.AuthSessions_TerminateOtherSessions))
entries.append(.currentSessionInfo(SortIndex(section: 1, item: 3), presentationData.strings.AuthSessions_TerminateOtherSessionsHelp))
} else if enableQRLogin {
hasAddDevice = true
entries.append(.currentAddDevice(SortIndex(section: 0, item: 4), presentationData.strings.AuthSessions_AddDevice))
entries.append(.currentSessionInfo(SortIndex(section: 0, item: 5), presentationData.strings.AuthSessions_OtherDevices))
// entries.append(.currentAddDevice(SortIndex(section: 1, item: 4), presentationData.strings.AuthSessions_AddDevice))
entries.append(.currentSessionInfo(SortIndex(section: 1, item: 5), presentationData.strings.AuthSessions_OtherDevices))
}
let filteredPendingSessions: [RecentAccountSession] = sessionsState.sessions.filter({ $0.flags.contains(.passwordPending) })
if !filteredPendingSessions.isEmpty {
entries.append(.pendingSessionsHeader(SortIndex(section: 0, item: 6), presentationData.strings.AuthSessions_IncompleteAttempts))
entries.append(.pendingSessionsHeader(SortIndex(section: 1, item: 6), presentationData.strings.AuthSessions_IncompleteAttempts))
for i in 0 ..< filteredPendingSessions.count {
if !existingSessionIds.contains(filteredPendingSessions[i].hash) {
existingSessionIds.insert(filteredPendingSessions[i].hash)
entries.append(.pendingSession(index: Int32(i), sortIndex: SortIndex(section: 1, item: i), strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, session: filteredPendingSessions[i], enabled: state.removingSessionId != filteredPendingSessions[i].hash && !state.terminatingOtherSessions, editing: state.editing, revealed: state.sessionIdWithRevealedOptions == filteredPendingSessions[i].hash))
entries.append(.pendingSession(index: Int32(i), sortIndex: SortIndex(section: 2, item: i), strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, session: filteredPendingSessions[i], enabled: state.removingSessionId != filteredPendingSessions[i].hash && !state.terminatingOtherSessions, editing: state.editing, revealed: state.sessionIdWithRevealedOptions == filteredPendingSessions[i].hash))
}
}
entries.append(.pendingSessionsInfo(SortIndex(section: 2, item: 0), presentationData.strings.AuthSessions_IncompleteAttemptsInfo))
entries.append(.pendingSessionsInfo(SortIndex(section: 3, item: 0), presentationData.strings.AuthSessions_IncompleteAttemptsInfo))
}
if sessionsState.sessions.count > 1 {
entries.append(.otherSessionsHeader(SortIndex(section: 3, item: 0), presentationData.strings.AuthSessions_OtherSessions))
entries.append(.otherSessionsHeader(SortIndex(section: 4, item: 0), presentationData.strings.AuthSessions_OtherSessions))
}
if enableQRLogin && !hasAddDevice {
entries.append(.addDevice(SortIndex(section: 3, item: 1), presentationData.strings.AuthSessions_AddDevice))
}
// if enableQRLogin && !hasAddDevice {
// entries.append(.addDevice(SortIndex(section: 4, item: 1), presentationData.strings.AuthSessions_AddDevice))
// }
let filteredSessions: [RecentAccountSession] = sessionsState.sessions.sorted(by: { lhs, rhs in
return lhs.activityDate > rhs.activityDate
@ -499,17 +513,17 @@ private func recentSessionsControllerEntries(presentationData: PresentationData,
for i in 0 ..< filteredSessions.count {
if !existingSessionIds.contains(filteredSessions[i].hash) {
existingSessionIds.insert(filteredSessions[i].hash)
entries.append(.session(index: Int32(i), sortIndex: SortIndex(section: 4, item: i), strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, session: filteredSessions[i], enabled: state.removingSessionId != filteredSessions[i].hash && !state.terminatingOtherSessions, editing: state.editing, revealed: state.sessionIdWithRevealedOptions == filteredSessions[i].hash))
entries.append(.session(index: Int32(i), sortIndex: SortIndex(section: 5, item: i), strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, session: filteredSessions[i], enabled: state.removingSessionId != filteredSessions[i].hash && !state.terminatingOtherSessions, editing: state.editing, revealed: state.sessionIdWithRevealedOptions == filteredSessions[i].hash))
}
}
if enableQRLogin && !hasAddDevice {
entries.append(.devicesInfo(SortIndex(section: 5, item: 0), presentationData.strings.AuthSessions_OtherDevices))
entries.append(.devicesInfo(SortIndex(section: 6, item: 0), presentationData.strings.AuthSessions_OtherDevices))
}
}
entries.append(.ttlHeader(SortIndex(section: 6, item: 0), presentationData.strings.AuthSessions_TerminateIfAwayTitle.uppercased()))
entries.append(.ttlTimeout(SortIndex(section: 6, item: 1), presentationData.strings.AuthSessions_TerminateIfAwayFor, timeIntervalString(strings: presentationData.strings, value: sessionsState.ttlDays * 24 * 60 * 60)))
entries.append(.ttlHeader(SortIndex(section: 7, item: 0), presentationData.strings.AuthSessions_TerminateIfAwayTitle.uppercased()))
entries.append(.ttlTimeout(SortIndex(section: 7, item: 1), presentationData.strings.AuthSessions_TerminateIfAwayFor, timeIntervalString(strings: presentationData.strings, value: sessionsState.ttlDays * 24 * 60 * 60)))
}
return entries
@ -730,7 +744,18 @@ public func recentSessionsController(context: AccountContext, activeSessionsCont
])
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, addDevice: {
pushControllerImpl?(AuthDataTransferSplashScreen(context: context, activeSessionsContext: activeSessionsContext))
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
DeviceAccess.authorizeAccess(to: .camera(.video), presentationData: presentationData, present: { c, a in
c.presentationArguments = a
context.sharedContext.mainWindow?.present(c, on: .root)
}, openSettings: {
context.sharedContext.applicationBindings.openSettings()
}, { granted in
guard granted else {
return
}
pushControllerImpl?(AuthTransferScanScreen(context: context, activeSessionsContext: activeSessionsContext))
})
}, openOtherAppsUrl: {
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: "https://desktop.telegram.org", forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {})
}, setupAuthorizationTTL: {
@ -760,9 +785,9 @@ public func recentSessionsController(context: AccountContext, activeSessionsCont
])
presentControllerImpl?(controller, nil)
}, openDesktopLink: {
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: "https://getdesktop.telegram.org", forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {})
}, openWebLink: {
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: "https://web.telegram.org", forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {})
})
let previousMode = Atomic<RecentSessionsMode>(value: .sessions)

View File

@ -11,6 +11,7 @@ import TelegramAnimatedStickerNode
import AccountContext
import Markdown
import TextFormat
import SolidRoundedButtonNode
class RecentSessionsHeaderItem: ListViewItem, ItemListItem {
let context: AccountContext
@ -18,14 +19,16 @@ class RecentSessionsHeaderItem: ListViewItem, ItemListItem {
let text: String
let animationName: String
let sectionId: ItemListSectionId
let buttonAction: () -> Void
let linkAction: ((ItemListTextItemLinkAction) -> Void)?
init(context: AccountContext, theme: PresentationTheme, text: String, animationName: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) {
init(context: AccountContext, theme: PresentationTheme, text: String, animationName: String, sectionId: ItemListSectionId, buttonAction: @escaping () -> Void, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) {
self.context = context
self.theme = theme
self.text = text
self.animationName = animationName
self.sectionId = sectionId
self.buttonAction = buttonAction
self.linkAction = linkAction
}
@ -71,21 +74,25 @@ private let titleFont = Font.regular(13.0)
class RecentSessionsHeaderItemNode: ListViewItemNode {
private let titleNode: TextNode
private var animationNode: AnimatedStickerNode
private let buttonNode: SolidRoundedButtonNode
private var item: RecentSessionsHeaderItem?
init() {
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false
self.titleNode.isUserInteractionEnabled = true
self.titleNode.contentMode = .left
self.titleNode.contentsScale = UIScreen.main.scale
self.animationNode = AnimatedStickerNode()
self.buttonNode = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(backgroundColor: .black, foregroundColor: .white), fontSize: 16.0, height: 50.0, cornerRadius: 11.0)
super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.titleNode)
self.addSubnode(self.animationNode)
self.addSubnode(self.buttonNode)
}
override public func didLoad() {
@ -95,23 +102,36 @@ class RecentSessionsHeaderItemNode: ListViewItemNode {
recognizer.tapActionAtPoint = { _ in
return .waitForSingleTap
}
self.view.addGestureRecognizer(recognizer)
self.titleNode.view.addGestureRecognizer(recognizer)
self.buttonNode.pressed = { [weak self] in
if let strongSelf = self, let item = strongSelf.item {
item.buttonAction()
}
}
}
func asyncLayout() -> (_ item: RecentSessionsHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let currentItem = self.item
return { item, params, neighbors in
var updatedTheme: PresentationTheme?
let leftInset: CGFloat = 32.0 + params.leftInset
let topInset: CGFloat = 92.0
if currentItem?.theme !== item.theme {
updatedTheme = item.theme
}
let attributedText = parseMarkdownIntoAttributedString(item.text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), link: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.itemAccentColor), linkAttribute: { contents in
return (TelegramTextAttributes.URL, contents)
}))
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
let contentSize = CGSize(width: params.width, height: topInset + titleLayout.size.height)
let contentSize = CGSize(width: params.width, height: topInset + titleLayout.size.height + 85.0)
let insets = itemListNeighborsGroupedInsets(neighbors, params)
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
@ -123,6 +143,18 @@ class RecentSessionsHeaderItemNode: ListViewItemNode {
strongSelf.animationNode.visibility = true
}
strongSelf.item = item
strongSelf.buttonNode.title = item.context.sharedContext.currentPresentationData.with { $0 }.strings.AuthSessions_LinkDesktopDevice
if let _ = updatedTheme {
strongSelf.buttonNode.icon = generateTintedImage(image: UIImage(bundleImageName: "Settings/QrButtonIcon"), color: .white)
strongSelf.buttonNode.updateTheme(SolidRoundedButtonTheme(theme: item.theme))
}
let buttonWidth = contentSize.width - 32.0
let buttonHeight = strongSelf.buttonNode.updateLayout(width: buttonWidth, transition: .immediate)
let buttonFrame = CGRect(x: 16.0, y: contentSize.height - buttonHeight - 12.0, width: buttonWidth, height: buttonHeight)
strongSelf.buttonNode.frame = buttonFrame
strongSelf.accessibilityLabel = attributedText.string
let iconSize = CGSize(width: 96.0, height: 96.0)
@ -150,9 +182,8 @@ class RecentSessionsHeaderItemNode: ListViewItemNode {
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
switch gesture {
case .tap:
let titleFrame = self.titleNode.frame
if let item = self.item, titleFrame.contains(location) {
if let (_, attributes) = self.titleNode.attributesAtPoint(CGPoint(x: location.x - titleFrame.minX, y: location.y - titleFrame.minY)) {
if let item = self.item {
if let (_, attributes) = self.titleNode.attributesAtPoint(location) {
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
item.linkAction?(.tap(url))
}

View File

@ -305,9 +305,15 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
location = session.country
ip = session.ip
let (icon, backgroundColor, animationName, colors) = iconForSession(session)
let (icon, backgroundColor, animationName, colorsArray) = iconForSession(session)
if let animationName = animationName {
let animationNode = AnimationNode(animation: animationName, colors: colors ?? ["apple.apple.Заливка 1": backgroundColor ?? .black], scale: 1.0)
var colors: [String: UIColor] = [:]
if let colorsArray = colorsArray {
for color in colorsArray {
colors[color] = backgroundColor
}
}
let animationNode = AnimationNode(animation: animationName, colors: colors, scale: 1.0)
self.animationNode = animationNode
animationNode.animationView()?.logHierarchyKeypaths()

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "scanphoto_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,183 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 5.335022 5.334961 cm
0.000000 0.000000 0.000000 scn
3.837526 19.330017 m
3.865001 19.330017 l
5.665000 19.330017 l
6.032270 19.330017 6.330000 19.032286 6.330000 18.665016 c
6.330000 18.297747 6.032270 18.000015 5.665000 18.000015 c
3.865001 18.000015 l
3.293975 18.000015 2.905700 17.999498 2.605557 17.974976 c
2.313177 17.951088 2.163464 17.907776 2.058923 17.854509 c
1.807727 17.726519 1.603498 17.522289 1.475507 17.271093 c
1.422241 17.166552 1.378929 17.016840 1.355040 16.724461 c
1.330518 16.424316 1.330001 16.036041 1.330001 15.465015 c
1.330001 13.665016 l
1.330001 13.297747 1.032270 13.000015 0.665001 13.000015 c
0.297731 13.000015 0.000001 13.297747 0.000001 13.665016 c
0.000001 15.465015 l
0.000000 15.492491 l
-0.000008 16.029188 -0.000015 16.472036 0.029457 16.832764 c
0.060066 17.207392 0.125747 17.551617 0.290468 17.874901 c
0.545971 18.376352 0.953664 18.784046 1.455116 19.039549 c
1.778399 19.204269 2.122624 19.269951 2.497252 19.300558 c
2.857971 19.330030 3.300807 19.330025 3.837486 19.330017 c
3.837526 19.330017 l
h
15.465000 18.000015 m
16.036026 18.000015 16.424301 17.999498 16.724443 17.974976 c
17.016825 17.951088 17.166536 17.907776 17.271078 17.854509 c
17.522274 17.726519 17.726503 17.522289 17.854494 17.271093 c
17.907759 17.166552 17.951071 17.016840 17.974960 16.724461 c
17.999483 16.424316 18.000000 16.036041 18.000000 15.465015 c
18.000000 13.665016 l
18.000000 13.297747 18.297731 13.000015 18.664999 13.000015 c
19.032270 13.000015 19.330000 13.297747 19.330000 13.665016 c
19.330000 15.465015 l
19.330000 15.492499 l
19.330000 15.492572 l
19.330008 16.029232 19.330013 16.472054 19.300543 16.832764 c
19.269934 17.207392 19.204252 17.551617 19.039532 17.874901 c
18.784029 18.376352 18.376337 18.784046 17.874884 19.039549 c
17.551601 19.204269 17.207376 19.269951 16.832748 19.300558 c
16.472031 19.330030 16.029194 19.330025 15.492514 19.330017 c
15.492474 19.330017 l
15.465000 19.330017 l
13.665000 19.330017 l
13.297730 19.330017 13.000000 19.032286 13.000000 18.665016 c
13.000000 18.297747 13.297730 18.000015 13.665000 18.000015 c
15.465000 18.000015 l
h
0.665001 6.330016 m
1.032270 6.330016 1.330001 6.032286 1.330001 5.665016 c
1.330001 3.865016 l
1.330001 3.293991 1.330518 2.905716 1.355040 2.605572 c
1.378929 2.313192 1.422241 2.163479 1.475507 2.058939 c
1.603498 1.807743 1.807727 1.603514 2.058923 1.475523 c
2.163464 1.422256 2.313177 1.378944 2.605557 1.355057 c
2.905700 1.330534 3.293975 1.330017 3.865001 1.330017 c
5.665000 1.330017 l
6.032270 1.330017 6.330000 1.032286 6.330000 0.665016 c
6.330000 0.297747 6.032270 0.000015 5.665000 0.000015 c
3.865001 0.000015 l
3.837517 0.000015 l
3.837445 0.000015 l
3.300784 0.000008 2.857962 0.000002 2.497252 0.029472 c
2.122624 0.060081 1.778399 0.125763 1.455116 0.290483 c
0.953664 0.545986 0.545971 0.953680 0.290468 1.455132 c
0.125747 1.778414 0.060066 2.122639 0.029457 2.497269 c
-0.000015 2.857996 -0.000008 3.300844 0.000000 3.837542 c
0.000001 3.865016 l
0.000001 5.665016 l
0.000001 6.032286 0.297731 6.330016 0.665001 6.330016 c
h
18.664999 6.330016 m
19.032270 6.330016 19.330000 6.032286 19.330000 5.665016 c
19.330000 3.865016 l
19.330000 3.837533 l
19.330000 3.837461 l
19.330008 3.300798 19.330013 2.857977 19.300543 2.497269 c
19.269934 2.122639 19.204252 1.778414 19.039532 1.455132 c
18.784029 0.953680 18.376337 0.545986 17.874884 0.290483 c
17.551601 0.125763 17.207376 0.060081 16.832748 0.029472 c
16.472040 0.000002 16.029215 0.000008 15.492555 0.000015 c
15.492483 0.000015 l
15.465000 0.000015 l
13.665000 0.000015 l
13.297730 0.000015 13.000000 0.297747 13.000000 0.665016 c
13.000000 1.032286 13.297730 1.330017 13.665000 1.330017 c
15.465000 1.330017 l
16.036026 1.330017 16.424301 1.330534 16.724443 1.355057 c
17.016825 1.378944 17.166536 1.422256 17.271078 1.475523 c
17.522274 1.603514 17.726503 1.807743 17.854494 2.058939 c
17.907759 2.163479 17.951071 2.313192 17.974960 2.605572 c
17.999483 2.905716 18.000000 3.293991 18.000000 3.865016 c
18.000000 5.665016 l
18.000000 6.032286 18.297731 6.330016 18.664999 6.330016 c
h
4.665000 14.330015 m
4.297731 14.330015 4.000000 14.032285 4.000000 13.665015 c
4.000000 13.297746 4.297731 13.000015 4.665000 13.000015 c
14.665001 13.000015 l
15.032270 13.000015 15.330000 13.297746 15.330000 13.665015 c
15.330000 14.032285 15.032270 14.330015 14.665001 14.330015 c
4.665000 14.330015 l
h
4.000000 9.665016 m
4.000000 10.032286 4.297731 10.330016 4.665000 10.330016 c
14.665001 10.330016 l
15.032270 10.330016 15.330000 10.032286 15.330000 9.665016 c
15.330000 9.297747 15.032270 9.000016 14.665001 9.000016 c
4.665000 9.000016 l
4.297731 9.000016 4.000000 9.297747 4.000000 9.665016 c
h
4.665000 6.330016 m
4.297731 6.330016 4.000000 6.032286 4.000000 5.665016 c
4.000000 5.297747 4.297731 5.000016 4.665000 5.000016 c
10.665001 5.000016 l
11.032270 5.000016 11.330000 5.297747 11.330000 5.665016 c
11.330000 6.032286 11.032270 6.330016 10.665001 6.330016 c
4.665000 6.330016 l
h
f*
n
Q
endstream
endobj
3 0 obj
5057
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000005147 00000 n
0000005170 00000 n
0000005343 00000 n
0000005417 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
5476
%%EOF

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "Icon-9.pdf",
"filename" : "devices_30.pdf",
"idiom" : "universal"
}
],

View File

@ -1,168 +0,0 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
1.000000 0.584314 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 4.913940 6.000000 cm
1.000000 1.000000 1.000000 scn
6.886106 17.665039 m
6.857284 17.665039 l
6.041643 17.665045 5.388978 17.665051 4.861559 17.621958 c
4.320179 17.577724 3.852469 17.484795 3.422230 17.265577 c
2.732616 16.914202 2.171942 16.353529 1.820566 15.663914 c
1.601349 15.233675 1.508419 14.765965 1.464186 14.224585 c
1.421094 13.697165 1.421099 13.044500 1.421105 12.228861 c
1.421105 12.200039 l
1.421105 8.200039 l
1.421105 8.172565 l
1.421096 7.635868 1.421089 7.193019 1.450562 6.832291 c
1.481171 6.457663 1.546852 6.113438 1.711573 5.790154 c
1.967075 5.288702 2.374769 4.881009 2.876221 4.625506 c
3.199503 4.460786 3.543729 4.395104 3.918357 4.364496 c
4.279082 4.335024 4.721926 4.335031 5.258616 4.335039 c
5.258646 4.335039 l
5.286105 4.335039 l
14.886106 4.335039 l
14.913565 4.335039 l
14.913593 4.335039 l
15.450286 4.335031 15.893129 4.335024 16.253853 4.364496 c
16.628483 4.395104 16.972706 4.460786 17.295990 4.625506 c
17.797443 4.881009 18.205135 5.288702 18.460638 5.790154 c
18.625359 6.113438 18.691040 6.457663 18.721649 6.832291 c
18.751122 7.193022 18.751116 7.635876 18.751106 8.172580 c
18.751106 8.200039 l
18.751106 12.200039 l
18.751106 12.228846 l
18.751106 12.228909 l
18.751112 13.044527 18.751116 13.697176 18.708025 14.224586 c
18.663792 14.765965 18.570862 15.233675 18.351645 15.663914 c
18.000267 16.353529 17.439594 16.914202 16.749981 17.265577 c
16.319742 17.484795 15.852033 17.577724 15.310652 17.621958 c
14.783233 17.665051 14.130567 17.665045 13.314927 17.665039 c
13.286105 17.665039 l
6.886106 17.665039 l
h
4.026037 16.080540 m
4.237534 16.188301 4.510732 16.258862 4.969863 16.296375 c
5.436759 16.334522 6.035054 16.335039 6.886106 16.335039 c
13.286105 16.335039 l
14.137157 16.335039 14.735452 16.334522 15.202347 16.296375 c
15.661479 16.258862 15.934677 16.188301 16.146173 16.080540 c
16.585531 15.856675 16.942741 15.499465 17.166607 15.060106 c
17.274368 14.848610 17.344929 14.575413 17.382442 14.116281 c
17.420589 13.649385 17.421104 13.051090 17.421104 12.200039 c
17.421104 8.200039 l
17.421104 7.629013 17.420589 7.240738 17.396065 6.940596 c
17.372177 6.648215 17.328865 6.498503 17.275600 6.393962 c
17.147608 6.142765 16.943378 5.938537 16.692183 5.810545 c
16.587643 5.757279 16.437929 5.713967 16.145550 5.690079 c
15.845406 5.665556 15.457130 5.665039 14.886106 5.665039 c
5.286105 5.665039 l
4.715079 5.665039 4.326805 5.665556 4.026661 5.690079 c
3.734282 5.713967 3.584569 5.757279 3.480028 5.810545 c
3.228832 5.938537 3.024603 6.142765 2.896612 6.393962 c
2.843346 6.498503 2.800034 6.648215 2.776145 6.940596 c
2.751623 7.240739 2.751105 7.629014 2.751105 8.200039 c
2.751105 12.200039 l
2.751105 13.051090 2.751623 13.649385 2.789769 14.116281 c
2.827282 14.575413 2.897842 14.848610 3.005605 15.060106 c
3.229469 15.499465 3.586679 15.856675 4.026037 16.080540 c
h
1.181526 2.574744 m
1.086058 2.499991 0.997261 2.411195 0.819668 2.233602 c
0.382109 1.796042 0.163330 1.577263 0.088082 1.409702 c
-0.147629 0.884821 0.107125 0.269789 0.644945 0.065315 c
0.816637 0.000038 1.126038 0.000038 1.744839 0.000038 c
18.427372 0.000038 l
19.046173 0.000038 19.355574 0.000038 19.527266 0.065315 c
20.065086 0.269789 20.319839 0.884821 20.084129 1.409702 c
20.008881 1.577263 19.790102 1.796042 19.352543 2.233602 c
19.174950 2.411195 19.086153 2.499991 18.990685 2.574744 c
18.703798 2.799378 18.360996 2.941372 17.999296 2.985391 c
17.878931 3.000039 17.753353 3.000039 17.502199 3.000039 c
2.670012 3.000039 l
2.418857 3.000039 2.293280 3.000039 2.172915 2.985391 c
1.811215 2.941372 1.468413 2.799378 1.181526 2.574744 c
h
f*
n
Q
endstream
endobj
3 0 obj
4601
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000004691 00000 n
0000004714 00000 n
0000004887 00000 n
0000004961 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
5020
%%EOF

View File

@ -0,0 +1,197 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
1.000000 0.584314 0.000000 scn
0.000000 18.799999 m
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
18.799999 30.000000 l
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
30.000000 11.200001 l
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
11.200000 0.000000 l
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
0.000000 18.799999 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 3.000000 6.000000 cm
1.000000 1.000000 1.000000 scn
16.161457 18.000000 m
16.200003 18.000000 l
18.800001 18.000000 l
18.838547 18.000000 l
18.838587 18.000000 l
19.100807 18.000008 19.345118 18.000015 19.570555 17.996254 c
19.613386 17.998739 19.656548 18.000000 19.700001 18.000000 c
20.000000 18.000000 l
20.000000 17.982378 l
20.067238 17.978825 20.132259 17.974556 20.195030 17.969427 c
20.590374 17.937126 20.983593 17.865810 21.361973 17.673018 c
21.926458 17.385397 22.385401 16.926455 22.673021 16.361969 c
22.865814 15.983589 22.937132 15.590370 22.969433 15.195025 c
23.000034 14.820482 23.000019 14.365762 23.000002 13.838665 c
23.000002 13.838642 l
23.000002 13.838520 l
23.000002 13.799997 l
23.000002 4.199997 l
23.000002 4.161474 l
23.000002 4.161351 l
23.000002 4.161328 l
23.000019 3.634233 23.000034 3.179511 22.969433 2.804969 c
22.937132 2.409624 22.865814 2.016405 22.673021 1.638027 c
22.385401 1.073540 21.926458 0.614599 21.361973 0.326979 c
20.983593 0.134184 20.590374 0.062868 20.195030 0.030567 c
19.820463 -0.000036 19.365707 -0.000021 18.838568 -0.000002 c
18.800001 -0.000002 l
16.200001 -0.000002 l
16.161434 -0.000002 l
15.634295 -0.000021 15.179541 -0.000036 14.804974 0.030567 c
14.409629 0.062868 14.016410 0.134184 13.638030 0.326979 c
13.073545 0.614599 12.614602 1.073540 12.326982 1.638027 c
12.134189 2.016405 12.062872 2.409624 12.030571 2.804969 c
11.999968 3.179541 11.999983 3.634304 12.000001 4.161453 c
12.000002 4.199997 l
12.000002 13.799997 l
12.000001 13.838541 l
11.999983 14.365690 11.999968 14.820454 12.030571 15.195025 c
12.062872 15.590370 12.134189 15.983589 12.326982 16.361969 c
12.614602 16.926455 13.073545 17.385397 13.638030 17.673018 c
14.016410 17.865810 14.409629 17.937126 14.804974 17.969427 c
14.867743 17.974556 14.932764 17.978825 15.000000 17.982378 c
15.000000 18.000000 l
15.300000 18.000000 l
15.343454 18.000000 15.386614 17.998739 15.429445 17.996254 c
15.654883 18.000015 15.899194 18.000008 16.161417 18.000000 c
16.161457 18.000000 l
h
15.347795 15.994253 m
15.202957 15.990751 15.078601 15.985120 14.967837 15.976070 c
14.696175 15.953875 14.595455 15.916197 14.546011 15.891004 c
14.357849 15.795131 14.204868 15.642150 14.108995 15.453988 c
14.083802 15.404544 14.046124 15.303825 14.023930 15.032162 c
14.000779 14.748824 14.000002 14.376551 14.000002 13.799997 c
14.000002 4.199997 l
14.000002 3.623444 14.000779 3.251170 14.023930 2.967833 c
14.046124 2.696170 14.083802 2.595450 14.108995 2.546006 c
14.204868 2.357844 14.357849 2.204864 14.546011 2.108991 c
14.595455 2.083797 14.696175 2.046120 14.967837 2.023924 c
15.251175 2.000774 15.623448 1.999998 16.200001 1.999998 c
18.800001 1.999998 l
19.376554 1.999998 19.748829 2.000774 20.032166 2.023924 c
20.303829 2.046120 20.404549 2.083797 20.453993 2.108991 c
20.642155 2.204864 20.795135 2.357844 20.891008 2.546006 c
20.916201 2.595450 20.953878 2.696170 20.976074 2.967833 c
20.999224 3.251170 21.000002 3.623444 21.000002 4.199997 c
21.000002 13.799997 l
21.000002 14.376551 20.999224 14.748824 20.976074 15.032162 c
20.953878 15.303825 20.916201 15.404544 20.891008 15.453988 c
20.795135 15.642150 20.642155 15.795131 20.453993 15.891004 c
20.404549 15.916197 20.303829 15.953875 20.032166 15.976070 c
19.921402 15.985120 19.797045 15.990751 19.652206 15.994253 c
19.564827 15.972827 19.500000 15.893984 19.500000 15.799999 c
19.500000 15.082029 18.917971 14.499999 18.200001 14.499999 c
16.799999 14.499999 l
16.082029 14.499999 15.500000 15.082029 15.500000 15.799999 c
15.500000 15.893984 15.435173 15.972827 15.347795 15.994253 c
h
11.002338 3.999994 m
4.000000 3.999994 l
4.000000 11.799995 l
4.000000 12.376549 4.000778 12.748822 4.023927 13.032160 c
4.046123 13.303823 4.083800 13.404542 4.108994 13.453985 c
4.204867 13.642148 4.357847 13.795128 4.546010 13.891002 c
4.595453 13.916195 4.696173 13.953873 4.967836 13.976068 c
5.251173 13.999218 5.623446 13.999995 6.200000 13.999995 c
11.002338 13.999995 l
11.009203 14.882974 11.036217 15.502047 11.142521 15.999995 c
6.200000 15.999995 l
6.161456 15.999998 l
6.161379 15.999998 l
6.161356 15.999998 l
5.634249 16.000013 5.179520 16.000027 4.804972 15.969426 c
4.409627 15.937125 4.016408 15.865808 3.638028 15.673015 c
3.073542 15.385395 2.614601 14.926454 2.326981 14.361967 c
2.134186 13.983587 2.062871 13.590368 2.030570 13.195024 c
1.999966 12.820452 1.999981 12.365690 1.999999 11.838545 c
1.999999 11.838540 l
2.000000 11.799995 l
2.000000 3.999996 l
0.500000 3.999996 l
0.223858 3.999996 0.000000 3.776138 0.000000 3.499996 c
0.000000 2.671569 0.671573 1.999998 1.500000 1.999998 c
2.000000 1.999996 l
3.000000 1.999996 l
11.142523 1.999996 l
11.036218 2.497943 11.009203 3.117016 11.002338 3.999994 c
h
f*
n
Q
endstream
endobj
3 0 obj
5712
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000005802 00000 n
0000005825 00000 n
0000005998 00000 n
0000006072 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
6131
%%EOF

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "qrbutton_24.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7557,6 +7557,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.updateChatPresentationInterfaceState(interactive: true, {
return $0.updatedShowSendAsPeers(true)
})
}, presentChatRequestAdminInfo: { [weak self] in
self?.presentChatRequestAdminInfo()
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get(), inlineSearch: self.performingInlineSearch.get()))
do {
@ -13871,26 +13873,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
private func presentChatRequestAdminInfo() {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
let text = ""
items.append(ActionSheetTextItem(title: text))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_InviteRequestInfoConfirm, color: .accent, action: { [weak self, weak controller] in
controller?.dismissAnimated()
self?.interfaceInteraction?.dismissReportPeer()
}))
controller.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak controller] in
if let requestChatPeer = self.presentationInterfaceState.contactStatus?.requestChatPeer, let requestDate = self.presentationInterfaceState.contactStatus?.peerStatusSettings?.requestChatDate {
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationData: presentationData)
var items: [ActionSheetItem] = []
let text = presentationData.strings.Conversation_InviteRequestInfo(EnginePeer(requestChatPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), stringForDate(timestamp: requestDate, strings: presentationData.strings))
items.append(ActionSheetTextItem(title: text.string))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_InviteRequestInfoConfirm, color: .accent, action: { [weak self, weak controller] in
controller?.dismissAnimated()
})
])])
controller.setItemGroups([])
self.chatDisplayNode.dismissInput()
self.push(controller)
self?.interfaceInteraction?.dismissReportPeer()
}))
controller.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak controller] in
controller?.dismissAnimated()
})
])])
self.chatDisplayNode.dismissInput()
self.present(controller, in: .window(.root))
}
}
private var crossfading = false

View File

@ -135,6 +135,7 @@ final class ChatPanelInterfaceInteraction {
let updateShowSendAsPeers: ((Bool) -> Bool) -> Void
let openInviteRequests: () -> Void
let openSendAsPeer: (ASDisplayNode, ContextGesture?) -> Void
let presentChatRequestAdminInfo: () -> Void
let statuses: ChatPanelInterfaceInteractionStatuses?
init(
@ -224,6 +225,7 @@ final class ChatPanelInterfaceInteraction {
updateShowSendAsPeers: @escaping ((Bool) -> Bool) -> Void,
openInviteRequests: @escaping () -> Void,
openSendAsPeer: @escaping (ASDisplayNode, ContextGesture?) -> Void,
presentChatRequestAdminInfo: @escaping () -> Void,
statuses: ChatPanelInterfaceInteractionStatuses?
) {
self.setupReplyMessage = setupReplyMessage
@ -312,6 +314,7 @@ final class ChatPanelInterfaceInteraction {
self.updateShowSendAsPeers = updateShowSendAsPeers
self.openInviteRequests = openInviteRequests
self.openSendAsPeer = openSendAsPeer
self.presentChatRequestAdminInfo = presentChatRequestAdminInfo
self.statuses = statuses
}
@ -407,6 +410,7 @@ final class ChatPanelInterfaceInteraction {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {
}, statuses: nil)
}
}

View File

@ -148,7 +148,7 @@ final class ChatRecentActionsController: TelegramBaseController {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, statuses: nil)
}, presentChatRequestAdminInfo: {}, statuses: nil)
self.navigationItem.titleView = self.titleView

View File

@ -311,6 +311,8 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
private var inviteInfoNode: ChatInfoTitlePanelInviteInfoNode?
private var peerNearbyInfoNode: ChatInfoTitlePanelPeerNearbyInfoNode?
private var tapGestureRecognizer: UITapGestureRecognizer?
override init() {
self.separatorNode = ASDisplayNode()
self.separatorNode.isLayerBacked = true
@ -320,6 +322,8 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
self.closeButton.displaysAsynchronously = false
self.textNode = ImmediateTextNode()
self.textNode.maximumNumberOfLines = 2
self.textNode.textAlignment = .center
super.init()
@ -330,6 +334,19 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
self.addSubnode(self.closeButton)
}
override func didLoad() {
super.didLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapped))
tapGestureRecognizer.isEnabled = false
self.view.addGestureRecognizer(tapGestureRecognizer)
self.tapGestureRecognizer = tapGestureRecognizer
}
@objc func tapped() {
self.interfaceInteraction?.presentChatRequestAdminInfo()
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> LayoutResult {
if interfaceState.theme !== self.theme {
self.theme = interfaceState.theme
@ -342,9 +359,6 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
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))
let updatedButtons: [ChatReportPeerTitleButton]
if let _ = interfaceState.renderedPeer?.peer {
updatedButtons = peerButtons(interfaceState)
@ -434,8 +448,8 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
if let requestChatPeer = interfaceState.contactStatus?.requestChatPeer, let renderedPeer = interfaceState.renderedPeer, let peer = renderedPeer.chatMainPeer {
let text: NSAttributedString
let regular = MarkdownAttributeSet(font: Font.regular(14.0), textColor: interfaceState.theme.rootController.navigationBar.primaryTextColor)
let bold = MarkdownAttributeSet(font: Font.bold(14.0), textColor: interfaceState.theme.rootController.navigationBar.primaryTextColor)
let regular = MarkdownAttributeSet(font: Font.regular(15.0), textColor: interfaceState.theme.rootController.navigationBar.primaryTextColor)
let bold = MarkdownAttributeSet(font: Font.bold(15.0), textColor: interfaceState.theme.rootController.navigationBar.primaryTextColor)
if let requestChatPeer = requestChatPeer as? TelegramChannel, case .broadcast = requestChatPeer.info {
text = addAttributesToStringWithRanges(interfaceState.strings.Conversation_InviteRequestAdminChannel(EnginePeer(peer).compactDisplayTitle, EnginePeer(requestChatPeer).displayTitle(strings: interfaceState.strings, displayOrder: interfaceState.nameDisplayOrder))._tuple, body: regular, argumentAttributes: [0: bold, 1: bold])
} else {
@ -445,19 +459,29 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
transition.updateAlpha(node: self.textNode, alpha: 1.0)
let textSize = self.textNode.updateLayout(CGSize(width: width - leftInset - rightInset - 40.0, height: 40.0))
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - textSize.width) / 2.0), y: 4.0), size: textSize)
let textSize = self.textNode.updateLayout(CGSize(width: width - leftInset - rightInset - 80.0, height: 40.0))
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - textSize.width) / 2.0), y: 10.0), size: textSize)
for (_, view) in self.buttons {
transition.updateAlpha(layer: view.layer, alpha: 0.0)
}
self.tapGestureRecognizer?.isEnabled = true
panelHeight += 15.0
} else {
transition.updateAlpha(node: self.textNode, alpha: 0.0)
for (_, view) in self.buttons {
transition.updateAlpha(layer: view.layer, alpha: 1.0)
}
self.tapGestureRecognizer?.isEnabled = false
}
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))
let initialPanelHeight = panelHeight
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))

View File

@ -337,7 +337,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, statuses: nil)
}, presentChatRequestAdminInfo: {}, statuses: nil)
self.selectionPanel.interfaceInteraction = interfaceInteraction

View File

@ -304,7 +304,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, statuses: nil)
}, presentChatRequestAdminInfo: {}, statuses: nil)
self.readyValue.set(self.chatListNode.ready)
}