Peers Nearby improvements

This commit is contained in:
Ilya Laktyushin 2019-06-20 03:41:03 +02:00
parent 6fad8ccc17
commit 8d723f1c45
21 changed files with 2607 additions and 2897 deletions

View File

@ -4425,7 +4425,6 @@ Any member of this group will be able to see messages in the channel.";
"Channel.AdminLog.MessageTransferedNameUsername" = "transferred ownership to %1$@ (%2$@)";
"Channel.AdminLog.MessageChangedGroupGeoLocation" = "changed group location to \"%@\"";
"Channel.AdminLog.MessageRemovedGroupGeoLocation" = "%@ removed group location";
"Map.SetThisLocation" = "Set This Location";
@ -4450,6 +4449,6 @@ Any member of this group will be able to see messages in the channel.";
"Group.PublicLink.Title" = "Public Link";
"Group.PublicLink.Placeholder" = "link";
"Group.PublicLink.Info" = "People can share this link with others and find your group using Telegram search.\n\nYou can use use **a-z**, **0-9** and undescores. Minimum length is **5** characters.";
"Group.PublicLink.Info" = "People can share this link with others and find your group using Telegram search.\n\nYou can use **a-z**, **0-9** and underscores. Minimum length is **5** characters.";
"CreateGroup.ErrorLocatedGroupsTooMuch" = "Sorry, you have too many location-based groups already. Please delete one of your existing ones first.";

View File

@ -31,6 +31,8 @@ public final class PeersNearbyContext {
private var entries: [PeerNearby]?
public init(network: Network, accountStateManager: AccountStateManager, coordinate: (latitude: Double, longitude: Double)) {
let expiryThreshold: Double = 10.0
self.disposable.set((network.request(Api.functions.contacts.getLocated(geoPoint: .inputGeoPoint(lat: coordinate.latitude, long: coordinate.longitude)))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
@ -62,8 +64,8 @@ public final class PeersNearbyContext {
}
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
var entries = strongSelf.entries?.filter { Double($0.expires) > timestamp } ?? []
let updatedEntries = updatedEntries.filter { Double($0.expires) > timestamp }
var entries = strongSelf.entries?.filter { Double($0.expires) + expiryThreshold > timestamp } ?? []
let updatedEntries = updatedEntries.filter { Double($0.expires) + expiryThreshold > timestamp }
var existingPeerIds: [PeerId: Int] = [:]
for i in 0 ..< entries.count {
@ -91,7 +93,7 @@ public final class PeersNearbyContext {
}
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
strongSelf.entries = strongSelf.entries?.filter { Double($0.expires) > timestamp }
strongSelf.entries = strongSelf.entries?.filter { Double($0.expires) + expiryThreshold > timestamp }
}, queue: self.queue)
self.timer?.start()
}

View File

@ -305,13 +305,10 @@ func apiEntitiesFromMessageTextEntities(_ entities: [MessageTextEntity], associa
break
case .Strikethrough:
apiEntities.append(.messageEntityStrike(offset: offset, length: length))
break
case .BlockQuote:
apiEntities.append(.messageEntityBlockquote(offset: offset, length: length))
break
case .Underline:
apiEntities.append(.messageEntityUnderline(offset: offset, length: length))
break
case .Custom:
break
}

View File

@ -72,8 +72,6 @@ apple_library(
'TelegramUI/DeviceProximityManager.h',
'TelegramUI/RaiseToListenActivator.h',
'TelegramUI/TGMimeTypeMap.h',
'TelegramUI/TGEmojiSuggestions.h',
'TelegramUI/TGChannelIntroController.h',
'TelegramUI/EDSunriseSet.h',
'TelegramUI/TGBridgeAudioDecoder.h',
'TelegramUI/TGBridgeAudioEncoder.h',

View File

@ -949,14 +949,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(isAdmin: false, isContact: false)))
} else {
appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_MessageRemovedGroupGeoLocation(author?.displayTitle ?? ""), generateEntities: { index in
if index == 0, let author = author {
return [.TextMention(peerId: author.id)]
}
return []
}, to: &text, entities: &entities)
} else {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])

View File

