mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
[WIP] Stories
This commit is contained in:
@@ -132,6 +132,8 @@ public final class ChatListHeaderComponent: Component {
|
||||
public let secondaryContent: Content?
|
||||
public let secondaryTransition: CGFloat
|
||||
public let networkStatus: HeaderNetworkStatusComponent.Content?
|
||||
public let storySubscriptions: EngineStorySubscriptions?
|
||||
public let storiesFraction: CGFloat
|
||||
public let context: AccountContext
|
||||
public let theme: PresentationTheme
|
||||
public let strings: PresentationStrings
|
||||
@@ -145,6 +147,8 @@ public final class ChatListHeaderComponent: Component {
|
||||
secondaryContent: Content?,
|
||||
secondaryTransition: CGFloat,
|
||||
networkStatus: HeaderNetworkStatusComponent.Content?,
|
||||
storySubscriptions: EngineStorySubscriptions?,
|
||||
storiesFraction: CGFloat,
|
||||
context: AccountContext,
|
||||
theme: PresentationTheme,
|
||||
strings: PresentationStrings,
|
||||
@@ -157,6 +161,8 @@ public final class ChatListHeaderComponent: Component {
|
||||
self.secondaryTransition = secondaryTransition
|
||||
self.context = context
|
||||
self.networkStatus = networkStatus
|
||||
self.storySubscriptions = storySubscriptions
|
||||
self.storiesFraction = storiesFraction
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.openStatusSetup = openStatusSetup
|
||||
@@ -179,6 +185,12 @@ public final class ChatListHeaderComponent: Component {
|
||||
if lhs.networkStatus != rhs.networkStatus {
|
||||
return false
|
||||
}
|
||||
if lhs.storySubscriptions != rhs.storySubscriptions {
|
||||
return false
|
||||
}
|
||||
if lhs.storiesFraction != rhs.storiesFraction {
|
||||
return false
|
||||
}
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
@@ -280,6 +292,7 @@ public final class ChatListHeaderComponent: Component {
|
||||
var chatListTitleView: ChatListTitleView?
|
||||
|
||||
var contentOffsetFraction: CGFloat = 0.0
|
||||
private(set) var centerContentWidth: CGFloat = 0.0
|
||||
|
||||
init(
|
||||
backPressed: @escaping () -> Void,
|
||||
@@ -342,15 +355,11 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
self.contentOffsetFraction = contentOffsetFraction
|
||||
|
||||
let scale = 1.0 * (1.0 - contentOffsetFraction) + 0.001 * contentOffsetFraction
|
||||
let translation = -44.0 * contentOffsetFraction * 0.5
|
||||
let translation = 44.0 * contentOffsetFraction * 0.5
|
||||
|
||||
var transform = CATransform3DIdentity
|
||||
transform = CATransform3DTranslate(transform, 0.0, translation, 0.0)
|
||||
transform = CATransform3DTranslate(transform, translation, 0.0, 0.0)
|
||||
transition.setSublayerTransform(view: self.titleOffsetContainer, transform: transform)
|
||||
|
||||
transition.setScale(view: self.titleScaleContainer, scale: scale)
|
||||
transition.setAlpha(view: self.titleScaleContainer, alpha: 1.0 - contentOffsetFraction)
|
||||
}
|
||||
|
||||
func updateNavigationTransitionAsPrevious(nextView: ContentView, fraction: CGFloat, transition: Transition, completion: @escaping () -> Void) {
|
||||
@@ -431,7 +440,7 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
func update(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, content: Content, backTitle: String?, sideInset: CGFloat, size: CGSize, transition: Transition) {
|
||||
func update(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, content: Content, backTitle: String?, sideInset: CGFloat, sideContentWidth: CGFloat, size: CGSize, transition: Transition) {
|
||||
transition.setPosition(view: self.titleOffsetContainer, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5))
|
||||
transition.setBounds(view: self.titleOffsetContainer, bounds: CGRect(origin: self.titleOffsetContainer.bounds.origin, size: size))
|
||||
|
||||
@@ -573,7 +582,8 @@ public final class ChatListHeaderComponent: Component {
|
||||
let remainingWidth = size.width - commonInset * 2.0
|
||||
|
||||
let titleTextSize = self.titleTextView.updateLayout(CGSize(width: remainingWidth, height: size.height))
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleTextSize.width) / 2.0), y: floor((size.height - titleTextSize.height) / 2.0)), size: titleTextSize)
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleTextSize.width) / 2.0) + sideContentWidth, y: floor((size.height - titleTextSize.height) / 2.0)), size: titleTextSize)
|
||||
transition.setFrame(view: self.titleTextView, frame: titleFrame)
|
||||
|
||||
if let titleComponent = content.titleComponent {
|
||||
@@ -592,6 +602,7 @@ public final class ChatListHeaderComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: remainingWidth, height: size.height)
|
||||
)
|
||||
|
||||
if let titleContentComponentView = titleContentView.view {
|
||||
if titleContentComponentView.superview == nil {
|
||||
self.titleScaleContainer.addSubview(titleContentComponentView)
|
||||
@@ -622,7 +633,8 @@ public final class ChatListHeaderComponent: Component {
|
||||
chatListTitleView.theme = theme
|
||||
chatListTitleView.strings = strings
|
||||
chatListTitleView.setTitle(chatListTitle, animated: false)
|
||||
chatListTitleView.updateLayout(size: chatListTitleContentSize, clearBounds: CGRect(origin: CGPoint(), size: chatListTitleContentSize), transition: transition.containedViewLayoutTransition)
|
||||
let centerContentWidth = chatListTitleView.updateLayout(size: chatListTitleContentSize, clearBounds: CGRect(origin: CGPoint(), size: chatListTitleContentSize), sideContentWidth: sideContentWidth, transition: transition.containedViewLayoutTransition)
|
||||
self.centerContentWidth = centerContentWidth
|
||||
|
||||
chatListTitleView.openStatusSetup = { [weak self] sourceView in
|
||||
guard let self else {
|
||||
@@ -657,6 +669,7 @@ public final class ChatListHeaderComponent: Component {
|
||||
private var secondaryContentView: ContentView?
|
||||
private var storyOffsetFraction: CGFloat = 0.0
|
||||
|
||||
private let storyPeerListExternalState = StoryPeerListComponent.ExternalState()
|
||||
private var storyPeerList: ComponentView<Empty>?
|
||||
public var storyPeerAction: ((EnginePeer?) -> Void)?
|
||||
|
||||
@@ -718,6 +731,12 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if let storyPeerListView = self.storyPeerList?.view {
|
||||
if let result = storyPeerListView.hitTest(self.convert(point, to: storyPeerListView), with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
for subview in self.subviews.reversed() {
|
||||
if !subview.isUserInteractionEnabled || subview.alpha < 0.01 || subview.isHidden {
|
||||
continue
|
||||
@@ -730,12 +749,6 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if let storyPeerListView = self.storyPeerList?.view {
|
||||
if let result = storyPeerListView.hitTest(self.convert(point, to: storyPeerListView), with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
let defaultResult = super.hitTest(point, with: event)
|
||||
|
||||
if let defaultResult, defaultResult !== self {
|
||||
@@ -745,33 +758,46 @@ public final class ChatListHeaderComponent: Component {
|
||||
return defaultResult
|
||||
}
|
||||
|
||||
public func updateStories(offset: CGFloat, context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, storySubscriptions: EngineStorySubscriptions?, transition: Transition) {
|
||||
var storyOffsetFraction: CGFloat = 1.0
|
||||
if let storySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
storyOffsetFraction = offset
|
||||
}
|
||||
/*public func updateStories(offset: CGFloat, context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, storySubscriptions: EngineStorySubscriptions?, transition: Transition) {
|
||||
|
||||
self.storyOffsetFraction = storyOffsetFraction
|
||||
}*/
|
||||
|
||||
private func updateContentStoryOffsets(transition: Transition) {
|
||||
}
|
||||
|
||||
func update(component: ChatListHeaderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||
self.state = state
|
||||
|
||||
let previousComponent = self.component
|
||||
self.component = component
|
||||
|
||||
let storyPeerList: ComponentView<Empty>
|
||||
var storyListTransition = transition
|
||||
if let current = self.storyPeerList {
|
||||
storyPeerList = current
|
||||
} else {
|
||||
storyListTransition = .immediate
|
||||
storyPeerList = ComponentView()
|
||||
self.storyPeerList = storyPeerList
|
||||
}
|
||||
|
||||
if !self.bounds.isEmpty {
|
||||
if let storySubscriptions = component.storySubscriptions {
|
||||
var storyOffsetFraction: CGFloat = 1.0
|
||||
storyOffsetFraction = component.storiesFraction
|
||||
let _ = storyOffsetFraction
|
||||
|
||||
//self.storyOffsetFraction = storyOffsetFraction
|
||||
|
||||
let storyPeerList: ComponentView<Empty>
|
||||
if let current = self.storyPeerList {
|
||||
storyPeerList = current
|
||||
} else {
|
||||
storyListTransition = .immediate
|
||||
storyPeerList = ComponentView()
|
||||
self.storyPeerList = storyPeerList
|
||||
}
|
||||
|
||||
let _ = storyPeerList.update(
|
||||
transition: storyListTransition,
|
||||
component: AnyComponent(StoryPeerListComponent(
|
||||
context: context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
externalState: self.storyPeerListExternalState,
|
||||
context: component.context,
|
||||
theme: component.theme,
|
||||
strings: component.strings,
|
||||
storySubscriptions: storySubscriptions,
|
||||
collapseFraction: 1.0 - offset,
|
||||
collapseFraction: 1.0 - component.storiesFraction,
|
||||
peerAction: { [weak self] peer in
|
||||
guard let self else {
|
||||
return
|
||||
@@ -782,43 +808,7 @@ public final class ChatListHeaderComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: self.bounds.width, height: 94.0)
|
||||
)
|
||||
if let storyPeerListComponentView = storyPeerList.view {
|
||||
if storyPeerListComponentView.superview == nil {
|
||||
self.addSubview(storyPeerListComponentView)
|
||||
}
|
||||
|
||||
let storyPeerListMinOffset: CGFloat = -7.0
|
||||
let storyPeerListMaxOffset: CGFloat = self.bounds.height + 8.0
|
||||
|
||||
let storyPeerListPosition: CGFloat = storyPeerListMinOffset * (1.0 - offset) + storyPeerListMaxOffset * offset
|
||||
|
||||
storyListTransition.setFrame(view: storyPeerListComponentView, frame: CGRect(origin: CGPoint(x: 0.0, y: storyPeerListPosition), size: CGSize(width: self.bounds.width, height: 94.0)))
|
||||
|
||||
var storyListAlpha: CGFloat = 1.0
|
||||
if let storySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
} else {
|
||||
storyListAlpha = offset
|
||||
}
|
||||
storyListTransition.setAlpha(view: storyPeerListComponentView, alpha: storyListAlpha)
|
||||
}
|
||||
|
||||
if let primaryContentView = self.primaryContentView {
|
||||
primaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: transition)
|
||||
}
|
||||
if let secondaryContentView = self.secondaryContentView {
|
||||
secondaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func updateContentStoryOffsets(transition: Transition) {
|
||||
}
|
||||
|
||||
func update(component: ChatListHeaderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||
self.state = state
|
||||
|
||||
let previousComponent = self.component
|
||||
self.component = component
|
||||
|
||||
if let primaryContent = component.primaryContent {
|
||||
var primaryContentTransition = transition
|
||||
@@ -850,7 +840,18 @@ public final class ChatListHeaderComponent: Component {
|
||||
self.primaryContentView = primaryContentView
|
||||
self.addSubview(primaryContentView)
|
||||
}
|
||||
primaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: primaryContent, backTitle: primaryContent.backTitle, sideInset: component.sideInset, size: availableSize, transition: primaryContentTransition)
|
||||
|
||||
var sideContentWidth: CGFloat = 0.0
|
||||
if let storySubscriptions = component.storySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
sideContentWidth = self.storyPeerListExternalState.collapsedWidth + 8.0
|
||||
}
|
||||
if let chatListTitle = primaryContent.chatListTitle {
|
||||
if chatListTitle.activity {
|
||||
sideContentWidth = 0.0
|
||||
}
|
||||
}
|
||||
|
||||
primaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: primaryContent, backTitle: primaryContent.backTitle, sideInset: component.sideInset, sideContentWidth: sideContentWidth * (1.0 - component.storiesFraction), size: availableSize, transition: primaryContentTransition)
|
||||
primaryContentTransition.setFrame(view: primaryContentView, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
|
||||
primaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: primaryContentTransition)
|
||||
@@ -889,7 +890,7 @@ public final class ChatListHeaderComponent: Component {
|
||||
self.secondaryContentView = secondaryContentView
|
||||
self.addSubview(secondaryContentView)
|
||||
}
|
||||
secondaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: secondaryContent, backTitle: component.primaryContent?.navigationBackTitle ?? component.primaryContent?.title, sideInset: component.sideInset, size: availableSize, transition: secondaryContentTransition)
|
||||
secondaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: secondaryContent, backTitle: component.primaryContent?.navigationBackTitle ?? component.primaryContent?.title, sideInset: component.sideInset, sideContentWidth: 0.0, size: availableSize, transition: secondaryContentTransition)
|
||||
secondaryContentTransition.setFrame(view: secondaryContentView, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
|
||||
secondaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: secondaryContentTransition)
|
||||
@@ -933,6 +934,34 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if let storyPeerList = self.storyPeerList, let storyPeerListComponentView = storyPeerList.view {
|
||||
if storyPeerListComponentView.superview == nil {
|
||||
self.addSubview(storyPeerListComponentView)
|
||||
}
|
||||
|
||||
let storyPeerListMinOffset: CGFloat = -7.0
|
||||
let storyPeerListMaxOffset: CGFloat = availableSize.height + 8.0
|
||||
|
||||
let storyPeerListPosition: CGFloat = storyPeerListMinOffset * (1.0 - component.storiesFraction) + storyPeerListMaxOffset * component.storiesFraction
|
||||
|
||||
var defaultStoryListX: CGFloat = 0.0
|
||||
if let primaryContentView = self.primaryContentView {
|
||||
defaultStoryListX = floor((self.storyPeerListExternalState.collapsedWidth - primaryContentView.centerContentWidth) * 0.5)
|
||||
}
|
||||
|
||||
storyListTransition.setFrame(view: storyPeerListComponentView, frame: CGRect(origin: CGPoint(x: -1.0 * availableSize.width * component.secondaryTransition + (1.0 - component.storiesFraction) * defaultStoryListX, y: storyPeerListPosition), size: CGSize(width: availableSize.width, height: 94.0)))
|
||||
|
||||
var storyListNormalAlpha: CGFloat = 1.0
|
||||
if let chatListTitle = component.primaryContent?.chatListTitle {
|
||||
if chatListTitle.activity {
|
||||
storyListNormalAlpha = component.storiesFraction
|
||||
}
|
||||
}
|
||||
|
||||
let storyListAlpha: CGFloat = (1.0 - component.secondaryTransition) * storyListNormalAlpha
|
||||
storyListTransition.setAlpha(view: storyPeerListComponentView, alpha: storyListAlpha)
|
||||
}
|
||||
|
||||
return availableSize
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user