mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Stories
This commit is contained in:
parent
c34f459a31
commit
eb78d075d7
@ -3118,8 +3118,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollToStories() {
|
||||
public func scrollToStories(peerId: EnginePeer.Id? = nil) {
|
||||
self.chatListDisplayNode.scrollToStories(animated: false)
|
||||
|
||||
if let peerId, let componentView = self.chatListHeaderView(), let storyPeerListView = componentView.storyPeerListView() {
|
||||
storyPeerListView.ensureItemVisible(peerId: peerId)
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollToStoriesAnimated() {
|
||||
|
@ -439,6 +439,13 @@ private final class ItemNode: ASDisplayNode {
|
||||
return deleteButtonNode.view
|
||||
}
|
||||
}
|
||||
|
||||
if self.buttonNode.isUserInteractionEnabled {
|
||||
if let result = self.buttonNode.view.hitTest(self.view.convert(point, to: self.buttonNode.view), with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return super.hitTest(point, with: event)
|
||||
}
|
||||
}
|
||||
|
@ -820,7 +820,7 @@ public final class SparseItemGrid: ASDisplayNode {
|
||||
self.scrollView.setContentOffset(CGPoint(x: 0.0, y: contentOffset), animated: false)
|
||||
}
|
||||
|
||||
func ensureItemVisible(index: Int) {
|
||||
func ensureItemVisible(index: Int, anyAmount: Bool) {
|
||||
guard let layout = self.layout, let _ = self.items else {
|
||||
return
|
||||
}
|
||||
@ -830,8 +830,14 @@ public final class SparseItemGrid: ASDisplayNode {
|
||||
|
||||
let itemFrame = layout.frame(at: index)
|
||||
let visibleBounds = self.scrollView.bounds
|
||||
if itemFrame.intersects(visibleBounds) {
|
||||
return
|
||||
if anyAmount {
|
||||
if itemFrame.intersects(visibleBounds) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if visibleBounds.contains(itemFrame) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var contentOffset: CGFloat
|
||||
@ -1936,11 +1942,11 @@ public final class SparseItemGrid: ASDisplayNode {
|
||||
currentViewport.scrollToItem(at: index)
|
||||
}
|
||||
|
||||
public func ensureItemVisible(index: Int) {
|
||||
public func ensureItemVisible(index: Int, anyAmount: Bool = true) {
|
||||
guard let currentViewport = self.currentViewport else {
|
||||
return
|
||||
}
|
||||
currentViewport.ensureItemVisible(index: index)
|
||||
currentViewport.ensureItemVisible(index: index, anyAmount: anyAmount)
|
||||
}
|
||||
|
||||
public func scrollToTop() -> Bool {
|
||||
|
@ -1000,6 +1000,15 @@ func _internal_uploadStoryImpl(postbox: Postbox, network: Network, accountPeerId
|
||||
updatedItems.append(updatedItem)
|
||||
}
|
||||
transaction.setStoryItems(peerId: toPeerId, items: items)
|
||||
|
||||
if let peer = transaction.getPeer(toPeerId) as? TelegramChannel, let storiesHidden = peer.storiesHidden {
|
||||
let subscriptionsKey: PostboxStorySubscriptionsKey = storiesHidden ? .hidden : .filtered
|
||||
var (state, peerIds) = transaction.getAllStorySubscriptions(key: subscriptionsKey)
|
||||
if !peerIds.contains(toPeerId) {
|
||||
peerIds.append(toPeerId)
|
||||
}
|
||||
transaction.replaceAllStorySubscriptions(key: .filtered, state: state, peerIds: peerIds)
|
||||
}
|
||||
}
|
||||
|
||||
id = idValue
|
||||
|
@ -953,6 +953,10 @@ public extension TelegramEngine {
|
||||
return lhs.peer.id < rhs.peer.id
|
||||
})
|
||||
|
||||
if !isHidden {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
return EngineStorySubscriptions(accountItem: accountItem, items: items, hasMoreToken: hasMoreToken)
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func _internal_updatePeerIsContact(transaction: Transaction, user: TelegramUser,
|
||||
}
|
||||
}
|
||||
|
||||
private func _internal_updateChannelMembership(transaction: Transaction, channel: TelegramChannel, isMember: Bool) {
|
||||
private func _internal_updateChannelMembership(transaction: Transaction, channel: TelegramChannel, isMember: Bool, justJoined: Bool) {
|
||||
if isMember, let storiesHidden = channel.storiesHidden {
|
||||
if storiesHidden {
|
||||
if transaction.storySubscriptionsContains(key: .filtered, peerId: channel.id) {
|
||||
@ -155,6 +155,10 @@ private func _internal_updateChannelMembership(transaction: Transaction, channel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if justJoined {
|
||||
_internal_addSynchronizePeerStoriesOperation(peerId: channel.id, transaction: transaction)
|
||||
}
|
||||
} else {
|
||||
if transaction.storySubscriptionsContains(key: .filtered, peerId: channel.id) {
|
||||
var (state, peerIds) = transaction.getAllStorySubscriptions(key: .filtered)
|
||||
@ -191,7 +195,7 @@ public func updatePeersCustom(transaction: Transaction, peers: [Peer], update: (
|
||||
if let updated = updated as? TelegramChannel {
|
||||
let isMember = updated.participationStatus == .member
|
||||
if isMember != wasMember || updated.storiesHidden != wasHidden {
|
||||
_internal_updateChannelMembership(transaction: transaction, channel: updated, isMember: isMember)
|
||||
_internal_updateChannelMembership(transaction: transaction, channel: updated, isMember: isMember, justJoined: previous == nil || wasHidden == nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,21 +481,29 @@ private final class CaptureProtectedItemLayer: AVSampleBufferDisplayLayer, ItemL
|
||||
}
|
||||
|
||||
private final class ItemTransitionView: UIView {
|
||||
private weak var itemLayer: ItemLayer?
|
||||
private weak var itemLayer: CALayer?
|
||||
private var copyDurationLayer: SimpleLayer?
|
||||
|
||||
private var durationLayerBottomLeftPosition: CGPoint?
|
||||
|
||||
init(itemLayer: ItemLayer?) {
|
||||
init(itemLayer: CALayer?) {
|
||||
self.itemLayer = itemLayer
|
||||
|
||||
super.init(frame: CGRect())
|
||||
|
||||
if let itemLayer {
|
||||
self.layer.contents = itemLayer.contents
|
||||
self.layer.contentsRect = itemLayer.contentsRect
|
||||
|
||||
if let durationLayer = itemLayer.durationLayer {
|
||||
var durationLayer: CALayer?
|
||||
if let itemLayer = itemLayer as? CaptureProtectedItemLayer {
|
||||
durationLayer = itemLayer.durationLayer
|
||||
self.layer.contents = itemLayer.getContents()
|
||||
} else if let itemLayer = itemLayer as? ItemLayer {
|
||||
durationLayer = itemLayer.durationLayer
|
||||
self.layer.contents = itemLayer.contents
|
||||
}
|
||||
|
||||
if let durationLayer {
|
||||
let copyDurationLayer = SimpleLayer()
|
||||
copyDurationLayer.contents = durationLayer.contents
|
||||
copyDurationLayer.contentsRect = durationLayer.contentsRect
|
||||
@ -1074,7 +1082,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
destinationView: self.view,
|
||||
transitionView: StoryContainerScreen.TransitionView(
|
||||
makeView: { [weak foundItemLayer] in
|
||||
return ItemTransitionView(itemLayer: foundItemLayer as? ItemLayer)
|
||||
return ItemTransitionView(itemLayer: foundItemLayer)
|
||||
},
|
||||
updateView: { view, state, transition in
|
||||
(view as? ItemTransitionView)?.update(state: state, transition: transition)
|
||||
@ -1104,10 +1112,15 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
return
|
||||
}
|
||||
if let itemId {
|
||||
let anyAmount = self.itemInteraction.hiddenMedia.isEmpty
|
||||
self.itemInteraction.hiddenMedia = Set([itemId.id])
|
||||
if let items = self.items, let item = items.items.first(where: { $0.id == AnyHashable(itemId.id) }) {
|
||||
self.itemGrid.ensureItemVisible(index: item.index, anyAmount: anyAmount)
|
||||
}
|
||||
} else {
|
||||
self.itemInteraction.hiddenMedia = Set()
|
||||
}
|
||||
|
||||
self.updateHiddenItems()
|
||||
})
|
||||
|
||||
|
@ -338,6 +338,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
private let backgroundEffectView: BlurredBackgroundView
|
||||
|
||||
private let focusedItem = ValuePromise<StoryId?>(nil, ignoreRepeated: true)
|
||||
private var stateValue: StoryContentContextState?
|
||||
private var contentUpdatedDisposable: Disposable?
|
||||
|
||||
private var stealthModeActiveUntilTimestamp: Int32?
|
||||
@ -412,7 +413,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
self.layer.addSublayer(self.backgroundLayer)
|
||||
|
||||
let horizontalPanRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.panGesture(_:)), allowedDirections: { [weak self] point in
|
||||
guard let self, let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
guard let self, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
return []
|
||||
}
|
||||
if let environment = self.environment, case .regular = environment.metrics.widthClass {
|
||||
@ -430,7 +431,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
|
||||
//TODO:move dismiss pan
|
||||
/*let verticalPanRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.dismissPanGesture(_:)), allowedDirections: { [weak self] point in
|
||||
guard let self, let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
guard let self, let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
return []
|
||||
}
|
||||
if let environment = self.environment, case .regular = environment.metrics.widthClass {
|
||||
@ -460,7 +461,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
guard let self else {
|
||||
return false
|
||||
}
|
||||
guard let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
guard let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
return false
|
||||
}
|
||||
if !itemSetComponentView.allowsExternalGestures(point: touch.location(in: itemSetComponentView)) {
|
||||
@ -480,7 +481,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
guard let self else {
|
||||
return false
|
||||
}
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
let itemLocation = self.convert(pinchLocation, to: itemSetComponentView)
|
||||
if itemSetComponentView.allowsExternalGestures(point: itemLocation) {
|
||||
@ -498,7 +499,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
var pinchLocation = pinchLocation
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
pinchLocation = self.convert(pinchLocation, to: itemSetComponentView)
|
||||
}
|
||||
@ -634,7 +635,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||
guard let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
guard let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -678,7 +679,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
private func updateHorizontalPan(translation: CGPoint) {
|
||||
var translation = translation
|
||||
|
||||
if var itemSetPanState = self.itemSetPanState, self.bounds.width > 0.0, let component = self.component, let stateValue = component.content.stateValue, let _ = stateValue.slice {
|
||||
if var itemSetPanState = self.itemSetPanState, self.bounds.width > 0.0, let stateValue = self.stateValue, let _ = stateValue.slice {
|
||||
func rubberBandingOffset(offset: CGFloat, bandingStart: CGFloat) -> CGFloat {
|
||||
let bandedOffset = offset - bandingStart
|
||||
let range: CGFloat = 600.0
|
||||
@ -706,7 +707,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
if var itemSetPanState = self.itemSetPanState {
|
||||
var shouldDismiss = false
|
||||
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let _ = stateValue.slice {
|
||||
if let component = self.component, let stateValue = self.stateValue, let _ = stateValue.slice {
|
||||
var direction: StoryContentContextNavigation.PeerDirection?
|
||||
var mayDismiss = false
|
||||
if itemSetPanState.fraction <= -0.3 {
|
||||
@ -787,7 +788,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
case .began:
|
||||
self.dismissAllTooltips()
|
||||
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if itemSetComponentView.hasActiveDeactivateableInput() {
|
||||
itemSetComponentView.deactivateInput()
|
||||
@ -806,7 +807,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
self.state?.updated(transition: .immediate)
|
||||
|
||||
if translation.y < -40.0 {
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if let activateInputWhileDragging = itemSetComponentView.activateInputWhileDragging() {
|
||||
activateInputWhileDragging()
|
||||
@ -830,7 +831,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring)))
|
||||
self.environment?.controller()?.dismiss()
|
||||
} else if translation.y < -200.0 || (translation.y < -100.0 && velocity.y < -100.0) {
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if itemSetComponentView.activateInput() {
|
||||
updateState = false
|
||||
@ -872,7 +873,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
let location = recognizer.location(in: recognizer.view)
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let currentItemView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let currentItemView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if currentItemView.hasActiveDeactivateableInput() {
|
||||
currentItemView.deactivateInput()
|
||||
} else {
|
||||
@ -893,7 +894,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
}
|
||||
|
||||
if subview is ItemSetView {
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], itemSetView === subview {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], itemSetView === subview {
|
||||
if let result = subview.hitTest(self.convert(point, to: subview), with: event) {
|
||||
return result
|
||||
}
|
||||
@ -934,7 +935,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
self.backgroundLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.28, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||
self.backgroundEffectView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.28, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||
|
||||
if let transitionIn = self.component?.transitionIn, let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let transitionIn = self.component?.transitionIn, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id] {
|
||||
if let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
itemSetComponentView.animateIn(transitionIn: transitionIn)
|
||||
}
|
||||
@ -958,7 +959,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
if !value {
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let currentItemView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let currentItemView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
currentItemView.maybeDisplayReactionTooltip()
|
||||
}
|
||||
}
|
||||
@ -971,7 +972,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
func animateOut(completion: @escaping () -> Void) {
|
||||
self.isAnimatingOut = true
|
||||
|
||||
if !self.dismissWithoutTransitionOut, let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View, let transitionOut = component.transitionOut(slice.peer.id, slice.item.storyItem.id) {
|
||||
if !self.dismissWithoutTransitionOut, let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View, let transitionOut = component.transitionOut(slice.peer.id, slice.item.storyItem.id) {
|
||||
self.state?.updated(transition: .immediate)
|
||||
|
||||
let transition = Transition(animation: .curve(duration: 0.25, curve: .easeInOut))
|
||||
@ -991,7 +992,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
focusedItemPromise.set(.single(nil))
|
||||
})
|
||||
} else {
|
||||
if let component = self.component, let stateValue = component.content.stateValue, let slice = stateValue.slice, let transitionOut = component.transitionOut(slice.peer.id, slice.item.storyItem.id) {
|
||||
if let component = self.component, let stateValue = self.stateValue, let slice = stateValue.slice, let transitionOut = component.transitionOut(slice.peer.id, slice.item.storyItem.id) {
|
||||
transitionOut.completed()
|
||||
}
|
||||
|
||||
@ -1020,10 +1021,10 @@ private final class StoryContainerScreenComponent: Component {
|
||||
private func updateVolumeButtonMonitoring() {
|
||||
if self.volumeButtonsListener == nil {
|
||||
let buttonAction = { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard let slice = component.content.stateValue?.slice else {
|
||||
guard let slice = self.stateValue?.slice else {
|
||||
return
|
||||
}
|
||||
var isSilentVideo = false
|
||||
@ -1038,7 +1039,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
}
|
||||
|
||||
if isSilentVideo {
|
||||
if let slice = component.content.stateValue?.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let currentItemView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
if let slice = self.stateValue?.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let currentItemView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||
currentItemView.displayMutedVideoTooltip()
|
||||
}
|
||||
} else {
|
||||
@ -1072,7 +1073,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
if let stateValue = component.content.stateValue, let slice = stateValue.slice {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice {
|
||||
if case .next = direction, slice.nextItemId == nil, (slice.item.position == nil || slice.item.position == slice.totalCount - 1) {
|
||||
if stateValue.nextSlice == nil {
|
||||
environment.controller()?.dismiss()
|
||||
@ -1194,10 +1195,15 @@ private final class StoryContainerScreenComponent: Component {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if self.isAnimatingOut || self.didAnimateOut {
|
||||
return
|
||||
}
|
||||
|
||||
let stateValue = component.content.stateValue
|
||||
|
||||
var focusedItemId: StoryId?
|
||||
var isVideo = false
|
||||
if let slice = component.content.stateValue?.slice {
|
||||
if let slice = stateValue?.slice {
|
||||
focusedItemId = StoryId(peerId: slice.peer.id, id: slice.item.storyItem.id)
|
||||
if case .file = slice.item.storyItem.media {
|
||||
isVideo = true
|
||||
@ -1206,25 +1212,40 @@ private final class StoryContainerScreenComponent: Component {
|
||||
self.focusedItem.set(focusedItemId)
|
||||
self.contentWantsVolumeButtonMonitoring.set(isVideo)
|
||||
|
||||
if update {
|
||||
if component.content.stateValue?.slice == nil {
|
||||
self.environment?.controller()?.dismiss()
|
||||
} else {
|
||||
let startTime = CFAbsoluteTimeGetCurrent()
|
||||
self.state?.updated(transition: .immediate)
|
||||
print("update time: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
||||
var hasItems = false
|
||||
if let stateValue {
|
||||
if stateValue.slice != nil {
|
||||
hasItems = true
|
||||
}
|
||||
}
|
||||
|
||||
if !hasItems {
|
||||
self.dismissWithoutTransitionOut = true
|
||||
environment.controller()?.dismiss()
|
||||
} else {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
self.stateValue = stateValue
|
||||
|
||||
if update {
|
||||
if self.stateValue?.slice == nil {
|
||||
self.environment?.controller()?.dismiss()
|
||||
} else {
|
||||
let startTime = CFAbsoluteTimeGetCurrent()
|
||||
self.state?.updated(transition: .immediate)
|
||||
print("update time: \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms")
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.contentUpdatedDisposable?.dispose()
|
||||
self.stateValue = component.content.stateValue
|
||||
self.contentUpdatedDisposable = (component.content.updated
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
guard let self, let component = self.component else {
|
||||
@ -1268,7 +1289,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
}
|
||||
|
||||
if let pendingNavigationToItemId = self.pendingNavigationToItemId {
|
||||
if let slice = component.content.stateValue?.slice, slice.peer.id == pendingNavigationToItemId.peerId {
|
||||
if let slice = self.stateValue?.slice, slice.peer.id == pendingNavigationToItemId.peerId {
|
||||
if slice.item.storyItem.id == pendingNavigationToItemId.id {
|
||||
self.pendingNavigationToItemId = nil
|
||||
}
|
||||
@ -1315,7 +1336,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
|
||||
var currentSlices: [StoryContentContextState.FocusedSlice] = []
|
||||
var focusedIndex: Int?
|
||||
if let component = self.component, let stateValue = component.content.stateValue {
|
||||
if let stateValue = self.stateValue {
|
||||
if let previousSlice = stateValue.previousSlice {
|
||||
currentSlices.append(previousSlice)
|
||||
}
|
||||
@ -1458,7 +1479,7 @@ private final class StoryContainerScreenComponent: Component {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let stateValue = component.content.stateValue, let slice = stateValue.slice {
|
||||
if let stateValue = self.stateValue, let slice = stateValue.slice {
|
||||
if slice.nextItemId != nil {
|
||||
component.content.navigate(navigation: .item(.next))
|
||||
} else if slice.previousItemId != nil {
|
||||
|
@ -215,7 +215,7 @@ final class StoryItemContentComponent: Component {
|
||||
videoNode.isHidden = true
|
||||
|
||||
self.videoNode = videoNode
|
||||
self.addSubview(videoNode.view)
|
||||
self.insertSubview(videoNode.view, aboveSubview: self.imageView)
|
||||
|
||||
videoNode.playbackCompleted = { [weak self] in
|
||||
guard let self else {
|
||||
|
@ -444,6 +444,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
var reactionContextNode: ReactionContextNode?
|
||||
weak var disappearingReactionContextNode: ReactionContextNode?
|
||||
var displayLikeReactions: Bool = false
|
||||
var tempReactionsGesture: ContextGesture?
|
||||
var waitingForReactionAnimateOutToLike: MessageReaction.Reaction?
|
||||
weak var standaloneReactionAnimation: StandaloneReactionAnimation?
|
||||
|
||||
@ -1656,7 +1657,10 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
externalViews: nil,
|
||||
expandFraction: footerExpandFraction,
|
||||
expandViewStats: { [weak self] in
|
||||
guard let self else {
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
if self.viewLists[component.slice.item.storyItem.id] == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -2025,6 +2029,13 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.contextController?.dismiss()
|
||||
self.contextController = nil
|
||||
|
||||
if let standaloneReactionAnimation = self.standaloneReactionAnimation {
|
||||
self.standaloneReactionAnimation = nil
|
||||
standaloneReactionAnimation.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak standaloneReactionAnimation] _ in
|
||||
standaloneReactionAnimation?.view.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
|
||||
if let inputPanelView = self.inputPanel.view {
|
||||
inputPanelView.layer.animatePosition(
|
||||
from: CGPoint(),
|
||||
@ -2769,12 +2780,11 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.performLikeAction()
|
||||
},
|
||||
likeOptionsAction: !haveLikeOptions ? nil : { [weak self] sourceView, gesture in
|
||||
gesture?.cancel()
|
||||
|
||||
guard let self else {
|
||||
gesture?.cancel()
|
||||
return
|
||||
}
|
||||
self.performLikeOptionsAction(sourceView: sourceView)
|
||||
self.performLikeOptionsAction(sourceView: sourceView, gesture: gesture)
|
||||
},
|
||||
inputModeAction: { [weak self] in
|
||||
guard let self else {
|
||||
@ -3108,20 +3118,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
self.isSearchActive = false
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)))
|
||||
},
|
||||
expandViewStats: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
if self.viewListDisplayState == .hidden {
|
||||
self.viewListDisplayState = .half
|
||||
|
||||
self.preparingToDisplayViewList = true
|
||||
self.updateScrolling(transition: .immediate)
|
||||
self.preparingToDisplayViewList = false
|
||||
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)))
|
||||
}
|
||||
expandViewStats: {
|
||||
},
|
||||
deleteAction: { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
@ -4160,6 +4157,26 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
reactionContextNode.forceDark = true
|
||||
self.reactionContextNode = reactionContextNode
|
||||
|
||||
if let tempReactionsGesture = self.tempReactionsGesture {
|
||||
tempReactionsGesture.externalUpdated = { [weak self] view, point in
|
||||
guard let self, let view, let reactionContextNode = self.reactionContextNode else {
|
||||
return
|
||||
}
|
||||
let presentationPoint = view.convert(point, to: reactionContextNode.view)
|
||||
reactionContextNode.highlightGestureMoved(location: presentationPoint, hover: false)
|
||||
}
|
||||
tempReactionsGesture.externalEnded = { [weak self] viewAndPoint in
|
||||
guard let self, let viewAndPoint, let reactionContextNode = self.reactionContextNode else {
|
||||
return
|
||||
}
|
||||
let _ = viewAndPoint
|
||||
/*let (view, point) = viewAndPoint
|
||||
let presentationPoint = view.convert(point, to: reactionContextNode.view)
|
||||
let _ = presentationPoint*/
|
||||
reactionContextNode.highlightGestureFinished(performAction: true)
|
||||
}
|
||||
}
|
||||
|
||||
reactionContextNode.reactionSelected = { [weak self] updateReaction, _ in
|
||||
guard let self else {
|
||||
return
|
||||
@ -4553,7 +4570,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
} else if let inputPanelFrameValue {
|
||||
component.externalState.derivedBottomInset = availableSize.height - min(inputPanelFrameValue.minY, contentFrame.maxY)
|
||||
} else {
|
||||
component.externalState.derivedBottomInset = 0.0
|
||||
component.externalState.derivedBottomInset = availableSize.height - itemsContainerFrame.maxY
|
||||
}
|
||||
|
||||
if !"".isEmpty {
|
||||
@ -5332,12 +5349,14 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
private func performLikeOptionsAction(sourceView: UIView) {
|
||||
private func performLikeOptionsAction(sourceView: UIView, gesture: ContextGesture?) {
|
||||
HapticFeedback().tap()
|
||||
|
||||
self.displayLikeReactions = true
|
||||
self.tempReactionsGesture = gesture
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
|
||||
self.updateIsProgressPaused()
|
||||
self.tempReactionsGesture = nil
|
||||
}
|
||||
|
||||
func dismissAllTooltips() {
|
||||
|
@ -355,7 +355,7 @@ public final class StoryFooterPanelComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
self.viewStatsButton.isEnabled = viewCount != 0
|
||||
self.viewStatsButton.isEnabled = viewCount != 0 && !component.isChannel
|
||||
|
||||
var rightContentOffset: CGFloat = availableSize.width - 12.0
|
||||
|
||||
|
@ -460,6 +460,15 @@ public final class StoryPeerListComponent: Component {
|
||||
})
|
||||
}
|
||||
|
||||
public func ensureItemVisible(peerId: EnginePeer.Id) {
|
||||
if let visibleItem = self.visibleItems[peerId], let itemView = visibleItem.view.view as? StoryPeerListItemComponent.View {
|
||||
let itemFrame = itemView.frame.offsetBy(dx: self.scrollView.bounds.minX, dy: 0.0)
|
||||
if !self.scrollView.bounds.contains(itemFrame.insetBy(dx: 20.0, dy: 0.0)) {
|
||||
self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -40.0, dy: 0.0), animated: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func setLoadingItem(peerId: EnginePeer.Id, signal: Signal<Never, NoError>) {
|
||||
var applyLoadingItem = true
|
||||
self.loadingItemDisposable?.dispose()
|
||||
|
@ -10012,7 +10012,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
|
||||
cancelImpl?()
|
||||
}))
|
||||
strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
//strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
return ActionDisposable { [weak controller] in
|
||||
Queue.mainQueue().async() {
|
||||
controller?.dismiss()
|
||||
|
@ -982,6 +982,29 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
paneTransition.updateFrame(node: pane.pane.node, frame: paneFrame)
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: paneTransition)
|
||||
}
|
||||
|
||||
var removeKeys: [PeerInfoPaneKey] = []
|
||||
for (key, paneNode) in self.pendingPanes {
|
||||
if !availablePanes.contains(key) {
|
||||
removeKeys.append(key)
|
||||
paneNode.pane.node.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
for key in removeKeys {
|
||||
self.pendingPanes.removeValue(forKey: key)
|
||||
}
|
||||
removeKeys.removeAll()
|
||||
|
||||
for (key, paneNode) in self.currentPanes {
|
||||
if !availablePanes.contains(key) {
|
||||
removeKeys.append(key)
|
||||
paneNode.node.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
for key in removeKeys {
|
||||
self.currentPanes.removeValue(forKey: key)
|
||||
}
|
||||
|
||||
if !self.didSetIsReady && data != nil {
|
||||
if let currentPaneKey = self.currentPaneKey, let currentPane = self.currentPanes[currentPaneKey] {
|
||||
self.didSetIsReady = true
|
||||
|
@ -382,6 +382,17 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
}
|
||||
}
|
||||
|
||||
let target: Stories.PendingTarget
|
||||
let targetPeerId: EnginePeer.Id
|
||||
if let sendAsPeerId = options.sendAsPeerId {
|
||||
target = .peer(sendAsPeerId)
|
||||
targetPeerId = sendAsPeerId
|
||||
} else {
|
||||
target = .myStories
|
||||
targetPeerId = context.account.peerId
|
||||
}
|
||||
storyTarget = target
|
||||
|
||||
let completionImpl: () -> Void = { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
@ -393,7 +404,11 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
|> take(1)
|
||||
|> timeout(0.25, queue: .mainQueue(), alternate: .single(true))
|
||||
|> deliverOnMainQueue).start(completed: { [weak chatListController] in
|
||||
chatListController?.scrollToStories()
|
||||
guard let chatListController else {
|
||||
return
|
||||
}
|
||||
|
||||
chatListController.scrollToStories(peerId: targetPeerId)
|
||||
Queue.mainQueue().justDispatch {
|
||||
commit({})
|
||||
}
|
||||
@ -405,14 +420,6 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
}
|
||||
}
|
||||
|
||||
let target: Stories.PendingTarget
|
||||
if let sendAsPeerId = options.sendAsPeerId {
|
||||
target = .peer(sendAsPeerId)
|
||||
} else {
|
||||
target = .myStories
|
||||
}
|
||||
storyTarget = target
|
||||
|
||||
if let _ = self.chatListController as? ChatListControllerImpl {
|
||||
switch mediaResult {
|
||||
case let .image(image, dimensions):
|
||||
|
Loading…
x
Reference in New Issue
Block a user