diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 452b249cbd..d8faf72ab7 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -2277,7 +2277,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController fileprivate func openStoryCamera() { var cameraTransitionIn: StoryCameraTransitionIn? if let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { cameraTransitionIn = StoryCameraTransitionIn( sourceView: transitionView, sourceRect: transitionView.bounds, @@ -2292,7 +2292,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return nil } if let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { return StoryCameraTransitionOut( destinationView: transitionView, destinationRect: transitionView.bounds, @@ -2340,7 +2340,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController var transitionIn: StoryContainerScreen.TransitionIn? if let peer, let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: peer.id) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peer.id) { transitionIn = StoryContainerScreen.TransitionIn( sourceView: transitionView, sourceRect: transitionView.bounds, @@ -2359,10 +2359,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } if let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { + if let (transitionView, transitionContentView) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { return StoryContainerScreen.TransitionOut( destinationView: transitionView, - transitionView: nil, + transitionView: transitionContentView, destinationRect: transitionView.bounds, destinationCornerRadius: transitionView.bounds.height * 0.5, destinationIsAvatar: true, @@ -2374,6 +2374,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return nil } ) + if let componentView = self.chatListHeaderView() { + componentView.storyPeerListView()?.setPreviewedItem(signal: storyContainerScreen.focusedItem) + } self.push(storyContainerScreen) }) } @@ -2446,7 +2449,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController public func transitionViewForOwnStoryItem() -> UIView? { if let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { return transitionView } } @@ -2455,7 +2458,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController public func animateStoryUploadRipple() { if let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { let localRect = transitionView.convert(transitionView.bounds, to: self.view) self.animateRipple(centerLocation: localRect.center) } @@ -4778,7 +4781,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return nil } if finished, let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) { return StoryCameraTransitionOut( destinationView: transitionView, destinationRect: transitionView.bounds, diff --git a/submodules/ContactListUI/BUILD b/submodules/ContactListUI/BUILD index 5cdac1cefe..fb00b0da66 100644 --- a/submodules/ContactListUI/BUILD +++ b/submodules/ContactListUI/BUILD @@ -41,6 +41,7 @@ swift_library( "//submodules/TelegramUI/Components/Stories/StoryContentComponent", "//submodules/TelegramUI/Components/Stories/StoryPeerListComponent", "//submodules/TelegramUI/Components/ChatListTitleView", + "//submodules/TelegramUI/Components/ChatListHeaderComponent", "//submodules/ComponentFlow", ], visibility = [ diff --git a/submodules/ContactListUI/Sources/ContactsController.swift b/submodules/ContactListUI/Sources/ContactsController.swift index b4f9bf94be..cc14d02e07 100644 --- a/submodules/ContactListUI/Sources/ContactsController.swift +++ b/submodules/ContactListUI/Sources/ContactsController.swift @@ -529,7 +529,7 @@ public class ContactsController: ViewController { var transitionIn: StoryContainerScreen.TransitionIn? if let peer, let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: peer.id) { + if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peer.id) { transitionIn = StoryContainerScreen.TransitionIn( sourceView: transitionView, sourceRect: transitionView.bounds, @@ -548,10 +548,10 @@ public class ContactsController: ViewController { } if let componentView = self.chatListHeaderView() { - if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { + if let (transitionView, transitionContentView) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { return StoryContainerScreen.TransitionOut( destinationView: transitionView, - transitionView: nil, + transitionView: transitionContentView, destinationRect: transitionView.bounds, destinationCornerRadius: transitionView.bounds.height * 0.5, destinationIsAvatar: true, diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 36964cc4f1..7441d5e1b9 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -372,6 +372,7 @@ swift_library( "//submodules/TelegramUI/Components/ShareWithPeersScreen", "//submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode", "//submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen", + "//submodules/TelegramUI/Components/MoreHeaderButton", ] + select({ "@build_bazel_rules_apple//apple:ios_armv7": [], "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, diff --git a/submodules/TelegramUI/Components/ChatListHeaderComponent/BUILD b/submodules/TelegramUI/Components/ChatListHeaderComponent/BUILD index 63d1a68cbf..6f94cb0c07 100644 --- a/submodules/TelegramUI/Components/ChatListHeaderComponent/BUILD +++ b/submodules/TelegramUI/Components/ChatListHeaderComponent/BUILD @@ -23,6 +23,7 @@ swift_library( "//submodules/TelegramUI/Components/Stories/StoryPeerListComponent", "//submodules/Components/ComponentDisplayAdapters", "//submodules/SearchUI", + "//submodules/TelegramUI/Components/MoreHeaderButton", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/ChatListHeaderComponent/Sources/ChatListHeaderComponent.swift b/submodules/TelegramUI/Components/ChatListHeaderComponent/Sources/ChatListHeaderComponent.swift index 6e7cce713c..0527392b00 100644 --- a/submodules/TelegramUI/Components/ChatListHeaderComponent/Sources/ChatListHeaderComponent.swift +++ b/submodules/TelegramUI/Components/ChatListHeaderComponent/Sources/ChatListHeaderComponent.swift @@ -8,6 +8,7 @@ import ChatListTitleView import AppBundle import StoryPeerListComponent import TelegramCore +import MoreHeaderButton public final class HeaderNetworkStatusComponent: Component { public enum Content: Equatable { diff --git a/submodules/TelegramUI/Components/MoreHeaderButton/BUILD b/submodules/TelegramUI/Components/MoreHeaderButton/BUILD new file mode 100644 index 0000000000..de1deee74d --- /dev/null +++ b/submodules/TelegramUI/Components/MoreHeaderButton/BUILD @@ -0,0 +1,20 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "MoreHeaderButton", + module_name = "MoreHeaderButton", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/Display", + "//submodules/AsyncDisplayKit", + "//submodules/AnimationUI", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/ChatListHeaderComponent/Sources/MoreHeaderButton.swift b/submodules/TelegramUI/Components/MoreHeaderButton/Sources/MoreHeaderButton.swift similarity index 100% rename from submodules/TelegramUI/Components/ChatListHeaderComponent/Sources/MoreHeaderButton.swift rename to submodules/TelegramUI/Components/MoreHeaderButton/Sources/MoreHeaderButton.swift diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/BUILD index 0a656a777f..1abccac0f3 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/BUILD @@ -25,6 +25,7 @@ swift_library( "//submodules/ContextUI", "//submodules/UndoUI", "//submodules/TelegramUI/Components/BottomButtonPanelComponent", + "//submodules/TelegramUI/Components/MoreHeaderButton", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift index be572d7296..d3d0c9fdba 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift @@ -13,6 +13,7 @@ import ContextUI import ChatTitleView import BottomButtonPanelComponent import UndoUI +import MoreHeaderButton final class PeerInfoStoryGridScreenComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 9036d65892..92e11ea18c 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -696,6 +696,42 @@ public final class StoryItemSetContainerComponent: Component { if let rightInfoView = self.rightInfoItem?.view.view { if transitionOut.destinationIsAvatar { + let transitionView = transitionOut.transitionView + let transitionViewImpl = transitionView?.makeView() + if let transitionViewImpl { + self.insertSubview(transitionViewImpl, aboveSubview: self.contentContainerView) + + let rightInfoSourceFrame = rightInfoView.convert(rightInfoView.bounds, to: self) + let positionKeyframes: [CGPoint] = generateParabollicMotionKeyframes(from: sourceLocalFrame.center, to: rightInfoSourceFrame.center, elevation: 0.0, duration: 0.3, curve: .spring, reverse: true) + + transitionViewImpl.frame = rightInfoSourceFrame + transitionViewImpl.alpha = 0.0 + transitionView?.updateView(transitionViewImpl, StoryContainerScreen.TransitionState( + sourceSize: rightInfoSourceFrame.size, + destinationSize: sourceLocalFrame.size, + progress: 0.0 + ), .immediate) + + let transition = Transition(animation: .curve(duration: 0.3, curve: .spring)) + + transitionViewImpl.alpha = 1.0 + transitionViewImpl.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + + rightInfoView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + + transition.setFrame(view: transitionViewImpl, frame: sourceLocalFrame) + + transitionViewImpl.layer.position = positionKeyframes[positionKeyframes.count - 1] + transitionViewImpl.layer.animateKeyframes(values: positionKeyframes.map { NSValue(cgPoint: $0) }, duration: 0.3, keyPath: "position", removeOnCompletion: false, additive: false) + transitionViewImpl.layer.animateBounds(from: CGRect(origin: CGPoint(), size: rightInfoSourceFrame.size), to: CGRect(origin: CGPoint(), size: sourceLocalFrame.size), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) + + transitionView?.updateView(transitionViewImpl, StoryContainerScreen.TransitionState( + sourceSize: rightInfoSourceFrame.size, + destinationSize: sourceLocalFrame.size, + progress: 1.0 + ), transition) + } + let positionKeyframes: [CGPoint] = generateParabollicMotionKeyframes(from: innerSourceLocalFrame.center, to: rightInfoView.layer.position, elevation: 0.0, duration: 0.3, curve: .spring, reverse: true) rightInfoView.layer.position = positionKeyframes[positionKeyframes.count - 1] rightInfoView.layer.animateKeyframes(values: positionKeyframes.map { NSValue(cgPoint: $0) }, duration: 0.3, keyPath: "position", removeOnCompletion: false, additive: false) @@ -715,33 +751,33 @@ public final class StoryItemSetContainerComponent: Component { removeOnCompletion: false ) - let transitionView = transitionOut.transitionView - let transitionViewImpl = transitionView?.makeView() - if let transitionViewImpl { - self.insertSubview(transitionViewImpl, belowSubview: self.contentContainerView) - - transitionViewImpl.frame = contentSourceFrame - transitionViewImpl.alpha = 0.0 - transitionView?.updateView(transitionViewImpl, StoryContainerScreen.TransitionState( - sourceSize: contentSourceFrame.size, - destinationSize: sourceLocalFrame.size, - progress: 0.0 - ), .immediate) - } - - if let transitionViewImpl { - let transition = Transition(animation: .curve(duration: 0.3, curve: .spring)) - - transitionViewImpl.alpha = 1.0 - transitionViewImpl.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) - self.contentContainerView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - - transition.setFrame(view: transitionViewImpl, frame: sourceLocalFrame) - transitionView?.updateView(transitionViewImpl, StoryContainerScreen.TransitionState( - sourceSize: contentSourceFrame.size, - destinationSize: sourceLocalFrame.size, - progress: 1.0 - ), transition) + if !transitionOut.destinationIsAvatar { + let transitionView = transitionOut.transitionView + let transitionViewImpl = transitionView?.makeView() + if let transitionViewImpl { + self.insertSubview(transitionViewImpl, belowSubview: self.contentContainerView) + + transitionViewImpl.frame = contentSourceFrame + transitionViewImpl.alpha = 0.0 + transitionView?.updateView(transitionViewImpl, StoryContainerScreen.TransitionState( + sourceSize: contentSourceFrame.size, + destinationSize: sourceLocalFrame.size, + progress: 0.0 + ), .immediate) + + let transition = Transition(animation: .curve(duration: 0.3, curve: .spring)) + + transitionViewImpl.alpha = 1.0 + transitionViewImpl.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + self.contentContainerView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + + transition.setFrame(view: transitionViewImpl, frame: sourceLocalFrame) + transitionView?.updateView(transitionViewImpl, StoryContainerScreen.TransitionState( + sourceSize: contentSourceFrame.size, + destinationSize: sourceLocalFrame.size, + progress: 1.0 + ), transition) + } } if let component = self.component, let visibleItemView = self.visibleItems[component.slice.item.id]?.view.view { diff --git a/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/BUILD b/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/BUILD index e9688ac1be..08439b34a2 100644 --- a/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/BUILD +++ b/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/BUILD @@ -14,10 +14,10 @@ swift_library( "//submodules/ComponentFlow", "//submodules/AppBundle", "//submodules/Components/BundleIconComponent", - "//submodules/TelegramUI/Components/ChatListHeaderComponent", "//submodules/AnimatedAvatarSetNode", "//submodules/AccountContext", "//submodules/TelegramCore", + "//submodules/TelegramUI/Components/MoreHeaderButton", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/Sources/StoryFooterPanelComponent.swift b/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/Sources/StoryFooterPanelComponent.swift index ebbf40a49d..7d9a7e1fa6 100644 --- a/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/Sources/StoryFooterPanelComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryFooterPanelComponent/Sources/StoryFooterPanelComponent.swift @@ -4,10 +4,10 @@ import Display import ComponentFlow import AppBundle import BundleIconComponent -import ChatListHeaderComponent import AnimatedAvatarSetNode import AccountContext import TelegramCore +import MoreHeaderButton public final class StoryFooterPanelComponent: Component { public let context: AccountContext diff --git a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/BUILD b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/BUILD index 5e5793b2d8..c192bd5d1d 100644 --- a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/BUILD +++ b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/BUILD @@ -20,6 +20,7 @@ swift_library( "//submodules/TelegramPresentationData", "//submodules/AvatarNode", "//submodules/ContextUI", + "//submodules/TelegramUI/Components/Stories/StoryContainerScreen", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift index 6c1f61890b..9573aa3168 100644 --- a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListComponent.swift @@ -6,8 +6,10 @@ import AppBundle import BundleIconComponent import AccountContext import TelegramCore +import Postbox import SwiftSignalKit import TelegramPresentationData +import StoryContainerScreen public final class StoryPeerListComponent: Component { public final class ExternalState { @@ -142,6 +144,9 @@ public final class StoryPeerListComponent: Component { private var requestedLoadMoreToken: String? private let loadMoreDisposable = MetaDisposable() + private var previewedItemDisposable: Disposable? + private var previewedItemId: EnginePeer.Id? + public override init(frame: CGRect) { self.collapsedButton = HighlightableButton() @@ -187,6 +192,7 @@ public final class StoryPeerListComponent: Component { deinit { self.loadMoreDisposable.dispose() + self.previewedItemDisposable?.dispose() } @objc private func collapsedButtonPressed() { @@ -196,12 +202,41 @@ public final class StoryPeerListComponent: Component { component.peerAction(nil) } - public func transitionViewForItem(peerId: EnginePeer.Id) -> UIView? { + public func setPreviewedItem(signal: Signal) { + self.previewedItemDisposable?.dispose() + self.previewedItemDisposable = (signal |> map(\.?.peerId) |> distinctUntilChanged |> deliverOnMainQueue).start(next: { [weak self] itemId in + guard let self else { + return + } + self.previewedItemId = itemId + + for (peerId, visibleItem) in self.visibleItems { + if let itemView = visibleItem.view.view as? StoryPeerListItemComponent.View { + itemView.updateIsPreviewing(isPreviewing: peerId == itemId) + } + } + }) + } + + public func transitionViewForItem(peerId: EnginePeer.Id) -> (UIView, StoryContainerScreen.TransitionView)? { if self.collapsedButton.isUserInteractionEnabled { return nil } if let visibleItem = self.visibleItems[peerId], let itemView = visibleItem.view.view as? StoryPeerListItemComponent.View { - return itemView.transitionView() + if !self.scrollView.bounds.intersects(itemView.frame) { + return nil + } + + return itemView.transitionView().flatMap { transitionView in + return (transitionView, StoryContainerScreen.TransitionView( + makeView: { [weak itemView] in + return StoryPeerListItemComponent.TransitionView(itemView: itemView) + }, + updateView: { view, state, transition in + (view as? StoryPeerListItemComponent.TransitionView)?.update(state: state, transition: transition) + } + )) + } } return nil } @@ -394,6 +429,8 @@ public final class StoryPeerListComponent: Component { itemTransition.setFrame(view: itemView.backgroundContainer, frame: itemFrame) itemTransition.setAlpha(view: itemView.backgroundContainer, alpha: itemAlpha) itemTransition.setScale(view: itemView.backgroundContainer, scale: itemScale) + + itemView.updateIsPreviewing(isPreviewing: self.previewedItemId == itemSet.peer.id) } } diff --git a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListItemComponent.swift b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListItemComponent.swift index d7f6fce759..863081c0ac 100644 --- a/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListItemComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryPeerListComponent/Sources/StoryPeerListItemComponent.swift @@ -11,6 +11,7 @@ import TelegramPresentationData import AvatarNode import ContextUI import AsyncDisplayKit +import StoryContainerScreen private func calculateCircleIntersection(center: CGPoint, otherCenter: CGPoint, radius: CGFloat) -> (point1Angle: CGFloat, point2Angle: CGFloat)? { let distanceVector = CGPoint(x: otherCenter.x - center.x, y: otherCenter.y - center.y) @@ -144,6 +145,47 @@ private final class StoryProgressLayer: SimpleShapeLayer { private var sharedAvatarBackgroundImage: UIImage? public final class StoryPeerListItemComponent: Component { + public final class TransitionView: UIView { + private weak var itemView: StoryPeerListItemComponent.View? + private var snapshotView: UIView? + private var portalView: PortalView? + + init(itemView: StoryPeerListItemComponent.View?) { + self.itemView = itemView + + super.init(frame: CGRect()) + + if let itemView { + if let portalView = PortalView(matchPosition: false) { + itemView.avatarContent.addPortal(view: portalView) + self.portalView = portalView + self.addSubview(portalView.view) + } + /*if let snapshotView = itemView.avatarContent.snapshotView(afterScreenUpdates: false) { + self.addSubview(snapshotView) + self.snapshotView = snapshotView + }*/ + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(state: StoryContainerScreen.TransitionState, transition: Transition) { + let size = state.sourceSize.interpolate(to: state.destinationSize, amount: state.progress) + + if let snapshotView = self.snapshotView { + transition.setPosition(view: snapshotView, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5)) + transition.setScale(view: snapshotView, scale: size.width / state.destinationSize.width) + } + if let portalView = self.portalView { + transition.setPosition(view: portalView.view, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5)) + transition.setScale(view: portalView.view, scale: size.width / state.destinationSize.width) + } + } + } + public let context: AccountContext public let theme: PresentationTheme public let strings: PresentationStrings @@ -240,6 +282,7 @@ public final class StoryPeerListItemComponent: Component { private let button: HighlightTrackingButton + fileprivate let avatarContent: PortalSourceView private let avatarContainer: UIView private let avatarBackgroundContainer: UIView private let avatarBackgroundView: UIImageView @@ -266,6 +309,9 @@ public final class StoryPeerListItemComponent: Component { self.extractedBackgroundView = UIImageView() self.extractedBackgroundView.alpha = 0.0 + self.avatarContent = PortalSourceView() + self.avatarContent.isUserInteractionEnabled = false + self.avatarContainer = UIView() self.avatarContainer.isUserInteractionEnabled = false @@ -294,9 +340,10 @@ public final class StoryPeerListItemComponent: Component { self.avatarBackgroundContainer.addSubview(self.avatarBackgroundView) self.extractedContainerNode.contentNode.view.addSubview(self.button) - self.button.addSubview(self.avatarContainer) + self.avatarContent.addSubview(self.avatarContainer) + self.button.addSubview(self.avatarContent) - self.button.layer.addSublayer(self.indicatorColorLayer) + self.avatarContent.layer.addSublayer(self.indicatorColorLayer) self.indicatorMaskLayer.addSublayer(self.indicatorShapeLayer) self.indicatorColorLayer.mask = self.indicatorMaskLayer @@ -366,6 +413,10 @@ public final class StoryPeerListItemComponent: Component { return self.avatarNode?.view } + func updateIsPreviewing(isPreviewing: Bool) { + self.avatarContent.alpha = isPreviewing ? 0.0 : 1.0 + } + func update(component: StoryPeerListItemComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { let size = availableSize @@ -439,7 +490,11 @@ public final class StoryPeerListItemComponent: Component { peer: component.peer ) avatarNode.updateSize(size: avatarSize) - transition.setPosition(view: self.avatarContainer, position: avatarFrame.center) + + transition.setPosition(view: self.avatarContent, position: CGPoint(x: avatarFrame.midX, y: avatarFrame.midY)) + transition.setBounds(view: self.avatarContent, bounds: CGRect(origin: CGPoint(), size: avatarFrame.size)) + + transition.setPosition(view: self.avatarContainer, position: CGPoint(x: avatarFrame.width * 0.5, y: avatarFrame.height * 0.5)) transition.setBounds(view: self.avatarContainer, bounds: CGRect(origin: CGPoint(), size: avatarFrame.size)) transition.setPosition(view: self.avatarBackgroundContainer, position: avatarFrame.center) @@ -517,7 +572,7 @@ public final class StoryPeerListItemComponent: Component { self.indicatorColorLayer.colors = colors } - transition.setPosition(layer: self.indicatorColorLayer, position: indicatorFrame.center) + transition.setPosition(layer: self.indicatorColorLayer, position: indicatorFrame.offsetBy(dx: -avatarFrame.minX, dy: -avatarFrame.minY).center) transition.setBounds(layer: self.indicatorColorLayer, bounds: CGRect(origin: CGPoint(), size: indicatorFrame.size)) transition.setPosition(layer: self.indicatorShapeLayer, position: CGPoint(x: indicatorFrame.width * 0.5, y: indicatorFrame.height * 0.5)) transition.setBounds(layer: self.indicatorShapeLayer, bounds: CGRect(origin: CGPoint(), size: indicatorFrame.size)) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index db4a381efb..71c75df56b 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -96,6 +96,7 @@ import LegacyCamera import LegacyInstantVideoController import StoryContainerScreen import StoryContentComponent +import MoreHeaderButton #if DEBUG import os.signpost