mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
a1ebe57732
@ -966,8 +966,13 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
|||||||
guard let self, !self.isInlineMode else {
|
guard let self, !self.isInlineMode else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
guard let validLayout = self.validLayout else {
|
||||||
|
return
|
||||||
|
}
|
||||||
let tempTopInset: CGFloat
|
let tempTopInset: CGFloat
|
||||||
if self.currentItemNode.startedScrollingAtUpperBound && !self.isInlineMode {
|
if validLayout.inlineNavigationLocation != nil {
|
||||||
|
tempTopInset = 0.0
|
||||||
|
} else if self.currentItemNode.startedScrollingAtUpperBound && !self.isInlineMode {
|
||||||
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
|
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
|
||||||
tempTopInset = ChatListNavigationBar.storiesScrollHeight
|
tempTopInset = ChatListNavigationBar.storiesScrollHeight
|
||||||
} else {
|
} else {
|
||||||
@ -2029,21 +2034,29 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getEffectiveNavigationScrollingOffset() -> CGFloat {
|
private func updateNavigationScrolling(navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
let mainOffset: CGFloat
|
var mainOffset: CGFloat
|
||||||
if let contentOffset = self.mainContainerNode.contentOffset, case let .known(value) = contentOffset {
|
if let contentOffset = self.mainContainerNode.contentOffset, case let .known(value) = contentOffset {
|
||||||
mainOffset = value
|
mainOffset = value
|
||||||
} else {
|
} else {
|
||||||
mainOffset = 1000.0
|
mainOffset = navigationHeight
|
||||||
|
}
|
||||||
|
mainOffset = min(mainOffset, ChatListNavigationBar.searchScrollHeight)
|
||||||
|
if abs(mainOffset) < 0.1 {
|
||||||
|
mainOffset = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultingOffset: CGFloat
|
let resultingOffset: CGFloat
|
||||||
if let inlineStackContainerNode = self.inlineStackContainerNode {
|
if let inlineStackContainerNode = self.inlineStackContainerNode {
|
||||||
let inlineOffset: CGFloat
|
var inlineOffset: CGFloat
|
||||||
if let contentOffset = inlineStackContainerNode.contentOffset, case let .known(value) = contentOffset {
|
if let contentOffset = inlineStackContainerNode.contentOffset, case let .known(value) = contentOffset {
|
||||||
inlineOffset = value
|
inlineOffset = value
|
||||||
} else {
|
} else {
|
||||||
inlineOffset = 1000.0
|
inlineOffset = navigationHeight
|
||||||
|
}
|
||||||
|
inlineOffset = min(inlineOffset, ChatListNavigationBar.searchScrollHeight)
|
||||||
|
if abs(inlineOffset) < 0.1 {
|
||||||
|
inlineOffset = 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
resultingOffset = mainOffset * (1.0 - self.inlineStackContainerTransitionFraction) + inlineOffset * self.inlineStackContainerTransitionFraction
|
resultingOffset = mainOffset * (1.0 - self.inlineStackContainerTransitionFraction) + inlineOffset * self.inlineStackContainerTransitionFraction
|
||||||
@ -2051,11 +2064,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
resultingOffset = mainOffset
|
resultingOffset = mainOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultingOffset
|
var offset = resultingOffset
|
||||||
}
|
|
||||||
|
|
||||||
private func updateNavigationScrolling(transition: ContainedViewLayoutTransition) {
|
|
||||||
var offset = self.getEffectiveNavigationScrollingOffset()
|
|
||||||
if self.isSearchDisplayControllerActive {
|
if self.isSearchDisplayControllerActive {
|
||||||
offset = 0.0
|
offset = 0.0
|
||||||
}
|
}
|
||||||
@ -2075,6 +2084,14 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
crossfadeStoryPeers: false
|
crossfadeStoryPeers: false
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mainDelta: CGFloat
|
||||||
|
if let _ = self.inlineStackContainerNode {
|
||||||
|
mainDelta = resultingOffset - max(0.0, mainOffset)
|
||||||
|
} else {
|
||||||
|
mainDelta = 0.0
|
||||||
|
}
|
||||||
|
transition.updateSublayerTransformOffset(layer: self.mainContainerNode.layer, offset: CGPoint(x: 0.0, y: -mainDelta))
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestNavigationBarLayout(transition: Transition) {
|
func requestNavigationBarLayout(transition: Transition) {
|
||||||
@ -2226,7 +2243,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.updateNavigationScrolling(transition: transition)
|
self.updateNavigationScrolling(navigationHeight: navigationBarLayout.navigationHeight, transition: transition)
|
||||||
|
|
||||||
if let navigationBarComponentView = self.navigationBarView.view as? ChatListNavigationBar.View {
|
if let navigationBarComponentView = self.navigationBarView.view as? ChatListNavigationBar.View {
|
||||||
navigationBarComponentView.deferScrollApplication = false
|
navigationBarComponentView.deferScrollApplication = false
|
||||||
@ -2342,50 +2359,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
let _ = inlineStackContainerNode
|
let _ = inlineStackContainerNode
|
||||||
}
|
}
|
||||||
|
|
||||||
self.updateNavigationScrolling(transition: self.tempNavigationScrollingTransition ?? .immediate)
|
self.updateNavigationScrolling(navigationHeight: containerLayout.navigationBarHeight, transition: self.tempNavigationScrollingTransition ?? .immediate)
|
||||||
|
|
||||||
/*if !isPrimary {
|
|
||||||
self.contentOffsetChanged?(offset)
|
|
||||||
if "".isEmpty {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if "".isEmpty {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let targetNode: ChatListContainerNode
|
|
||||||
if isPrimary {
|
|
||||||
targetNode = inlineStackContainerNode
|
|
||||||
} else {
|
|
||||||
targetNode = self.mainContainerNode
|
|
||||||
}
|
|
||||||
|
|
||||||
switch offset {
|
|
||||||
case let .known(value) where (value <= containerLayout.navigationBarHeight - 76.0 - 46.0 - 8.0 + UIScreenPixel || self.contentOffsetSyncLockedIn):
|
|
||||||
if case let .known(otherValue) = targetNode.currentItemNode.visibleContentOffset(), abs(otherValue - value) <= UIScreenPixel {
|
|
||||||
self.contentOffsetSyncLockedIn = true
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch offset {
|
|
||||||
case let .known(value) where self.contentOffsetSyncLockedIn:
|
|
||||||
var targetValue = value
|
|
||||||
if targetValue > containerLayout.navigationBarHeight - 76.0 - 46.0 - 8.0 {
|
|
||||||
targetValue = containerLayout.navigationBarHeight - 76.0 - 46.0 - 8.0
|
|
||||||
}
|
|
||||||
|
|
||||||
targetNode.fixContentOffset(offset: targetValue)
|
|
||||||
|
|
||||||
self.contentOffsetChanged?(offset)
|
|
||||||
default:
|
|
||||||
if !isPrimary {
|
|
||||||
self.contentOffsetChanged?(offset)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func shouldStopScrolling(listView: ListView, velocity: CGFloat, isPrimary: Bool) -> Bool {
|
private func shouldStopScrolling(listView: ListView, velocity: CGFloat, isPrimary: Bool) -> Bool {
|
||||||
@ -2538,8 +2512,10 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.temporaryContentOffsetChangeTransition = transition
|
self.temporaryContentOffsetChangeTransition = transition
|
||||||
|
self.tempNavigationScrollingTransition = transition
|
||||||
self.controller?.requestLayout(transition: transition)
|
self.controller?.requestLayout(transition: transition)
|
||||||
self.temporaryContentOffsetChangeTransition = nil
|
self.temporaryContentOffsetChangeTransition = nil
|
||||||
|
self.tempNavigationScrollingTransition = nil
|
||||||
} else {
|
} else {
|
||||||
inlineStackContainerNode.removeFromSupernode()
|
inlineStackContainerNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
@ -2155,6 +2155,16 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if textString.length == 0, case let .groupReference(data) = item.content, let storyState = data.storyState, storyState.stats.totalCount != 0 {
|
||||||
|
//TODO:localize
|
||||||
|
let storyText: String
|
||||||
|
if storyState.stats.totalCount == 1 {
|
||||||
|
storyText = "1 story"
|
||||||
|
} else {
|
||||||
|
storyText = "\(storyState.stats.totalCount) stories"
|
||||||
|
}
|
||||||
|
textString.append(NSAttributedString(string: storyText, font: textFont, textColor: theme.messageTextColor))
|
||||||
|
}
|
||||||
attributedText = textString
|
attributedText = textString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3197,7 +3197,7 @@ public final class ChatListNode: ListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var options = transition.options
|
var options = transition.options
|
||||||
options.insert(.Synchronous)
|
//options.insert(.Synchronous)
|
||||||
if self.view.window != nil {
|
if self.view.window != nil {
|
||||||
if !options.contains(.AnimateInsertion) {
|
if !options.contains(.AnimateInsertion) {
|
||||||
options.insert(.PreferSynchronousDrawing)
|
options.insert(.PreferSynchronousDrawing)
|
||||||
|
@ -450,6 +450,8 @@ public final class PeerStoryListContext {
|
|||||||
|
|
||||||
private var updatesDisposable: Disposable?
|
private var updatesDisposable: Disposable?
|
||||||
|
|
||||||
|
private var completionCallbacksByToken: [Int: [() -> Void]] = [:]
|
||||||
|
|
||||||
init(queue: Queue, account: Account, peerId: EnginePeer.Id, isArchived: Bool) {
|
init(queue: Queue, account: Account, peerId: EnginePeer.Id, isArchived: Bool) {
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.account = account
|
self.account = account
|
||||||
@ -519,7 +521,7 @@ public final class PeerStoryListContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.stateValue = State(peerReference: peerReference, items: items, totalCount: totalCount, loadMoreToken: 0, isCached: true, allEntityFiles: allEntityFiles)
|
self.stateValue = State(peerReference: peerReference, items: items, totalCount: totalCount, loadMoreToken: 0, isCached: true, allEntityFiles: allEntityFiles)
|
||||||
self.loadMore()
|
self.loadMore(completion: nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,16 +529,26 @@ public final class PeerStoryListContext {
|
|||||||
self.requestDisposable?.dispose()
|
self.requestDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMore() {
|
func loadMore(completion: (() -> Void)?) {
|
||||||
if self.isLoadingMore {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let loadMoreToken = self.stateValue.loadMoreToken else {
|
guard let loadMoreToken = self.stateValue.loadMoreToken else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let completion = completion {
|
||||||
|
if self.completionCallbacksByToken[loadMoreToken] == nil {
|
||||||
|
self.completionCallbacksByToken[loadMoreToken] = []
|
||||||
|
}
|
||||||
|
self.completionCallbacksByToken[loadMoreToken]?.append(completion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.isLoadingMore {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.isLoadingMore = true
|
self.isLoadingMore = true
|
||||||
|
|
||||||
|
let limit = 100
|
||||||
|
|
||||||
let peerId = self.peerId
|
let peerId = self.peerId
|
||||||
let account = self.account
|
let account = self.account
|
||||||
let accountPeerId = account.peerId
|
let accountPeerId = account.peerId
|
||||||
@ -551,9 +563,9 @@ public final class PeerStoryListContext {
|
|||||||
|
|
||||||
let signal: Signal<Api.stories.Stories, MTRpcError>
|
let signal: Signal<Api.stories.Stories, MTRpcError>
|
||||||
if isArchived {
|
if isArchived {
|
||||||
signal = account.network.request(Api.functions.stories.getStoriesArchive(offsetId: Int32(loadMoreToken), limit: 100))
|
signal = account.network.request(Api.functions.stories.getStoriesArchive(offsetId: Int32(loadMoreToken), limit: Int32(limit)))
|
||||||
} else {
|
} else {
|
||||||
signal = account.network.request(Api.functions.stories.getPinnedStories(userId: inputUser, offsetId: Int32(loadMoreToken), limit: 100))
|
signal = account.network.request(Api.functions.stories.getPinnedStories(userId: inputUser, offsetId: Int32(loadMoreToken), limit: Int32(limit)))
|
||||||
}
|
}
|
||||||
return signal
|
return signal
|
||||||
|> map { result -> Api.stories.Stories? in
|
|> map { result -> Api.stories.Stories? in
|
||||||
@ -575,7 +587,7 @@ public final class PeerStoryListContext {
|
|||||||
switch result {
|
switch result {
|
||||||
case let .stories(count, stories, users):
|
case let .stories(count, stories, users):
|
||||||
totalCount = Int(count)
|
totalCount = Int(count)
|
||||||
hasMore = stories.count >= 100
|
hasMore = stories.count >= limit
|
||||||
|
|
||||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
|
||||||
|
|
||||||
@ -664,6 +676,12 @@ public final class PeerStoryListContext {
|
|||||||
}
|
}
|
||||||
self.stateValue = updatedState
|
self.stateValue = updatedState
|
||||||
|
|
||||||
|
if let callbacks = self.completionCallbacksByToken.removeValue(forKey: loadMoreToken) {
|
||||||
|
for f in callbacks {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.updatesDisposable == nil {
|
if self.updatesDisposable == nil {
|
||||||
self.updatesDisposable = (self.account.stateManager.storyUpdates
|
self.updatesDisposable = (self.account.stateManager.storyUpdates
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self] updates in
|
|> deliverOn(self.queue)).start(next: { [weak self] updates in
|
||||||
@ -863,9 +881,9 @@ public final class PeerStoryListContext {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func loadMore() {
|
public func loadMore(completion: (() -> Void)? = nil) {
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
impl.loadMore()
|
impl.loadMore(completion : completion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1488,7 +1488,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
self.requestHistoryAroundVisiblePosition(synchronous: false, reloadAtTop: false)
|
self.requestHistoryAroundVisiblePosition(synchronous: false, reloadAtTop: false)
|
||||||
|
|
||||||
if peerId == context.account.peerId {
|
if peerId == context.account.peerId && !isArchive {
|
||||||
self.preloadArchiveListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: true)
|
self.preloadArchiveListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1502,8 +1502,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
public func loadHole(anchor: SparseItemGrid.HoleAnchor, at location: SparseItemGrid.HoleLocation) -> Signal<Never, NoError> {
|
public func loadHole(anchor: SparseItemGrid.HoleAnchor, at location: SparseItemGrid.HoleLocation) -> Signal<Never, NoError> {
|
||||||
let listSource = self.listSource
|
let listSource = self.listSource
|
||||||
return Signal { _ in
|
return Signal { subscriber in
|
||||||
listSource.loadMore()
|
listSource.loadMore(completion: {
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
return EmptyDisposable
|
return EmptyDisposable
|
||||||
}
|
}
|
||||||
@ -1584,8 +1589,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
localMonthTimestamp: Month(localTimestamp: item.timestamp + timezoneOffset).packedValue
|
localMonthTimestamp: Month(localTimestamp: item.timestamp + timezoneOffset).packedValue
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if mappedItems.count < state.totalCount, let lastItem = state.items.last {
|
if mappedItems.count < state.totalCount, let lastItem = state.items.last, let loadMoreToken = state.loadMoreToken {
|
||||||
mappedHoles.append(VisualMediaHoleAnchor(index: mappedItems.count, storyId: 1, localMonthTimestamp: Month(localTimestamp: lastItem.timestamp + timezoneOffset).packedValue))
|
mappedHoles.append(VisualMediaHoleAnchor(index: mappedItems.count, storyId: Int32(loadMoreToken), localMonthTimestamp: Month(localTimestamp: lastItem.timestamp + timezoneOffset).packedValue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalCount = state.totalCount
|
totalCount = state.totalCount
|
||||||
|
@ -125,11 +125,17 @@ public final class ArchiveInfoContentComponent: Component {
|
|||||||
contentHeight += iconSize
|
contentHeight += iconSize
|
||||||
contentHeight += 15.0
|
contentHeight += 15.0
|
||||||
|
|
||||||
|
let titleString = NSMutableAttributedString()
|
||||||
|
titleString.append(NSAttributedString(string: "This is Your Archive", font: Font.semibold(19.0), textColor: component.theme.list.itemPrimaryTextColor))
|
||||||
|
let imageAttachment = NSTextAttachment()
|
||||||
|
imageAttachment.image = self.iconBackground.image
|
||||||
|
titleString.append(NSAttributedString(attachment: imageAttachment))
|
||||||
|
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
let titleSize = self.title.update(
|
let titleSize = self.title.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: "This is Your Archive", font: Font.semibold(19.0), textColor: component.theme.list.itemPrimaryTextColor)),
|
text: .plain(titleString),
|
||||||
maximumNumberOfLines: 1
|
maximumNumberOfLines: 1
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
|
@ -163,7 +163,7 @@ final class StoryItemContentComponent: Component {
|
|||||||
videoNode.isHidden = true
|
videoNode.isHidden = true
|
||||||
|
|
||||||
self.videoNode = videoNode
|
self.videoNode = videoNode
|
||||||
self.addSubnode(videoNode)
|
self.addSubview(videoNode.view)
|
||||||
|
|
||||||
videoNode.playbackCompleted = { [weak self] in
|
videoNode.playbackCompleted = { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
|
@ -365,6 +365,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
var preparingToDisplayViewList: Bool = false
|
var preparingToDisplayViewList: Bool = false
|
||||||
var displayViewList: Bool = false
|
var displayViewList: Bool = false
|
||||||
var viewLists: [Int32: ViewList] = [:]
|
var viewLists: [Int32: ViewList] = [:]
|
||||||
|
let viewListsContainer: UIView
|
||||||
|
|
||||||
var isEditingStory: Bool = false
|
var isEditingStory: Bool = false
|
||||||
|
|
||||||
@ -440,6 +441,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
self.inputPanelContainer.isUserInteractionEnabled = false
|
self.inputPanelContainer.isUserInteractionEnabled = false
|
||||||
self.inputPanelContainer.layer.cornerRadius = 11.0
|
self.inputPanelContainer.layer.cornerRadius = 11.0
|
||||||
|
|
||||||
|
self.viewListsContainer = SparseContainerView()
|
||||||
|
self.viewListsContainer.clipsToBounds = true
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.itemsContainerView.addSubview(self.scroller)
|
self.itemsContainerView.addSubview(self.scroller)
|
||||||
@ -457,6 +461,8 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
self.controlsContainerView.addSubview(self.closeButton)
|
self.controlsContainerView.addSubview(self.closeButton)
|
||||||
self.closeButton.addTarget(self, action: #selector(self.closePressed), for: .touchUpInside)
|
self.closeButton.addTarget(self, action: #selector(self.closePressed), for: .touchUpInside)
|
||||||
|
|
||||||
|
self.addSubview(self.viewListsContainer)
|
||||||
|
|
||||||
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
|
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
|
||||||
tapRecognizer.delegate = self
|
tapRecognizer.delegate = self
|
||||||
self.itemsContainerView.addGestureRecognizer(tapRecognizer)
|
self.itemsContainerView.addGestureRecognizer(tapRecognizer)
|
||||||
@ -983,7 +989,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
let combinedFraction = offsetFraction + centerFraction
|
let combinedFraction = offsetFraction + centerFraction
|
||||||
let combinedFractionSign: CGFloat = combinedFraction < 0.0 ? -1.0 : 1.0
|
let combinedFractionSign: CGFloat = combinedFraction < 0.0 ? -1.0 : 1.0
|
||||||
|
|
||||||
let fractionDistanceToCenter: CGFloat = min(1.0, abs(combinedFraction))
|
let unboundFractionDistanceToCenter: CGFloat = abs(combinedFraction)
|
||||||
|
let fractionDistanceToCenter: CGFloat = min(1.0, unboundFractionDistanceToCenter)
|
||||||
|
let _ = fractionDistanceToCenter
|
||||||
|
|
||||||
var itemPositionX = centralItemX
|
var itemPositionX = centralItemX
|
||||||
itemPositionX += min(1.0, abs(combinedFraction)) * combinedFractionSign * scaledFullItemScrollDistance
|
itemPositionX += min(1.0, abs(combinedFraction)) * combinedFractionSign * scaledFullItemScrollDistance
|
||||||
@ -1122,7 +1130,15 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
}
|
}
|
||||||
itemTransition.setTransform(view: visibleItem.contentContainerView, transform: transform)
|
itemTransition.setTransform(view: visibleItem.contentContainerView, transform: transform)
|
||||||
itemTransition.setCornerRadius(layer: visibleItem.contentContainerView.layer, cornerRadius: 12.0 * (1.0 / itemScale))
|
itemTransition.setCornerRadius(layer: visibleItem.contentContainerView.layer, cornerRadius: 12.0 * (1.0 / itemScale))
|
||||||
itemTransition.setAlpha(view: visibleItem.contentContainerView, alpha: 1.0 * (1.0 - fractionDistanceToCenter) + 0.75 * fractionDistanceToCenter)
|
|
||||||
|
let countedFractionDistanceToCenter: CGFloat = max(0.0, min(1.0, unboundFractionDistanceToCenter / 3.0))
|
||||||
|
var itemAlpha: CGFloat = 1.0 * (1.0 - countedFractionDistanceToCenter) + 0.0 * countedFractionDistanceToCenter
|
||||||
|
itemAlpha = max(0.0, min(1.0, itemAlpha))
|
||||||
|
|
||||||
|
let collapsedAlpha = itemAlpha * itemLayout.contentScaleFraction + 0.0 * (1.0 - itemLayout.contentScaleFraction)
|
||||||
|
itemAlpha = (1.0 - fractionDistanceToCenter) * itemAlpha + fractionDistanceToCenter * collapsedAlpha
|
||||||
|
|
||||||
|
itemTransition.setAlpha(view: visibleItem.contentContainerView, alpha: itemAlpha)
|
||||||
|
|
||||||
var itemProgressMode = self.itemProgressMode()
|
var itemProgressMode = self.itemProgressMode()
|
||||||
if index != centralIndex {
|
if index != centralIndex {
|
||||||
@ -2139,12 +2155,12 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
|
|
||||||
var viewListFrame = CGRect(origin: CGPoint(x: viewListBaseOffsetX, y: availableSize.height - viewListSize.height), size: viewListSize)
|
var viewListFrame = CGRect(origin: CGPoint(x: viewListBaseOffsetX, y: availableSize.height - viewListSize.height), size: viewListSize)
|
||||||
let indexDistance = CGFloat(max(-1, min(1, itemIndex - currentIndex)))
|
let indexDistance = CGFloat(max(-1, min(1, itemIndex - currentIndex)))
|
||||||
viewListFrame.origin.x += indexDistance * availableSize.width
|
viewListFrame.origin.x += indexDistance * (availableSize.width + 20.0)
|
||||||
|
|
||||||
if let viewListView = viewList.view.view as? StoryItemSetViewListComponent.View {
|
if let viewListView = viewList.view.view as? StoryItemSetViewListComponent.View {
|
||||||
var animateIn = false
|
var animateIn = false
|
||||||
if viewListView.superview == nil {
|
if viewListView.superview == nil {
|
||||||
self.addSubview(viewListView)
|
self.viewListsContainer.addSubview(viewListView)
|
||||||
animateIn = true
|
animateIn = true
|
||||||
} else {
|
} else {
|
||||||
fixedAnimationOffset = viewListFrame.minX - viewListView.frame.minX
|
fixedAnimationOffset = viewListFrame.minX - viewListView.frame.minX
|
||||||
@ -2229,6 +2245,15 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
|
|
||||||
let contentFrame = CGRect(origin: CGPoint(x: 0.0, y: component.containerInsets.top - (contentSize.height - contentVisualHeight) * 0.5), size: contentSize)
|
let contentFrame = CGRect(origin: CGPoint(x: 0.0, y: component.containerInsets.top - (contentSize.height - contentVisualHeight) * 0.5), size: contentSize)
|
||||||
|
|
||||||
|
transition.setFrame(view: self.viewListsContainer, frame: CGRect(origin: CGPoint(x: contentFrame.minX, y: 0.0), size: CGSize(width: contentSize.width, height: availableSize.height)))
|
||||||
|
let viewListsRadius: CGFloat
|
||||||
|
if component.metrics.widthClass == .regular {
|
||||||
|
viewListsRadius = 10.0
|
||||||
|
} else {
|
||||||
|
viewListsRadius = 0.0
|
||||||
|
}
|
||||||
|
transition.setCornerRadius(layer: self.viewListsContainer.layer, cornerRadius: viewListsRadius)
|
||||||
|
|
||||||
transition.setFrame(view: self.inputPanelContainer, frame: contentFrame)
|
transition.setFrame(view: self.inputPanelContainer, frame: contentFrame)
|
||||||
|
|
||||||
let itemLayout = ItemLayout(
|
let itemLayout = ItemLayout(
|
||||||
|
@ -586,10 +586,11 @@ final class StoryItemSetViewListComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if itemUpdated || viewsNilUpdated {
|
if itemUpdated || viewsNilUpdated {
|
||||||
self.viewListState = nil
|
|
||||||
self.viewListDisposable?.dispose()
|
self.viewListDisposable?.dispose()
|
||||||
|
|
||||||
if let views = component.storyItem.views {
|
if let views = component.storyItem.views {
|
||||||
|
self.viewListState = nil
|
||||||
|
|
||||||
let viewList: EngineStoryViewListContext
|
let viewList: EngineStoryViewListContext
|
||||||
if let current = component.sharedListsContext.viewLists[StoryId(peerId: component.peerId, id: component.storyItem.id)] {
|
if let current = component.sharedListsContext.viewLists[StoryId(peerId: component.peerId, id: component.storyItem.id)] {
|
||||||
viewList = current
|
viewList = current
|
||||||
@ -618,6 +619,8 @@ final class StoryItemSetViewListComponent: Component {
|
|||||||
})
|
})
|
||||||
applyState = true
|
applyState = true
|
||||||
let _ = synchronous
|
let _ = synchronous
|
||||||
|
} else {
|
||||||
|
self.viewListState = EngineStoryViewListContext.State(totalCount: 0, items: [], loadMoreToken: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,8 +609,8 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
if self.storyStats != storyStats || self.presentationData.theme.theme !== theme || force {
|
if self.storyStats != storyStats || self.presentationData.theme.theme !== theme || force {
|
||||||
self.avatarNode.setStoryStats(storyStats: storyStats.flatMap { storyStats in
|
self.avatarNode.setStoryStats(storyStats: storyStats.flatMap { storyStats in
|
||||||
return AvatarNode.StoryStats(
|
return AvatarNode.StoryStats(
|
||||||
totalCount: storyStats.totalCount,
|
totalCount: storyStats.totalCount != 0 ? 1 : 0,
|
||||||
unseenCount: storyStats.unseenCount,
|
unseenCount: storyStats.unseenCount != 0 ? 1 : 0,
|
||||||
hasUnseenCloseFriendsItems: storyStats.hasUnseenCloseFriends
|
hasUnseenCloseFriendsItems: storyStats.hasUnseenCloseFriends
|
||||||
)
|
)
|
||||||
}, presentationParams: AvatarNode.StoryPresentationParams(
|
}, presentationParams: AvatarNode.StoryPresentationParams(
|
||||||
|
@ -406,12 +406,15 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
|||||||
|
|
||||||
if hasAvatar {
|
if hasAvatar {
|
||||||
if let effectiveAuthor = effectiveAuthor {
|
if let effectiveAuthor = effectiveAuthor {
|
||||||
let storyStats: PeerStoryStats?
|
var storyStats: PeerStoryStats?
|
||||||
switch content {
|
if case .peer(id: context.account.peerId) = chatLocation {
|
||||||
case let .message(_, _, _, attributes, _):
|
} else {
|
||||||
storyStats = attributes.authorStoryStats
|
switch content {
|
||||||
case let .group(messages):
|
case let .message(_, _, _, attributes, _):
|
||||||
storyStats = messages.first?.3.authorStoryStats
|
storyStats = attributes.authorStoryStats
|
||||||
|
case let .group(messages):
|
||||||
|
storyStats = messages.first?.3.authorStoryStats
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarHeader = ChatMessageAvatarHeader(timestamp: content.index.timestamp, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), message: message, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction, storyStats: storyStats)
|
avatarHeader = ChatMessageAvatarHeader(timestamp: content.index.timestamp, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), message: message, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction, storyStats: storyStats)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user