mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Stories
This commit is contained in:
parent
f3c0a20a61
commit
a7ab23f97a
@ -19,6 +19,7 @@ import ComponentDisplayAdapters
|
||||
import ComponentFlow
|
||||
import ChatFolderLinkPreviewScreen
|
||||
import ChatListHeaderComponent
|
||||
import StoryPeerListComponent
|
||||
|
||||
public enum ChatListContainerNodeFilter: Equatable {
|
||||
case all
|
||||
@ -927,7 +928,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
if itemNode.listNode.isTracking && !self.currentItemNode.startedScrollingAtUpperBound && self.tempTopInset == 0.0 {
|
||||
if case let .known(value) = offset {
|
||||
if value < -1.0 {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
self.currentItemNode.startedScrollingAtUpperBound = true
|
||||
self.tempTopInset = ChatListNavigationBar.storiesScrollHeight
|
||||
}
|
||||
@ -958,7 +959,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
||||
}
|
||||
let tempTopInset: CGFloat
|
||||
if self.currentItemNode.startedScrollingAtUpperBound {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
tempTopInset = ChatListNavigationBar.storiesScrollHeight
|
||||
} else {
|
||||
tempTopInset = 0.0
|
||||
@ -1799,7 +1800,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
return false
|
||||
}
|
||||
|
||||
if let storySubscriptions = controller.orderedStorySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
if let storySubscriptions = controller.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
if let navigationBarComponentView = self.navigationBarView.view as? ChatListNavigationBar.View {
|
||||
if navigationBarComponentView.storiesUnlocked {
|
||||
return true
|
||||
@ -2060,7 +2061,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
if let storySubscriptions = self.controller?.orderedStorySubscriptions, (shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) || true) {
|
||||
self.tempAllowAvatarExpansion = true
|
||||
self.tempDisableStoriesAnimations = !animated
|
||||
self.tempNavigationScrollingTransition = animated ? .animated(duration: 0.3, curve: .spring) : .immediate
|
||||
|
@ -1162,11 +1162,17 @@ public class Account {
|
||||
let extractedExpr: [Signal<AccountRunningImportantTasks, NoError>] = [
|
||||
managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] },
|
||||
self.pendingMessageManager.hasPendingMessages |> map { !$0.isEmpty ? AccountRunningImportantTasks.pendingMessages : [] },
|
||||
(self.pendingStoryManager?.hasPending ?? .single(false)) |> map { hasPending in hasPending ? AccountRunningImportantTasks.pendingMessages : [] },
|
||||
self.pendingUpdateMessageManager.updatingMessageMedia |> map { !$0.isEmpty ? AccountRunningImportantTasks.pendingMessages : [] },
|
||||
self.pendingPeerMediaUploadManager.uploadingPeerMedia |> map { !$0.isEmpty ? AccountRunningImportantTasks.pendingMessages : [] },
|
||||
(self.pendingStoryManager?.hasPending ?? .single(false)) |> map {
|
||||
hasPending in hasPending ? AccountRunningImportantTasks.pendingMessages : []
|
||||
},
|
||||
self.pendingUpdateMessageManager.updatingMessageMedia |> map {
|
||||
!$0.isEmpty ? AccountRunningImportantTasks.pendingMessages : []
|
||||
},
|
||||
self.pendingPeerMediaUploadManager.uploadingPeerMedia |> map {
|
||||
!$0.isEmpty ? AccountRunningImportantTasks.pendingMessages : []
|
||||
},
|
||||
self.accountPresenceManager.isPerformingUpdate() |> map { $0 ? AccountRunningImportantTasks.other : [] },
|
||||
self.notificationAutolockReportManager.isPerformingUpdate() |> map { $0 ? AccountRunningImportantTasks.other : [] }
|
||||
//self.notificationAutolockReportManager.isPerformingUpdate() |> map { $0 ? AccountRunningImportantTasks.other : [] }
|
||||
]
|
||||
let importantBackgroundOperations: [Signal<AccountRunningImportantTasks, NoError>] = extractedExpr
|
||||
let importantBackgroundOperationsRunning = combineLatest(queue: Queue(), importantBackgroundOperations)
|
||||
|
@ -475,6 +475,7 @@ public final class EngineStorySubscriptions: Equatable {
|
||||
public let peer: EnginePeer
|
||||
public let hasUnseen: Bool
|
||||
public let hasUnseenCloseFriends: Bool
|
||||
public let hasPending: Bool
|
||||
public let storyCount: Int
|
||||
public let unseenCount: Int
|
||||
public let lastTimestamp: Int32
|
||||
@ -483,6 +484,7 @@ public final class EngineStorySubscriptions: Equatable {
|
||||
peer: EnginePeer,
|
||||
hasUnseen: Bool,
|
||||
hasUnseenCloseFriends: Bool,
|
||||
hasPending: Bool,
|
||||
storyCount: Int,
|
||||
unseenCount: Int,
|
||||
lastTimestamp: Int32
|
||||
@ -490,6 +492,7 @@ public final class EngineStorySubscriptions: Equatable {
|
||||
self.peer = peer
|
||||
self.hasUnseen = hasUnseen
|
||||
self.hasUnseenCloseFriends = hasUnseenCloseFriends
|
||||
self.hasPending = hasPending
|
||||
self.storyCount = storyCount
|
||||
self.unseenCount = unseenCount
|
||||
self.lastTimestamp = lastTimestamp
|
||||
|
@ -645,6 +645,7 @@ public extension TelegramEngine {
|
||||
|
||||
additionalDataKeys.append(PostboxViewKey.storyItems(peerId: self.account.peerId))
|
||||
additionalDataKeys.append(PostboxViewKey.storiesState(key: .peer(self.account.peerId)))
|
||||
additionalDataKeys.append(PostboxViewKey.storiesState(key: .local))
|
||||
|
||||
var subscriptionPeerIds = storySubscriptionsView.peerIds.filter { $0 != self.account.peerId }
|
||||
if !debugTimer {
|
||||
@ -680,6 +681,7 @@ public extension TelegramEngine {
|
||||
peer: EnginePeer(accountPeer),
|
||||
hasUnseen: false,
|
||||
hasUnseenCloseFriends: false,
|
||||
hasPending: false,
|
||||
storyCount: 0,
|
||||
unseenCount: 0,
|
||||
lastTimestamp: 0
|
||||
@ -696,14 +698,17 @@ public extension TelegramEngine {
|
||||
var hasUnseen = false
|
||||
var hasUnseenCloseFriends = false
|
||||
var unseenCount = 0
|
||||
var hasPending = false
|
||||
if let peerState = peerState {
|
||||
hasUnseen = peerState.maxReadId < lastEntry.id
|
||||
|
||||
for item in itemsView.items {
|
||||
if item.id > peerState.maxReadId {
|
||||
unseenCount += 1
|
||||
|
||||
if case let .item(item) = item.value.get(Stories.StoredItem.self) {
|
||||
}
|
||||
|
||||
if case let .item(item) = item.value.get(Stories.StoredItem.self) {
|
||||
if item.id > peerState.maxReadId {
|
||||
if item.isCloseFriends {
|
||||
hasUnseenCloseFriends = true
|
||||
}
|
||||
@ -712,10 +717,17 @@ public extension TelegramEngine {
|
||||
}
|
||||
}
|
||||
|
||||
if let view = views.views[PostboxViewKey.storiesState(key: .local)] as? StoryStatesView, let localState = view.value?.get(Stories.LocalState.self) {
|
||||
if !localState.items.isEmpty {
|
||||
hasPending = true
|
||||
}
|
||||
}
|
||||
|
||||
let item = EngineStorySubscriptions.Item(
|
||||
peer: EnginePeer(accountPeer),
|
||||
hasUnseen: hasUnseen,
|
||||
hasUnseenCloseFriends: hasUnseenCloseFriends,
|
||||
hasPending: hasPending,
|
||||
storyCount: itemsView.items.count,
|
||||
unseenCount: unseenCount,
|
||||
lastTimestamp: lastEntry.timestamp
|
||||
@ -766,6 +778,7 @@ public extension TelegramEngine {
|
||||
peer: EnginePeer(peer),
|
||||
hasUnseen: hasUnseen,
|
||||
hasUnseenCloseFriends: hasUnseenCloseFriends,
|
||||
hasPending: false,
|
||||
storyCount: itemsView.items.count,
|
||||
unseenCount: unseenCount,
|
||||
lastTimestamp: lastEntry.timestamp
|
||||
|
@ -847,14 +847,6 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
|
||||
let sideContentWidth: CGFloat = 0.0
|
||||
/*if let storySubscriptions = component.storySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
sideContentWidth = self.storyPeerListExternalState.collapsedWidth + 12.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, sideContentFraction: (1.0 - component.storiesFraction), size: availableSize, transition: primaryContentTransition)
|
||||
primaryContentTransition.setFrame(view: primaryContentView, frame: CGRect(origin: CGPoint(), size: availableSize))
|
||||
|
@ -610,44 +610,6 @@ public final class ChatListNavigationBar: Component {
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
/*private func addStoriesUnlockedAnimation(duration: Double, animateScrollUnlocked: Bool) {
|
||||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
self.applyScrollFractionAnimator?.invalidate()
|
||||
self.applyScrollFractionAnimator = nil
|
||||
|
||||
let storiesUnlocked = component.storiesUnlocked
|
||||
|
||||
self.storiesOffsetStartFraction = self.storiesOffsetFraction
|
||||
self.storiesUnlockedStartFraction = self.storiesUnlockedFraction
|
||||
|
||||
self.applyScrollFraction = 0.0
|
||||
self.applyScrollUnlockedFraction = 0.0
|
||||
self.applyScrollFractionAnimator = DisplayLinkAnimator(duration: duration * UIView.animationDurationFactor(), from: 0.0, to: 1.0, update: { [weak self] value in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let t = listViewAnimationCurveSystem(value)
|
||||
self.applyScrollFraction = t
|
||||
if animateScrollUnlocked {
|
||||
self.applyScrollUnlockedFraction = storiesUnlocked ? t : (1.0 - t)
|
||||
}
|
||||
|
||||
if let rawScrollOffset = self.rawScrollOffset {
|
||||
self.hasDeferredScrollOffset = true
|
||||
self.applyScroll(offset: rawScrollOffset, allowAvatarsExpansion: self.currentAllowAvatarsExpansion, transition: .immediate)
|
||||
}
|
||||
}, completion: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.applyScrollFractionAnimator?.invalidate()
|
||||
self.applyScrollFractionAnimator = nil
|
||||
})
|
||||
}*/
|
||||
}
|
||||
|
||||
public func makeView() -> View {
|
||||
|
@ -5,6 +5,7 @@ import ComponentFlow
|
||||
import SwiftSignalKit
|
||||
import TelegramCore
|
||||
import Postbox
|
||||
import TelegramPresentationData
|
||||
|
||||
public final class StoryContentItem {
|
||||
public final class ExternalState {
|
||||
@ -33,17 +34,20 @@ public final class StoryContentItem {
|
||||
public final class Environment: Equatable {
|
||||
public let externalState: ExternalState
|
||||
public let sharedState: SharedState
|
||||
public let theme: PresentationTheme
|
||||
public let presentationProgressUpdated: (Double, Bool) -> Void
|
||||
public let markAsSeen: (StoryId) -> Void
|
||||
|
||||
public init(
|
||||
externalState: ExternalState,
|
||||
sharedState: SharedState,
|
||||
theme: PresentationTheme,
|
||||
presentationProgressUpdated: @escaping (Double, Bool) -> Void,
|
||||
markAsSeen: @escaping (StoryId) -> Void
|
||||
) {
|
||||
self.externalState = externalState
|
||||
self.sharedState = sharedState
|
||||
self.theme = theme
|
||||
self.presentationProgressUpdated = presentationProgressUpdated
|
||||
self.markAsSeen = markAsSeen
|
||||
}
|
||||
@ -55,6 +59,9 @@ public final class StoryContentItem {
|
||||
if lhs.sharedState !== rhs.sharedState {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -621,6 +621,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
let itemEnvironment = StoryContentItem.Environment(
|
||||
externalState: visibleItem.externalState,
|
||||
sharedState: component.storyItemSharedState,
|
||||
theme: component.theme,
|
||||
presentationProgressUpdated: { [weak self, weak visibleItem] progress, canSwitch in
|
||||
guard let self = self, let component = self.component else {
|
||||
return
|
||||
@ -656,7 +657,6 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
)
|
||||
if let view = visibleItem.view.view {
|
||||
if view.superview == nil {
|
||||
view.isUserInteractionEnabled = false
|
||||
self.contentContainerView.insertSubview(view, at: 0)
|
||||
}
|
||||
itemTransition.setFrame(view: view, frame: CGRect(origin: CGPoint(), size: itemLayout.size))
|
||||
@ -1139,6 +1139,15 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isUnsupported = false
|
||||
var disabledPlaceholder: String?
|
||||
if component.slice.peer.isService {
|
||||
disabledPlaceholder = "You can't reply to this story"
|
||||
} else if case .unsupported = component.slice.item.storyItem.media {
|
||||
isUnsupported = true
|
||||
disabledPlaceholder = "You can't reply to this story"
|
||||
}
|
||||
|
||||
let keyboardWasHidden = self.inputPanelExternalState.isKeyboardHidden
|
||||
let inputNodeVisible = self.sendMessageContext.currentInputMode == .media || hasFirstResponder(self)
|
||||
@ -1374,7 +1383,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
displayGradient: false, //(component.inputHeight != 0.0 || inputNodeVisible) && component.metrics.widthClass != .regular,
|
||||
bottomInset: component.inputHeight != 0.0 || inputNodeVisible ? 0.0 : bottomContentInset,
|
||||
hideKeyboard: self.sendMessageContext.currentInputMode == .media,
|
||||
disabledPlaceholder: component.slice.peer.isService ? "You can't reply to this story" : nil
|
||||
disabledPlaceholder: disabledPlaceholder
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: inputPanelAvailableWidth, height: 200.0)
|
||||
@ -1976,7 +1985,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if !component.slice.item.storyItem.text.isEmpty {
|
||||
if !isUnsupported, !component.slice.item.storyItem.text.isEmpty {
|
||||
var captionItemTransition = transition
|
||||
let captionItem: CaptionItem
|
||||
if let current = self.captionItem {
|
||||
|
@ -23,6 +23,9 @@ swift_library(
|
||||
"//submodules/TelegramUniversalVideoContent",
|
||||
"//submodules/AvatarNode",
|
||||
"//submodules/Components/HierarchyTrackingLayer",
|
||||
"//submodules/TelegramUI/Components/ButtonComponent",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/TelegramPresentationData",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -437,6 +437,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
peer: peer,
|
||||
hasUnseen: state.hasUnseen,
|
||||
hasUnseenCloseFriends: state.hasUnseenCloseFriends,
|
||||
hasPending: false,
|
||||
storyCount: state.items.count,
|
||||
unseenCount: 0,
|
||||
lastTimestamp: state.items.last?.timestamp ?? 0
|
||||
|
@ -12,6 +12,9 @@ import UniversalMediaPlayer
|
||||
import TelegramUniversalVideoContent
|
||||
import StoryContainerScreen
|
||||
import HierarchyTrackingLayer
|
||||
import ButtonComponent
|
||||
import MultilineTextComponent
|
||||
import TelegramPresentationData
|
||||
|
||||
final class StoryItemContentComponent: Component {
|
||||
typealias EnvironmentType = StoryContentItem.Environment
|
||||
@ -38,56 +41,6 @@ final class StoryItemContentComponent: Component {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/*static func preload(context: AccountContext, message: EngineMessage) -> Signal<Never, NoError> {
|
||||
var messageMedia: EngineMedia?
|
||||
for media in message.media {
|
||||
switch media {
|
||||
case let image as TelegramMediaImage:
|
||||
messageMedia = .image(image)
|
||||
case let file as TelegramMediaFile:
|
||||
messageMedia = .file(file)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
guard let messageMedia else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var fetchSignal: Signal<Never, NoError>?
|
||||
switch messageMedia {
|
||||
case let .image(image):
|
||||
if let representation = image.representations.last {
|
||||
fetchSignal = fetchedMediaResource(
|
||||
mediaBox: context.account.postbox.mediaBox,
|
||||
userLocation: .peer(message.id.peerId),
|
||||
userContentType: .image,
|
||||
reference: ImageMediaReference.message(message: MessageReference(message._asMessage()), media: image).resourceReference(representation.resource)
|
||||
)
|
||||
|> ignoreValues
|
||||
|> `catch` { _ -> Signal<Never, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
case let .file(file):
|
||||
fetchSignal = fetchedMediaResource(
|
||||
mediaBox: context.account.postbox.mediaBox,
|
||||
userLocation: .peer(message.id.peerId),
|
||||
userContentType: .image,
|
||||
reference: FileMediaReference.message(message: MessageReference(message._asMessage()), media: file).resourceReference(file.resource)
|
||||
)
|
||||
|> ignoreValues
|
||||
|> `catch` { _ -> Signal<Never, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return fetchSignal ?? .complete()
|
||||
}*/
|
||||
|
||||
final class View: StoryContentItem.View {
|
||||
private let imageNode: TransformImageNode
|
||||
@ -100,6 +53,9 @@ final class StoryItemContentComponent: Component {
|
||||
private weak var state: EmptyComponentState?
|
||||
private var environment: StoryContentItem.Environment?
|
||||
|
||||
private var unsupportedText: ComponentView<Empty>?
|
||||
private var unsupportedButton: ComponentView<Empty>?
|
||||
|
||||
private var isProgressPaused: Bool = false
|
||||
private var currentProgressTimer: SwiftSignalKit.Timer?
|
||||
private var currentProgressTimerValue: Double = 0.0
|
||||
@ -353,10 +309,20 @@ final class StoryItemContentComponent: Component {
|
||||
self.environment?.presentationProgressUpdated(clippedProgress, false)
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if let unsupportedButtonView = self.unsupportedButton?.view {
|
||||
if let result = unsupportedButtonView.hitTest(self.convert(point, to: unsupportedButtonView), with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func update(component: StoryItemContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<StoryContentItem.Environment>, transition: Transition) -> CGSize {
|
||||
self.component = component
|
||||
self.state = state
|
||||
self.environment = environment[StoryContentItem.Environment.self].value
|
||||
let environment = environment[StoryContentItem.Environment.self].value
|
||||
self.environment = environment
|
||||
|
||||
let peerReference = PeerReference(component.peer._asPeer())
|
||||
|
||||
@ -366,6 +332,8 @@ final class StoryItemContentComponent: Component {
|
||||
messageMedia = .image(image)
|
||||
case let .file(file):
|
||||
messageMedia = .file(file)
|
||||
case .unsupported:
|
||||
self.contentLoaded = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -504,6 +472,99 @@ final class StoryItemContentComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
switch component.item.media {
|
||||
case .image, .file:
|
||||
if let unsupportedText = self.unsupportedText {
|
||||
self.unsupportedText = nil
|
||||
unsupportedText.view?.removeFromSuperview()
|
||||
}
|
||||
if let unsupportedButton = self.unsupportedButton {
|
||||
self.unsupportedButton = nil
|
||||
unsupportedButton.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
self.backgroundColor = .black
|
||||
default:
|
||||
var unsuportedTransition = transition
|
||||
|
||||
let unsupportedText: ComponentView<Empty>
|
||||
if let current = self.unsupportedText {
|
||||
unsupportedText = current
|
||||
} else {
|
||||
unsuportedTransition = .immediate
|
||||
unsupportedText = ComponentView()
|
||||
self.unsupportedText = unsupportedText
|
||||
}
|
||||
|
||||
let unsupportedButton: ComponentView<Empty>
|
||||
if let current = self.unsupportedButton {
|
||||
unsupportedButton = current
|
||||
} else {
|
||||
unsuportedTransition = .immediate
|
||||
unsupportedButton = ComponentView()
|
||||
self.unsupportedButton = unsupportedButton
|
||||
}
|
||||
|
||||
//TODO:localize
|
||||
let unsupportedTextSize = unsupportedText.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "This story is not supported by\nyour version of Telegram.", font: Font.regular(17.0), textColor: .white)),
|
||||
horizontalAlignment: .center,
|
||||
maximumNumberOfLines: 0
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - 16.0 * 2.0, height: availableSize.height)
|
||||
)
|
||||
let unsupportedButtonSize = unsupportedButton.update(
|
||||
transition: unsuportedTransition,
|
||||
component: AnyComponent(ButtonComponent(
|
||||
background: ButtonComponent.Background(
|
||||
color: environment.theme.list.itemCheckColors.fillColor,
|
||||
foreground: environment.theme.list.itemCheckColors.foregroundColor,
|
||||
pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.7)
|
||||
),
|
||||
content: AnyComponentWithIdentity(id: AnyHashable(""), component: AnyComponent(Text(text: "Update Telegram", font: Font.semibold(17.0), color: environment.theme.list.itemCheckColors.foregroundColor
|
||||
))),
|
||||
isEnabled: true,
|
||||
displaysProgress: false,
|
||||
action: { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
component.context.sharedContext.applicationBindings.openAppStorePage()
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 240.0, height: 50.0)
|
||||
)
|
||||
|
||||
let spacing: CGFloat = 24.0
|
||||
let contentHeight = unsupportedTextSize.height + unsupportedButtonSize.height + spacing
|
||||
var contentY = floor((availableSize.height - contentHeight) * 0.5)
|
||||
|
||||
let unsupportedTextFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - unsupportedTextSize.width) * 0.5), y: contentY), size: unsupportedTextSize)
|
||||
contentY += unsupportedTextSize.height + spacing
|
||||
|
||||
let unsupportedButtonFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - unsupportedButtonSize.width) * 0.5), y: contentY), size: unsupportedButtonSize)
|
||||
|
||||
if let unsupportedTextView = unsupportedText.view {
|
||||
if unsupportedTextView.superview == nil {
|
||||
self.addSubview(unsupportedTextView)
|
||||
}
|
||||
unsuportedTransition.setPosition(view: unsupportedTextView, position: unsupportedTextFrame.center)
|
||||
unsupportedTextView.bounds = CGRect(origin: CGPoint(), size: unsupportedTextFrame.size)
|
||||
}
|
||||
if let unsupportedButtonView = unsupportedButton.view {
|
||||
if unsupportedButtonView.superview == nil {
|
||||
self.addSubview(unsupportedButtonView)
|
||||
}
|
||||
unsuportedTransition.setFrame(view: unsupportedButtonView, frame: unsupportedButtonFrame)
|
||||
}
|
||||
|
||||
self.backgroundColor = UIColor(rgb: 0x181818)
|
||||
}
|
||||
|
||||
self.updateIsProgressPaused()
|
||||
|
||||
return availableSize
|
||||
|
@ -11,6 +11,16 @@ import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import StoryContainerScreen
|
||||
|
||||
public func shouldDisplayStoriesInChatListHeader(storySubscriptions: EngineStorySubscriptions) -> Bool {
|
||||
if !storySubscriptions.items.isEmpty {
|
||||
return true
|
||||
}
|
||||
if let accountItem = storySubscriptions.accountItem, (accountItem.hasUnseen || accountItem.hasPending) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func solveParabolicMotion(from sourcePoint: CGPoint, to targetPosition: CGPoint, progress: CGFloat) -> CGPoint {
|
||||
if sourcePoint.y == targetPosition.y {
|
||||
return sourcePoint.interpolate(to: targetPosition, amount: progress)
|
||||
@ -373,12 +383,23 @@ public final class StoryPeerListComponent: Component {
|
||||
}
|
||||
|
||||
var hasStories: Bool = false
|
||||
if let storySubscriptions = component.storySubscriptions, !storySubscriptions.items.isEmpty {
|
||||
if let storySubscriptions = component.storySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions) {
|
||||
hasStories = true
|
||||
}
|
||||
let _ = hasStories
|
||||
|
||||
let collapseStartIndex = component.useHiddenList ? 0 : 1
|
||||
let collapseStartIndex: Int
|
||||
if component.useHiddenList {
|
||||
collapseStartIndex = 0
|
||||
} else if let storySubscriptions = component.storySubscriptions {
|
||||
if let accountItem = storySubscriptions.accountItem, (accountItem.hasUnseen || accountItem.hasPending) {
|
||||
collapseStartIndex = 0
|
||||
} else {
|
||||
collapseStartIndex = 1
|
||||
}
|
||||
} else {
|
||||
collapseStartIndex = 1
|
||||
}
|
||||
|
||||
let collapsedItemWidth: CGFloat = 24.0
|
||||
let collapsedItemDistance: CGFloat = 14.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user