@ -11,6 +11,7 @@ struct ChatTextInputAttributes {
static let bold = NSAttributedStringKey(rawValue: "Attribute__Bold")
static let italic = NSAttributedStringKey(rawValue: "Attribute__Italic")
static let monospace = NSAttributedStringKey(rawValue: "Attribute__Monospace")
static let strikethrough = NSAttributedStringKey(rawValue: "Attribute__Strikethrough")
static let textMention = NSAttributedStringKey(rawValue: "Attribute__TextMention")
static let textUrl = NSAttributedStringKey(rawValue: "Attribute__TextUrl")
}
@ -23,7 +24,7 @@ func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttributedStr
for (key, value) in attributes {
if key == ChatTextInputAttributes.textMention || key == ChatTextInputAttributes.textUrl {
result.addAttribute(key, value: value, range: range)
} else if key == ChatTextInputAttributes.bold || key == ChatTextInputAttributes.italic || key == ChatTextInputAttributes.monospace {
} else if key == ChatTextInputAttributes.bold || key == ChatTextInputAttributes.italic || key == ChatTextInputAttributes.monospace || key == ChatTextInputAttributes.strikethrough {
result.addAttribute(key, value: value, range: range)
}
}
@ -37,7 +38,6 @@ private struct FontAttributes: OptionSet {
static let bold = FontAttributes(rawValue: 1 << 0)
static let italic = FontAttributes(rawValue: 1 << 1)
static let monospace = FontAttributes(rawValue: 1 << 2)
static let strikethrough = FontAttributes(rawValue: 1 << 3)
}
func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor) -> NSAttributedString {
@ -66,13 +66,20 @@ func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize:
} else if key == ChatTextInputAttributes.monospace {
result.addAttribute(key, value: value, range: range)
fontAttributes.insert(.monospace)
} else if key == ChatTextInputAttributes.strikethrough {
result.addAttribute(key, value: value, range: range)
result.addAttribute(NSAttributedStringKey.strikethroughStyle, value: NSUnderlineStyle.styleSingle.rawValue as NSNumber, range: range)
}
}
if !fontAttributes.isEmpty {
var font: UIFont?
if fontAttributes == [.bold, .italic, .monospace] {
font = Font.semiboldItalicMonospace(fontSize)
} else if fontAttributes == [.bold, .monospace] {
font = Font.semiboldMonospace(fontSize)
} else if fontAttributes == [.italic, .monospace] {
font = Font.italicMonospace(fontSize)
} else if fontAttributes == [.bold, .italic] {
font = Font.semiboldItalic(fontSize)
} else if fontAttributes == [.bold] {
@ -384,7 +391,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed
}
func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat) {
guard var initialAttributedText = textNode.attributedText, initialAttributedText.length != 0 else {
guard let initialAttributedText = textNode.attributedText, initialAttributedText.length != 0 else {
return
}
@ -406,6 +413,7 @@ func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: Prese
textNode.textView.textStorage.removeAttribute(NSAttributedStringKey.font, range: fullRange)
textNode.textView.textStorage.removeAttribute(NSAttributedStringKey.foregroundColor, range: fullRange)
textNode.textView.textStorage.removeAttribute(NSAttributedStringKey.underlineStyle, range: fullRange)
textNode.textView.textStorage.removeAttribute(NSAttributedStringKey.strikethroughStyle, range: fullRange)
textNode.textView.textStorage.removeAttribute(ChatTextInputAttributes.textMention, range: fullRange)
textNode.textView.textStorage.removeAttribute(ChatTextInputAttributes.textUrl, range: fullRange)
@ -432,6 +440,9 @@ func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: Prese
} else if key == ChatTextInputAttributes.monospace {
textNode.textView.textStorage.addAttribute(key, value: value, range: range)
fontAttributes.insert(.monospace)
} else if key == ChatTextInputAttributes.strikethrough {
textNode.textView.textStorage.addAttribute(key, value: value, range: range)
textNode.textView.textStorage.addAttribute(NSAttributedStringKey.strikethroughStyle, value: NSUnderlineStyle.styleSingle.rawValue as NSNumber, range: range)
}
}
@ -492,8 +503,8 @@ func chatTextInputAddFormattingAttribute(_ state: ChatTextInputState, attribute:
for (key, _) in attributes {
if key == attribute && range == nsRange {
addAttribute = false
attributesToRemove.append(key)
}
attributesToRemove.append(key)
}
}
@ -634,7 +645,7 @@ func breakChatInputText(_ text: NSAttributedString) -> [NSAttributedString] {
}
}
private let markdownRegexFormat = "(^|\\s|\\n)(````?)([\\s\\S]+?)(````?)([\\s\\n\\.,:?!;]|$)|(^|\\s)(`|\\*\\*|__)([^\\n]+?)\\7([\\s\\.,:?!;]|$)|@(\\d+)\\s*\\((.+?)\\)"
private let markdownRegexFormat = "(^|\\s|\\n)(````?)([\\s\\S]+?)(````?)([\\s\\n\\.,:?!;]|$)|(^|\\s)(`|\\*\\*|__|~~)([^\\n]+?)\\7([\\s\\.,:?!;]|$)|@(\\d+)\\s*\\((.+?)\\)"
private let markdownRegex = try? NSRegularExpression(pattern: markdownRegexFormat, options: [.caseInsensitive, .anchorsMatchLines])
func convertMarkdownToAttributes(_ text: NSAttributedString) -> NSAttributedString {
@ -678,6 +689,9 @@ func convertMarkdownToAttributes(_ text: NSAttributedString) -> NSAttributedStri
case "__":
result.append(NSAttributedString(string: substring, attributes: [ChatTextInputAttributes.italic: true as NSNumber]))
offsetRanges.append((NSMakeRange(matchIndex + match.range(at: 6).length, text.count), match.range(at: 6).length * 2))
case "~~":
result.append(NSAttributedString(string: substring, attributes: [ChatTextInputAttributes.strikethrough: true as NSNumber]))
offsetRanges.append((NSMakeRange(matchIndex + match.range(at: 6).length, text.count), match.range(at: 6).length * 2))
default:
break
}

View File

