mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-01 12:17:53 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/TelegramUI
This commit is contained in:
commit
7ffa11e408
@ -766,7 +766,34 @@ final class ChatListSearchContainerNode: SearchDisplayControllerContentNode {
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
var recentItemsTransition = combineLatest(hasRecentPeers, recentlySearchedPeers(postbox: account.postbox), presentationDataPromise.get(), self.statePromise.get())
|
||||
|
||||
let previousRecentlySearchedPeerOrder = Atomic<[PeerId]>(value: [])
|
||||
let fixedRecentlySearchedPeers = recentlySearchedPeers(postbox: account.postbox)
|
||||
|> map { peers -> [RecentlySearchedPeer] in
|
||||
var result: [RecentlySearchedPeer] = []
|
||||
let _ = previousRecentlySearchedPeerOrder.modify { current in
|
||||
var updated: [PeerId] = []
|
||||
for id in current {
|
||||
inner: for peer in peers {
|
||||
if peer.peer.peerId == id {
|
||||
updated.append(id)
|
||||
result.append(peer)
|
||||
break inner
|
||||
}
|
||||
}
|
||||
}
|
||||
for peer in peers.reversed() {
|
||||
if !updated.contains(peer.peer.peerId) {
|
||||
updated.insert(peer.peer.peerId, at: 0)
|
||||
result.insert(peer, at: 0)
|
||||
}
|
||||
}
|
||||
return updated
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var recentItemsTransition = combineLatest(hasRecentPeers, fixedRecentlySearchedPeers, presentationDataPromise.get(), self.statePromise.get())
|
||||
|> mapToSignal { [weak self] hasRecentPeers, peers, presentationData, state -> Signal<(ChatListSearchContainerRecentTransition, Bool), NoError> in
|
||||
var entries: [ChatListRecentEntry] = []
|
||||
if !filter.contains(.onlyGroups) {
|
||||
|
||||
@ -22,6 +22,7 @@ enum InteractiveMediaNodeActivateContent {
|
||||
|
||||
final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
private let imageNode: TransformImageNode
|
||||
private var currentImageArguments: TransformImageArguments?
|
||||
private var videoNode: UniversalVideoNode?
|
||||
private var statusNode: RadialStatusNode?
|
||||
private var badgeNode: ChatMessageInteractiveMediaBadge?
|
||||
@ -396,7 +397,19 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
strongSelf.sizeCalculation = sizeCalculation
|
||||
strongSelf.automaticPlayback = automaticPlayback
|
||||
strongSelf.automaticDownload = automaticDownload
|
||||
transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame)
|
||||
|
||||
if let previousArguments = strongSelf.currentImageArguments {
|
||||
if previousArguments.imageSize == arguments.imageSize {
|
||||
strongSelf.imageNode.frame = imageFrame
|
||||
} else {
|
||||
transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame)
|
||||
}
|
||||
} else {
|
||||
strongSelf.imageNode.frame = imageFrame
|
||||
}
|
||||
strongSelf.currentImageArguments = arguments
|
||||
imageApply()
|
||||
|
||||
strongSelf.statusNode?.position = CGPoint(x: imageFrame.midX, y: imageFrame.midY)
|
||||
|
||||
if let replaceVideoNode = replaceVideoNode {
|
||||
@ -469,8 +482,6 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
strongSelf.fetchControls.with({ $0 })?.fetch(false)
|
||||
}
|
||||
|
||||
imageApply()
|
||||
|
||||
strongSelf.updateFetchStatus()
|
||||
}
|
||||
})
|
||||
|
||||
@ -304,6 +304,7 @@ class ContactMultiselectionController: ViewController {
|
||||
if let presentationArguments = self.presentationArguments as? ViewControllerPresentationArguments {
|
||||
switch presentationArguments.presentationAnimation {
|
||||
case .modalSheet:
|
||||
self.view.endEditing(true)
|
||||
self.contactsNode.animateOut(completion: { [weak self] in
|
||||
self?.dismissed?()
|
||||
completion?()
|
||||
|
||||
@ -174,7 +174,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func animateOut(completion: (() -> Void)?) {
|
||||
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: 0.0, y: self.layer.bounds.size.height), duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: false, additive: true, completion: { [weak self] _ in
|
||||
self.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.layer.bounds.size.height), duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: false, additive: true, completion: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.dismiss?()
|
||||
completion?()
|
||||
|
||||
@ -368,7 +368,14 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if self.currentExpandedDetails == nil {
|
||||
if var currentExpandedDetails = self.currentExpandedDetails {
|
||||
for (index, expanded) in expandedDetails {
|
||||
if currentExpandedDetails[index] == nil {
|
||||
currentExpandedDetails[index] = expanded
|
||||
}
|
||||
}
|
||||
self.currentExpandedDetails = currentExpandedDetails
|
||||
} else {
|
||||
self.currentExpandedDetails = expandedDetails
|
||||
}
|
||||
|
||||
@ -540,8 +547,8 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let currentLayout = self.currentLayout, collapseOffset > 0.0 {
|
||||
|
||||
if let currentLayout = self.currentLayout {
|
||||
let effectiveContentHeight = currentLayout.contentSize.height - collapseOffset
|
||||
if effectiveContentHeight != self.scrollNode.view.contentSize.height {
|
||||
transition.animateView {
|
||||
@ -928,12 +935,17 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private func findAnchorItem(_ anchor: String, items: [InstantPageItem]) -> (InstantPageItem, CGFloat, [InstantPageDetailsItem])? {
|
||||
for item in items {
|
||||
if let item = item as? InstantPageAnchorItem, item.anchor == anchor {
|
||||
return (item, 0.0, [])
|
||||
return (item, -10.0, [])
|
||||
} else if let item = item as? InstantPageTextItem {
|
||||
if let lineIndex = item.anchors[anchor] {
|
||||
return (item, item.lines[lineIndex].frame.minY - 10.0, [])
|
||||
}
|
||||
}
|
||||
else if let item = item as? InstantPageTableItem {
|
||||
if let offset = item.anchors[anchor] {
|
||||
return (item, offset - 10.0, [])
|
||||
}
|
||||
}
|
||||
else if let item = item as? InstantPageDetailsItem {
|
||||
if let (foundItem, offset, detailsItems) = self.findAnchorItem(anchor, items: item.items) {
|
||||
var detailsItems = detailsItems
|
||||
@ -965,14 +977,13 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if let webPage = self.webPage, case let .Loaded(content) = webPage.content, let page = content.instantPage, page.url == baseUrl, let anchor = anchor {
|
||||
if !anchor.isEmpty {
|
||||
if let (item, lineOffset, detailsItems) = findAnchorItem(String(anchor), items: items) {
|
||||
var previousDetailsItem: InstantPageDetailsItem?
|
||||
var previousDetailsNode: InstantPageDetailsNode?
|
||||
var containerOffset: CGFloat = 0.0
|
||||
for detailsItem in detailsItems {
|
||||
if let previousNode = previousDetailsNode, let previousDetailsItem = previousDetailsItem {
|
||||
if let previousNode = previousDetailsNode {
|
||||
previousNode.contentNode.updateDetailsExpanded(detailsItem.index, true, animated: false)
|
||||
let frame = previousNode.contentNode.effectiveFrameForItem(detailsItem)
|
||||
containerOffset += frame.minY + previousDetailsItem.titleHeight
|
||||
let frame = previousNode.effectiveFrameForItem(detailsItem)
|
||||
containerOffset += frame.minY
|
||||
|
||||
previousDetailsNode = previousNode.contentNode.nodeForDetailsItem(detailsItem)
|
||||
previousDetailsNode?.setExpanded(true, animated: false)
|
||||
@ -983,18 +994,23 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
previousDetailsNode = self.nodeForDetailsItem(detailsItem)
|
||||
previousDetailsNode?.setExpanded(true, animated: false)
|
||||
previousDetailsItem = detailsItem
|
||||
}
|
||||
}
|
||||
|
||||
let frame: CGRect
|
||||
if let previousDetailsNode = previousDetailsNode, let previousDetailsItem = previousDetailsItem {
|
||||
containerOffset += previousDetailsItem.titleHeight
|
||||
frame = previousDetailsNode.contentNode.effectiveFrameForItem(item)
|
||||
if let previousDetailsNode = previousDetailsNode {
|
||||
frame = previousDetailsNode.effectiveFrameForItem(item)
|
||||
} else {
|
||||
frame = self.effectiveFrameForItem(item)
|
||||
}
|
||||
self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: containerOffset + frame.minY + lineOffset - self.scrollNode.view.contentInset.top), animated: true)
|
||||
|
||||
var targetY = min(containerOffset + frame.minY + lineOffset, self.scrollNode.view.contentSize.height - self.scrollNode.frame.height)
|
||||
if targetY < self.scrollNode.view.contentOffset.y {
|
||||
targetY -= self.scrollNode.view.contentInset.top
|
||||
} else {
|
||||
targetY -= self.containerLayout?.statusBarHeight ?? 20.0
|
||||
}
|
||||
self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: targetY), animated: true)
|
||||
}
|
||||
} else {
|
||||
self.scrollNode.view.setContentOffset(CGPoint(x: 0.0, y: -self.scrollNode.view.contentInset.top), animated: true)
|
||||
|
||||
@ -361,7 +361,7 @@ final class InstantPageDetailsContentNode : ASDisplayNode {
|
||||
return CGRect(origin: origin, size: tile.frame.size)
|
||||
}
|
||||
|
||||
func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
|
||||
fileprivate func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
|
||||
let layoutOrigin = item.frame.origin
|
||||
var origin = layoutOrigin
|
||||
|
||||
@ -610,6 +610,10 @@ final class InstantPageDetailsNode: ASDisplayNode, InstantPageNode {
|
||||
var effectiveContentSize: CGSize {
|
||||
return self.contentNode.effectiveContentSize
|
||||
}
|
||||
|
||||
func effectiveFrameForItem(_ item: InstantPageItem) -> CGRect {
|
||||
return self.contentNode.effectiveFrameForItem(item).offsetBy(dx: 0.0, dy: self.item.titleHeight)
|
||||
}
|
||||
}
|
||||
|
||||
private final class InstantPageDetailsArrowNodeParameters: NSObject {
|
||||
|
||||
@ -32,11 +32,11 @@ final class InstantPageFeedbackItem: InstantPageItem {
|
||||
}
|
||||
|
||||
func distanceThresholdGroup() -> Int? {
|
||||
return nil
|
||||
return 8
|
||||
}
|
||||
|
||||
func distanceThresholdWithGroupCount(_ count: Int) -> CGFloat {
|
||||
return 0.0
|
||||
return CGFloat.greatestFiniteMagnitude
|
||||
}
|
||||
|
||||
func linkSelectionRects(at point: CGPoint) -> [CGRect] {
|
||||
|
||||
@ -269,7 +269,7 @@ func layoutInstantPageBlock(webpage: TelegramMediaWebpage, rtl: Bool, block: Ins
|
||||
for subBlock in blocks {
|
||||
let subLayout = layoutInstantPageBlock(webpage: webpage, rtl: rtl, block: subBlock, boundingWidth: boundingWidth - horizontalInset * 2.0 - indexSpacing - maxIndexWidth, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: listItems, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights)
|
||||
|
||||
let spacing: CGFloat = previousBlock != nil ? spacingBetweenBlocks(upper: previousBlock, lower: subBlock) : 0.0
|
||||
let spacing: CGFloat = previousBlock != nil && subLayout.contentSize.height > 0.0 ? spacingBetweenBlocks(upper: previousBlock, lower: subBlock) : 0.0
|
||||
let blockItems = subLayout.flattenedItemsWithOrigin(CGPoint(x: horizontalInset + indexSpacing + maxIndexWidth, y: contentSize.height + spacing))
|
||||
if previousBlock == nil {
|
||||
originY += spacing
|
||||
|
||||
@ -4,7 +4,7 @@ import TelegramCore
|
||||
func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?) -> CGFloat {
|
||||
if let upper = upper, let lower = lower {
|
||||
switch (upper, lower) {
|
||||
case (_, .cover), (_, .channelBanner), (.details, .details), (.relatedArticles, nil), (.anchor, _), (_, .anchor):
|
||||
case (_, .cover), (_, .channelBanner), (.details, .details), (.relatedArticles, nil), (_, .anchor):
|
||||
return 0.0
|
||||
case (.divider, _), (_, .divider):
|
||||
return 25.0
|
||||
@ -49,7 +49,7 @@ func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?) ->
|
||||
}
|
||||
} else if let lower = lower {
|
||||
switch lower {
|
||||
case .cover, .channelBanner, .details:
|
||||
case .cover, .channelBanner, .details, .anchor:
|
||||
return 0.0
|
||||
default:
|
||||
return 25.0
|
||||
|
||||
@ -108,6 +108,8 @@ final class InstantPageTableItem: InstantPageScrollableItem {
|
||||
fileprivate let cells: [InstantPageTableCellItem]
|
||||
private let borderWidth: CGFloat
|
||||
|
||||
let anchors: [String: CGFloat]
|
||||
|
||||
fileprivate init(frame: CGRect, totalWidth: CGFloat, horizontalInset: CGFloat, borderWidth: CGFloat, theme: InstantPageTheme, cells: [InstantPageTableCellItem], rtl: Bool) {
|
||||
self.frame = frame
|
||||
self.totalWidth = totalWidth
|
||||
@ -116,6 +118,20 @@ final class InstantPageTableItem: InstantPageScrollableItem {
|
||||
self.theme = theme
|
||||
self.cells = cells
|
||||
self.isRTL = rtl
|
||||
|
||||
var anchors: [String: CGFloat] = [:]
|
||||
for cell in cells {
|
||||
if let textItem = cell.textItem {
|
||||
for (anchor, lineIndex) in textItem.anchors {
|
||||
if anchors[anchor] == nil {
|
||||
let textItemFrame = textItem.frame.offsetBy(dx: cell.frame.minX, dy: cell.frame.minY)
|
||||
let offset = textItemFrame.minY + textItem.lines[lineIndex].frame.minY
|
||||
anchors[anchor] = offset
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.anchors = anchors
|
||||
}
|
||||
|
||||
var contentSize: CGSize {
|
||||
|
||||
@ -552,7 +552,8 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
|
||||
var lastIndex: CFIndex = 0
|
||||
var currentLineOrigin = CGPoint()
|
||||
|
||||
|
||||
var hasAnchors = false
|
||||
var maxLineWidth: CGFloat = 0.0
|
||||
var maxImageHeight: CGFloat = 0.0
|
||||
var extraDescent: CGFloat = 0.0
|
||||
@ -677,6 +678,10 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
}
|
||||
}
|
||||
|
||||
if !anchorItems.isEmpty {
|
||||
hasAnchors = true
|
||||
}
|
||||
|
||||
if hadExtraDescent && extraDescent > 0 {
|
||||
workingLineOrigin.y += fontLineSpacing
|
||||
}
|
||||
@ -706,7 +711,7 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
|
||||
}
|
||||
|
||||
var height: CGFloat = 0.0
|
||||
if !lines.isEmpty {
|
||||
if !lines.isEmpty && !(string.length == 1 && hasAnchors) {
|
||||
height = lines.last!.frame.maxY + extraDescent
|
||||
}
|
||||
|
||||
|
||||
@ -634,7 +634,7 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat
|
||||
entries.append(UserInfoEntry.addContact(presentationData.theme, presentationData.strings.UserInfo_AddContact))
|
||||
}
|
||||
|
||||
if let cachedUserData = cachedPeerData as? CachedUserData, !(cachedUserData.hasAccountPeerPhone ?? false) {
|
||||
if let cachedUserData = cachedPeerData as? CachedUserData, let hasAccountPeerPhone = cachedUserData.hasAccountPeerPhone, !hasAccountPeerPhone {
|
||||
entries.append(UserInfoEntry.shareMyContact(presentationData.theme, presentationData.strings.UserInfo_ShareMyContactInfo))
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user