@ -855,7 +855,7 @@ final class ContactListNode: ASDisplayNode {
var authorizeImpl: (() -> Void)?
var openPrivacyPolicyImpl: (() -> Void)?
self.authorizationNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: UIImage(bundleImageName: "Settings/Permissions/Contacts"), title: self.presentationData.strings.Contacts_PermissionsTitle, text: self.presentationData.strings.Contacts_PermissionsText, buttonTitle: self.presentationData.strings.Contacts_PermissionsAllow, buttonAction: {
self.authorizationNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: .image(UIImage(bundleImageName: "Settings/Permissions/Contacts")), title: self.presentationData.strings.Contacts_PermissionsTitle, text: self.presentationData.strings.Contacts_PermissionsText, buttonTitle: self.presentationData.strings.Contacts_PermissionsAllow, buttonAction: {
authorizeImpl?()
}, openPrivacyPolicy: {
openPrivacyPolicyImpl?()
@ -1261,7 +1261,7 @@ final class ContactListNode: ASDisplayNode {
let authorizationPreviousHidden = strongSelf.authorizationNode.isHidden
strongSelf.authorizationNode.removeFromSupernode()
strongSelf.authorizationNode = PermissionContentNode(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: UIImage(bundleImageName: "Settings/Permissions/Contacts"), title: strongSelf.presentationData.strings.Contacts_PermissionsTitle, text: strongSelf.presentationData.strings.Contacts_PermissionsText, buttonTitle: strongSelf.presentationData.strings.Contacts_PermissionsAllow, buttonAction: {
strongSelf.authorizationNode = PermissionContentNode(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, kind: PermissionKind.contacts.rawValue, icon: .image(UIImage(bundleImageName: "Settings/Permissions/Contacts")), title: strongSelf.presentationData.strings.Contacts_PermissionsTitle, text: strongSelf.presentationData.strings.Contacts_PermissionsText, buttonTitle: strongSelf.presentationData.strings.Contacts_PermissionsAllow, buttonAction: {
authorizeImpl?()
}, openPrivacyPolicy: {
openPrivacyPolicyImpl?()

View File

@ -132,6 +132,8 @@ func generateChatInputTextEntities(_ text: NSAttributedString) -> [MessageTextEn
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Italic))
} else if key == ChatTextInputAttributes.monospace {
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Code))
} else if key == ChatTextInputAttributes.strikethrough {
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Strikethrough))
} else if key == ChatTextInputAttributes.textMention, let value = value as? ChatTextInputTextMentionAttribute {
entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .TextMention(peerId: value.peerId)))
} else if key == ChatTextInputAttributes.textUrl, let value = value as? ChatTextInputTextUrlAttribute {

View File

@ -184,13 +184,14 @@ class ItemListAddressItemNode: ListViewItemNode {
let string = stringWithAppliedEntities(item.text, entities: [], baseColor: baseColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, fixedFont: textFixedFont)
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset - 98.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var padding: CGFloat = !item.label.isEmpty ? 39.0 : 20.0
let contentSize = CGSize(width: params.width, height: textLayout.size.height + padding)
let padding: CGFloat = !item.label.isEmpty ? 39.0 : 20.0
let imageSide = min(90.0, contentSize.height - 18.0)
let imageSide = min(90.0, max(46.0, textLayout.size.height + padding - 18.0))
let imageSize = CGSize(width: imageSide, height: imageSide)
let imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: 4.0), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))
let contentSize = CGSize(width: params.width, height: max(textLayout.size.height + padding, imageSize.height + 18.0))
let nodeLayout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
return (nodeLayout, { [weak self] animation in
if let strongSelf = self {

View File

@ -19,15 +19,17 @@ class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let text: String
let multiline: Bool
let activityIndicator: Bool
let accessoryText: ItemListSectionHeaderAccessoryText?
let sectionId: ItemListSectionId
let isAlwaysPlain: Bool = true
init(theme: PresentationTheme, text: String, multiline: Bool = false, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
init(theme: PresentationTheme, text: String, multiline: Bool = false, activityIndicator: Bool = false, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
self.theme = theme
self.text = text
self.multiline = multiline
self.activityIndicator = activityIndicator
self.accessoryText = accessoryText
self.sectionId = sectionId
}
@ -72,8 +74,11 @@ class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
private let titleFont = Font.regular(14.0)
class ItemListSectionHeaderItemNode: ListViewItemNode {
private var item: ItemListSectionHeaderItem?
private let titleNode: TextNode
private let accessoryTextNode: TextNode
private var activityIndicator: ActivityIndicator?
private let activateArea: AccessibilityAreaNode
@ -102,6 +107,8 @@ class ItemListSectionHeaderItemNode: ListViewItemNode {
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let makeAccessoryTextLayout = TextNode.asyncLayout(self.accessoryTextNode)
let previousItem = self.item
return { item, params, neighbors in
let leftInset: CGFloat = 15.0 + params.leftInset
@ -136,6 +143,8 @@ class ItemListSectionHeaderItemNode: ListViewItemNode {
return (layout, { [weak self] in
if let strongSelf = self {
strongSelf.item = item
let _ = titleApply()
let _ = accessoryApply()
@ -144,6 +153,31 @@ class ItemListSectionHeaderItemNode: ListViewItemNode {
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 7.0), size: titleLayout.size)
strongSelf.accessoryTextNode.frame = CGRect(origin: CGPoint(x: params.width - leftInset - accessoryLayout.size.width, y: 7.0), size: accessoryLayout.size)
if previousItem?.activityIndicator != item.activityIndicator {
if item.activityIndicator {
let activityIndicator: ActivityIndicator
if let currentActivityIndicator = strongSelf.activityIndicator {
activityIndicator = currentActivityIndicator
} else {
activityIndicator = ActivityIndicator(type: .custom(item.theme.list.sectionHeaderTextColor, 18.0, 1.0, false))
strongSelf.addSubnode(activityIndicator)
strongSelf.activityIndicator = activityIndicator
}
activityIndicator.isHidden = false
if previousItem != nil {
activityIndicator.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
} else if let activityIndicator = strongSelf.activityIndicator {
activityIndicator.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, completion: { finished in
if finished {
activityIndicator.isHidden = true
}
})
}
}
strongSelf.activityIndicator?.frame = CGRect(origin: CGPoint(x: strongSelf.titleNode.frame.maxX + 6.0, y: 7.0 - UIScreenPixel), size: CGSize(width: 18.0, height: 18.0))
}
})
}

View File

@ -1,31 +0,0 @@
import Foundation
import TelegramCore
import Display
import TelegramPresentationData
import TelegramUIPrivateModule
func legacyChannelIntroController(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) -> ViewController {
let controller = LegacyController(presentation: .custom, theme: theme)
controller.bind(controller: TGChannelIntroController(context: controller.context, getLocalizedString: { string in
guard let string = string else {
return nil
}
if let value = strings.primaryComponent.dict[string] {
return value
} else if let value = strings.secondaryComponent?.dict[string] {
return value
} else {
return string
}
}, theme: TGChannelIntroControllerTheme(backgroundColor: theme.list.plainBackgroundColor, primaryColor: theme.list.itemPrimaryTextColor, secondaryColor: theme.list.itemSecondaryTextColor, accentColor: theme.list.itemAccentColor, backArrowImage: NavigationBarTheme.generateBackArrowImage(color: theme.list.itemAccentColor), introImage: UIImage(bundleImageName: "Chat/Intro/ChannelIntro")), dismiss: { [weak controller] in
if let navigationController = controller?.navigationController as? NavigationController {
_ = navigationController.popViewController(animated: true)
}
}, completion: { [weak controller] in
if let navigationController = controller?.navigationController as? NavigationController {
navigationController.replaceTopController(createChannelController(context: context), animated: true)
}
})!)
return controller
}

View File

@ -56,11 +56,11 @@ private enum PeersNearbySection: Int32 {
private enum PeersNearbyEntry: ItemListNodeEntry {
case header(PresentationTheme, String)
case usersHeader(PresentationTheme, String)
case empty(PresentationTheme, String, Bool)
case usersHeader(PresentationTheme, String, Bool)
case empty(PresentationTheme, String)
case user(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PeerNearbyEntry)
case groupsHeader(PresentationTheme, String)
case groupsHeader(PresentationTheme, String, Bool)
case createGroup(PresentationTheme, String, Double?, Double?, String?)
case group(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PeerNearbyEntry)
@ -111,14 +111,14 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
} else {
return false
}
case let .usersHeader(lhsTheme, lhsText):
if case let .usersHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
case let .usersHeader(lhsTheme, lhsText, lhsLoading):
if case let .usersHeader(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading {
return true
} else {
return false
}
case let .empty(lhsTheme, lhsText, lhsLoading):
if case let .empty(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading {
case let .empty(lhsTheme, lhsText):
if case let .empty(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
@ -129,8 +129,8 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
} else {
return false
}
case let .groupsHeader(lhsTheme, lhsText):
if case let .groupsHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
case let .groupsHeader(lhsTheme, lhsText, lhsLoading):
if case let .groupsHeader(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading {
return true
} else {
return false
@ -181,16 +181,16 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
switch self {
case let .header(theme, text):
return PeersNearbyHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .usersHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .empty(theme, text, _):
case let .usersHeader(theme, text, loading):
return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading, sectionId: self.section)
case let .empty(theme, text):
return ItemListPlaceholderItem(theme: theme, text: text, sectionId: self.section, style: .blocks)
case let .user(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(strings.Map_DistanceAway(stringForDistance(peer.distance)).0), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
arguments.openChat(peer.peer.0)
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, hasTopGroupInset: false, tag: nil)
case let .groupsHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .groupsHeader(theme, text, loading):
return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading, sectionId: self.section)
case let .createGroup(theme, title, latitude, longitude, address):
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.createGroupIcon(theme), title: title, alwaysPlain: false, sectionId: self.section, editing: false, action: {
if let latitude = latitude, let longitude = longitude {
@ -249,7 +249,7 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, presentationDa
var entries: [PeersNearbyEntry] = []
entries.append(.header(presentationData.theme, presentationData.strings.PeopleNearby_Description))
entries.append(.usersHeader(presentationData.theme, presentationData.strings.PeopleNearby_Users.uppercased()))
entries.append(.usersHeader(presentationData.theme, presentationData.strings.PeopleNearby_Users.uppercased(), data == nil))
if let data = data, !data.users.isEmpty {
var i: Int32 = 0
for user in data.users {
@ -257,10 +257,10 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, presentationDa
i += 1
}
} else {
entries.append(.empty(presentationData.theme, presentationData.strings.PeopleNearby_UsersEmpty, data == nil))
entries.append(.empty(presentationData.theme, presentationData.strings.PeopleNearby_UsersEmpty))
}
entries.append(.groupsHeader(presentationData.theme, presentationData.strings.PeopleNearby_Groups.uppercased()))
entries.append(.groupsHeader(presentationData.theme, presentationData.strings.PeopleNearby_Groups.uppercased(), data == nil))
entries.append(.createGroup(presentationData.theme, presentationData.strings.PeopleNearby_CreateGroup, data?.latitude, data?.longitude, data?.address))
if let data = data, !data.groups.isEmpty {
var i: Int32 = 0

View File

@ -4,6 +4,20 @@ import Display
import AsyncDisplayKit
import TelegramPresentationData
enum PermissionContentIcon {
case image(UIImage?)
case icon(PermissionControllerCustomIcon)
func imageForTheme(_ theme: PresentationTheme) -> UIImage? {
switch self {
case let .image(image):
return image
case let .icon(icon):
return theme.overallDarkAppearance ? (icon.dark ?? icon.light) : icon.light
}
}
}
final class PermissionContentNode: ASDisplayNode {
private var theme: PresentationTheme
let kind: Int32
@ -17,6 +31,7 @@ final class PermissionContentNode: ASDisplayNode {
private let footerNode: ImmediateTextNode
private let privacyPolicyButton: HighlightableButtonNode
private let icon: PermissionContentIcon
private var title: String
private var text: String
@ -25,13 +40,14 @@ final class PermissionContentNode: ASDisplayNode {
var validLayout: (CGSize, UIEdgeInsets)?
init(theme: PresentationTheme, strings: PresentationStrings, kind: Int32, icon: UIImage?, title: String, subtitle: String? = nil, text: String, buttonTitle: String, footerText: String? = nil, buttonAction: @escaping () -> Void, openPrivacyPolicy: (() -> Void)?) {
init(theme: PresentationTheme, strings: PresentationStrings, kind: Int32, icon: PermissionContentIcon, title: String, subtitle: String? = nil, text: String, buttonTitle: String, footerText: String? = nil, buttonAction: @escaping () -> Void, openPrivacyPolicy: (() -> Void)?) {
self.theme = theme
self.kind = kind
self.buttonAction = buttonAction
self.openPrivacyPolicy = openPrivacyPolicy
self.icon = icon
self.title = title
self.text = text
@ -75,7 +91,7 @@ final class PermissionContentNode: ASDisplayNode {
super.init()
self.iconNode.image = icon
self.iconNode.image = icon.imageForTheme(theme)
self.title = title
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.list.itemPrimaryTextColor)
@ -115,6 +131,8 @@ final class PermissionContentNode: ASDisplayNode {
let theme = presentationData.theme
self.theme = theme
self.iconNode.image = self.icon.imageForTheme(theme)
let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.list.itemPrimaryTextColor)
let link = MarkdownAttributeSet(font: Font.regular(16.0), textColor: theme.list.itemAccentColor, additionalAttributes: [TelegramTextAttributes.URL: ""])
self.textNode.attributedText = parseMarkdownIntoAttributedString(self.text.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center)

View File

@ -84,18 +84,14 @@ final class PermissionControllerNode: ASDisplayNode {
return UITracingLayerView()
})
self.applyPresentationData()
self.updatePresentationData(self.presentationData)
}
func updatePresentationData(_ presentationData: PresentationData) {
self.presentationData = presentationData
self.applyPresentationData()
}
private func applyPresentationData() {
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
self.contentNode?.updatePresentationData(self.presentationData)
}
func animateIn(completion: (() -> Void)? = nil) {
@ -208,7 +204,7 @@ final class PermissionControllerNode: ASDisplayNode {
hasPrivacyPolicy = false
}
let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: dataState.kind.rawValue, icon: icon, title: title, text: text, buttonTitle: buttonTitle, buttonAction: { [weak self] in
let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: dataState.kind.rawValue, icon: .image(icon), title: title, text: text, buttonTitle: buttonTitle, buttonAction: { [weak self] in
self?.allow?()
}, openPrivacyPolicy: hasPrivacyPolicy ? self.openPrivacyPolicy : nil)
self.insertSubnode(contentNode, at: 0)
@ -237,15 +233,8 @@ final class PermissionControllerNode: ASDisplayNode {
if let contentNode = self.contentNode {
transition.updateFrame(node: contentNode, frame: contentFrame)
contentNode.updateLayout(size: contentFrame.size, insets: insets, transition: transition)
} else {
let iconImage: UIImage?
if self.presentationData.theme.overallDarkAppearance {
iconImage = icon.dark ?? icon.light
} else {
iconImage = icon.light
}
let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: 0, icon: iconImage, title: title, subtitle: subtitle, text: text, buttonTitle: buttonTitle, footerText: footerText, buttonAction: { [weak self] in
} else {
let contentNode = PermissionContentNode(theme: self.presentationData.theme, strings: self.presentationData.strings, kind: 0, icon: .icon(icon), title: title, subtitle: subtitle, text: text, buttonTitle: buttonTitle, footerText: footerText, buttonAction: { [weak self] in
self?.allow?()
}, openPrivacyPolicy: nil)
self.insertSubnode(contentNode, at: 0)

View File

@ -34,6 +34,8 @@ func chatInputStateStringWithAppliedEntities(_ text: String, entities: [MessageT
string.addAttribute(ChatTextInputAttributes.textUrl, value: ChatTextInputTextUrlAttribute(url: url), range: range)
case .Code, .Pre:
string.addAttribute(ChatTextInputAttributes.monospace, value: true as NSNumber, range: range)
case .Strikethrough:
string.addAttribute(ChatTextInputAttributes.strikethrough, value: true as NSNumber, range: range)
default:
break
}
@ -121,6 +123,8 @@ func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], ba
nsString = text as NSString
}
string.addAttribute(NSAttributedStringKey(rawValue: TelegramTextAttributes.PeerTextMention), value: nsString!.substring(with: range), range: range)
case .Strikethrough:
string.addAttribute(NSAttributedStringKey.strikethroughStyle, value: NSUnderlineStyle.styleSingle.rawValue as NSNumber, range: range)
case let .TextMention(peerId):
string.addAttribute(NSAttributedStringKey.foregroundColor, value: linkColor, range: range)
if underlineLinks && underlineAllLinks {

View File

@ -1,20 +0,0 @@
#import <LegacyComponents/LegacyComponents.h>
@interface TGChannelIntroControllerTheme : NSObject
@property (nonatomic, strong, readonly) UIColor *backgroundColor;
@property (nonatomic, strong, readonly) UIColor *primaryColor;
@property (nonatomic, strong, readonly) UIColor *secondaryColor;
@property (nonatomic, strong, readonly) UIColor *accentColor;
@property (nonatomic, strong, readonly) UIImage *backArrowImage;
@property (nonatomic, strong, readonly) UIImage *introImage;
- (instancetype)initWithBackgroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor secondaryColor:(UIColor *)secondaryColor accentColor:(UIColor *)accentColor backArrowImage:(UIImage *)backArrowImage introImage:(UIImage *)introImage;
@end
@interface TGChannelIntroController : TGViewController
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context getLocalizedString:(NSString *(^)(NSString *))getLocalizedString theme:(TGChannelIntroControllerTheme *)theme dismiss:(void (^)(void))dismiss completion:(void (^)(void))completion;
@end

View File

@ -1,266 +0,0 @@
#import "TGChannelIntroController.h"
#import <LegacyComponents/LegacyComponents.h>
#import <LegacyComponents/TGModernButton.h>
@implementation TGChannelIntroControllerTheme
- (instancetype)initWithBackgroundColor:(UIColor *)backgroundColor primaryColor:(UIColor *)primaryColor secondaryColor:(UIColor *)secondaryColor accentColor:(UIColor *)accentColor backArrowImage:(UIImage *)backArrowImage introImage:(UIImage *)introImage {
self = [super init];
if (self != nil) {
_backgroundColor = backgroundColor;
_primaryColor = primaryColor;
_secondaryColor = secondaryColor;
_accentColor = accentColor;
_backArrowImage = backArrowImage;
_introImage = introImage;
}
return self;
}
@end
@interface TGChannelIntroController ()
{
TGModernButton *_backButton;
UIImageView *_phoneImageView;
UILabel *_titleLabel;
UILabel *_descriptionLabel;
TGModernButton *_createButton;
TGChannelIntroControllerTheme *_theme;
NSString *(^_getLocalizedString)(NSString *);
void (^_dismiss)(void);
void (^_completion)(void);
}
@end
@implementation TGChannelIntroController
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context getLocalizedString:(NSString *(^)(NSString *))getLocalizedString theme:(TGChannelIntroControllerTheme *)theme dismiss:(void (^)(void))dismiss completion:(void (^)(void))completion {
self = [super initWithContext:context];
if (self != nil) {
_getLocalizedString = [getLocalizedString copy];
_theme = theme;
_dismiss = [dismiss copy];
_completion = [completion copy];
}
return self;
}
- (void)loadView
{
[super loadView];
self.view.backgroundColor = _theme.backgroundColor;
UIImage *image = _theme.backArrowImage;
UIGraphicsBeginImageContextWithOptions(image.size, false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
CGContextSetBlendMode (context, kCGBlendModeSourceAtop);
CGContextSetFillColorWithColor(context, _theme.accentColor.CGColor);
CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height));
UIImage *arrowImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
_backButton = [[TGModernButton alloc] initWithFrame:CGRectZero];
_backButton.exclusiveTouch = true;
_backButton.titleLabel.font = TGSystemFontOfSize(17);
[_backButton setTitle:_getLocalizedString(@"Common.Back") forState:UIControlStateNormal];
[_backButton setTitleColor:_theme.accentColor];
[_backButton addTarget:self action:@selector(backButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_backButton];
UIImageView *arrowView = [[UIImageView alloc] initWithFrame:CGRectMake(-19, 5.5f, 13, 22)];
arrowView.image = arrowImage;
[_backButton addSubview:arrowView];
_phoneImageView = [[UIImageView alloc] initWithImage:_theme.introImage];
_phoneImageView.frame = CGRectMake(0, 0, 154, 220);
[self.view addSubview:_phoneImageView];
_titleLabel = [[UILabel alloc] init];
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.font = TGSystemFontOfSize(21);
_titleLabel.textColor = _theme.primaryColor;
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.text = _getLocalizedString(@"ChannelIntro.Title");
[self.view addSubview:_titleLabel];
_descriptionLabel = [[UILabel alloc] init];
_descriptionLabel.backgroundColor = [UIColor clearColor];
_descriptionLabel.numberOfLines = 0;
_descriptionLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:_descriptionLabel];
NSString *description = _getLocalizedString(@"ChannelIntro.Text");
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:description];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = 2;
style.alignment = NSTextAlignmentCenter;
[attrString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, description.length)];
[attrString addAttribute:NSForegroundColorAttributeName value:_theme.secondaryColor range:NSMakeRange(0, description.length)];
[attrString addAttribute:NSFontAttributeName value:TGSystemFontOfSize(16) range:NSMakeRange(0, description.length)];
_descriptionLabel.attributedText = attrString;
_createButton = [[TGModernButton alloc] init];
_createButton.exclusiveTouch = true;
_createButton.backgroundColor = [UIColor clearColor];
_createButton.titleLabel.font = TGSystemFontOfSize(21);
[_createButton setTitleColor:_theme.accentColor];
[_createButton setTitle:_getLocalizedString(@"ChannelIntro.CreateChannel") forState:UIControlStateNormal];
[_createButton addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_createButton];
}
- (bool)navigationBarShouldBeHidden
{
return true;
}
- (void)backButtonPressed
{
if (_dismiss != nil)
_dismiss();
else
[self.navigationController popViewControllerAnimated:true];
}
- (void)buttonPressed
{
_completion();
}
- (void)viewWillLayoutSubviews
{
CGRect bounds = self.context.fullscreenBounds;
UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
if (bounds.size.width > bounds.size.height) {
orientation = UIInterfaceOrientationLandscapeLeft;
}
UIEdgeInsets safeAreaInset = [self calculatedSafeAreaInset];
int iosVersion = [[[UIDevice currentDevice] systemVersion] intValue];
if (UIEdgeInsetsEqualToEdgeInsets(safeAreaInset, UIEdgeInsetsZero) && (iosVersion < 11 || TGIsPad() || UIInterfaceOrientationIsPortrait(orientation)))
safeAreaInset.top = 20.0f;
[_backButton sizeToFit];
_backButton.frame = CGRectMake(27 + safeAreaInset.left, 5.0f + TGScreenPixel + safeAreaInset.top, ceil(_backButton.frame.size.width), ceil(_backButton.frame.size.height));
[_titleLabel sizeToFit];
[_descriptionLabel sizeToFit];
[_createButton sizeToFit];
int screenSize = (int)TGScreenSize().height;
CGFloat titleY = 0;
CGFloat imageY = 0;
CGFloat descY = 0;
CGFloat buttonY = 0;
if (UIInterfaceOrientationIsPortrait(orientation))
{
switch (screenSize)
{
case 812:
case 896:
titleY = 445 + 44;
imageY = 141 + 44;
descY = 490 + 44;
buttonY = 610 + 44;
break;
case 736:
titleY = 445;
imageY = 141;
descY = 490;
buttonY = 610;
break;
case 667:
titleY = 407;
imageY = 120;
descY = 448;
buttonY = 558;
break;
case 568:
titleY = 354;
imageY = 87;
descY = 397;
buttonY = 496;
break;
default:
titleY = 307;
imageY = 60;
descY = 344;
buttonY = 424;
break;
}
_phoneImageView.frame = CGRectMake((self.view.frame.size.width - _phoneImageView.frame.size.width) / 2, imageY, _phoneImageView.frame.size.width, _phoneImageView.frame.size.height);
_titleLabel.frame = CGRectMake((self.view.frame.size.width - _titleLabel.frame.size.width) / 2, titleY, ceil(_titleLabel.frame.size.width), ceil(_titleLabel.frame.size.height));
_descriptionLabel.frame = CGRectMake((self.view.frame.size.width - _descriptionLabel.frame.size.width) / 2, descY, ceil(_descriptionLabel.frame.size.width), ceil(_descriptionLabel.frame.size.height));
_createButton.frame = CGRectMake((self.view.frame.size.width - _createButton.frame.size.width) / 2, buttonY, ceil(_createButton.frame.size.width), ceil(_createButton.frame.size.height));
}
else
{
CGFloat leftX = 0;
CGFloat rightX = 0;
switch (screenSize)
{
case 812:
leftX = 190 + 44;
rightX = 448 + 44;
titleY = 103;
descY = 148;
buttonY = 237;
break;
case 736:
leftX = 209;
rightX = 504;
titleY = 115;
descY = 156;
buttonY = 278;
break;
case 667:
leftX = 190;
rightX = 448;
titleY = 103;
descY = 148;
buttonY = 237;
break;
case 568:
leftX = 164;
rightX = 388;
titleY = 78;
descY = 121;
buttonY = 217;
break;
default:
leftX = 125;
rightX = 328;
titleY = 78;
descY = 121;
buttonY = 219;
break;
}
_phoneImageView.frame = CGRectMake(leftX - _phoneImageView.frame.size.width / 2, (self.view.frame.size.height - _phoneImageView.frame.size.height) / 2, _phoneImageView.frame.size.width, _phoneImageView.frame.size.height);
_titleLabel.frame = CGRectMake(rightX - _titleLabel.frame.size.width / 2, titleY, ceil(_titleLabel.frame.size.width), ceil(_titleLabel.frame.size.height));
_descriptionLabel.frame = CGRectMake(rightX - _descriptionLabel.frame.size.width / 2, descY, ceil(_descriptionLabel.frame.size.width), ceil(_descriptionLabel.frame.size.height));
_createButton.frame = CGRectMake(rightX - _createButton.frame.size.width / 2, buttonY, ceil(_createButton.frame.size.width), ceil(_createButton.frame.size.height));
}
}
@end

View File

@ -12,7 +12,6 @@ module TelegramUIPrivateModule {
header "../DeviceProximityManager.h"
header "../RaiseToListenActivator.h"
header "../TGMimeTypeMap.h"
header "../TGChannelIntroController.h"
header "../Bridge Audio/TGBridgeAudioDecoder.h"
header "../Bridge Audio/TGBridgeAudioEncoder.h"
header "../TGContactModel.h"

View File

@ -407,9 +407,6 @@
D0642EFC1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0642EFB1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift */; };
D064EF871F69A06F00AC0398 /* MessageContentKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = D064EF861F69A06F00AC0398 /* MessageContentKind.swift */; };
D0671F2D2145AB28000A8AE7 /* LegacyAvatarPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0671F2C2145AB28000A8AE7 /* LegacyAvatarPicker.swift */; };
D067B4A5211C911C00796039 /* LegacyChannelIntroController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D067B4A4211C911C00796039 /* LegacyChannelIntroController.swift */; };
D067B4AA211C916300796039 /* TGChannelIntroController.h in Headers */ = {isa = PBXBuildFile; fileRef = D067B4A6211C916200796039 /* TGChannelIntroController.h */; };
D067B4AD211C916300796039 /* TGChannelIntroController.m in Sources */ = {isa = PBXBuildFile; fileRef = D067B4A9211C916200796039 /* TGChannelIntroController.m */; };
D0684A041F6C3AD50059F570 /* ChatListTypingNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0684A031F6C3AD50059F570 /* ChatListTypingNode.swift */; };
D06887F01F72DEE6000AB936 /* ShareInputFieldNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06887EF1F72DEE6000AB936 /* ShareInputFieldNode.swift */; };
D069F5D0212700B90000565A /* StickerPanePeerSpecificSetupGridItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D069F5CF212700B90000565A /* StickerPanePeerSpecificSetupGridItem.swift */; };
@ -1733,9 +1730,6 @@
D0642EFB1F3E1E7B00792790 /* ChatHistoryNavigationButtons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatHistoryNavigationButtons.swift; sourceTree = "<group>"; };
D064EF861F69A06F00AC0398 /* MessageContentKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageContentKind.swift; sourceTree = "<group>"; };
D0671F2C2145AB28000A8AE7 /* LegacyAvatarPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyAvatarPicker.swift; sourceTree = "<group>"; };
D067B4A4211C911C00796039 /* LegacyChannelIntroController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyChannelIntroController.swift; sourceTree = "<group>"; };
D067B4A6211C916200796039 /* TGChannelIntroController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGChannelIntroController.h; sourceTree = "<group>"; };
D067B4A9211C916200796039 /* TGChannelIntroController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGChannelIntroController.m; sourceTree = "<group>"; };
D0684A031F6C3AD50059F570 /* ChatListTypingNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListTypingNode.swift; sourceTree = "<group>"; };
D06879541DB8F1FC00424BBD /* CachedResourceRepresentations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedResourceRepresentations.swift; sourceTree = "<group>"; };
D06879561DB8F22200424BBD /* FetchCachedRepresentations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchCachedRepresentations.swift; sourceTree = "<group>"; };
@ -3267,16 +3261,6 @@
name = "Setup Two Step Verification";
sourceTree = "<group>";
};
D067B4AE211C916D00796039 /* Channel Intro */ = {
isa = PBXGroup;
children = (
D067B4A4211C911C00796039 /* LegacyChannelIntroController.swift */,
D067B4A6211C916200796039 /* TGChannelIntroController.h */,
D067B4A9211C916200796039 /* TGChannelIntroController.m */,
);
name = "Channel Intro";
sourceTree = "<group>";
};
D0736F261DF4D2F300F2C02A /* Telegram Controller */ = {
isa = PBXGroup;
children = (
@ -3336,7 +3320,6 @@
D07551891DDA4C7C0073E051 /* Legacy Components */ = {
isa = PBXGroup;
children = (
D067B4AE211C916D00796039 /* Channel Intro */,
D0AE2FDB22B1D3610058D3BC /* Bridge Audio */,
D075518A1DDA4D7D0073E051 /* LegacyController.swift */,
D075518C1DDA4E0B0073E051 /* LegacyControllerNode.swift */,
@ -4899,7 +4882,6 @@
D0E9BACB1F05738600F079A4 /* STPAPIPostRequest.h in Headers */,
D0E9BA561F055A0B00F079A4 /* STPFormTextField.h in Headers */,
D008177C22B46B7E008A895F /* TGItemProviderSignals.h in Headers */,
D067B4AA211C916300796039 /* TGChannelIntroController.h in Headers */,
D0E9BABE1F05735F00F079A4 /* STPPaymentConfiguration+Private.h in Headers */,
D0E9BACA1F05738600F079A4 /* STPAPIClient+Private.h in Headers */,
D0E9BA251F05578900F079A4 /* STPCardBrand.h in Headers */,
@ -5232,7 +5214,6 @@
D0AB263321C3DFEA008F6685 /* CreatePollOptionActionItem.swift in Sources */,
09FFBCDB22849CB500C33B4B /* PDF.swift in Sources */,
09D968A1221F7FF100B1458A /* ChatTypingActivityContentNode.swift in Sources */,
D067B4AD211C916300796039 /* TGChannelIntroController.m in Sources */,
D0BE303220601FFC00FBE6D8 /* LocationBroadcastActionSheetItem.swift in Sources */,
090E778E22AA863A00CD99F5 /* PeersNearbyIconNode.swift in Sources */,
D0EC6CF41EB9F58800EBF1C3 /* ManagedMediaId.swift in Sources */,
@ -5959,7 +5940,6 @@
091417F421EF4F5F00C8325A /* WallpaperGalleryItem.swift in Sources */,
D02F4AE91FCF370B004DFBAE /* ChatMessageInteractiveMediaBadge.swift in Sources */,
D0EC6E461EB9F58900EBF1C3 /* ItemListLoadingIndicatorEmptyStateItem.swift in Sources */,
D067B4A5211C911C00796039 /* LegacyChannelIntroController.swift in Sources */,
D00817CF22B47A14008A895F /* LegacyFileImport.swift in Sources */,
D01A21AF1F39EA2E00DDA104 /* InstantPageTheme.swift in Sources */,
D0EC6E471EB9F58900EBF1C3 /* ItemListTextEmptyStateItem.swift in Sources */,