Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2023-07-15 20:32:45 +02:00
commit 61c795b95b
9 changed files with 224 additions and 187 deletions

View File

@ -1083,26 +1083,19 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.chatListDisplayNode.mainContainerNode.currentItemNode.clearHighlightAnimated(true)
if let navigationController = self.navigationController as? NavigationController {
let chatListController = ChatListControllerImpl(context: self.context, location: .chatList(groupId: groupId), controlsHistoryPreload: false, enableDebugActions: false)
chatListController.navigationPresentation = .master
navigationController.pushViewController(chatListController)
}
if !didDisplayTip {
#if DEBUG
#else
let _ = ApplicationSpecificNotice.setDisplayChatListArchiveTooltip(accountManager: self.context.sharedContext.accountManager).start()
#endif
self.push(ArchiveInfoScreen(context: self.context, settings: settings, buttonAction: { [weak self] in
guard let self else {
return
}
if let navigationController = self.navigationController as? NavigationController {
let chatListController = ChatListControllerImpl(context: self.context, location: .chatList(groupId: groupId), controlsHistoryPreload: false, enableDebugActions: false)
chatListController.navigationPresentation = .master
navigationController.pushViewController(chatListController)
}
}))
} else {
if let navigationController = self.navigationController as? NavigationController {
let chatListController = ChatListControllerImpl(context: self.context, location: .chatList(groupId: groupId), controlsHistoryPreload: false, enableDebugActions: false)
chatListController.navigationPresentation = .master
navigationController.pushViewController(chatListController)
}
self.push(ArchiveInfoScreen(context: self.context, settings: settings))
}
})
}
@ -2693,6 +2686,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
if peer.isService {
return
}
var items: [ContextMenuItem] = []
//TODO:localize
@ -2769,7 +2766,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
})))
let isMuted = resolvedAreStoriesMuted(globalSettings: globalSettings._asGlobalNotificationSettings(), peer: peer._asPeer(), peerSettings: notificationSettings._asNotificationSettings(), topSearchPeers: topSearchPeers)
items.append(.action(ContextMenuActionItem(text: isMuted ? "Notify" : "Don't Notify", icon: { theme in
items.append(.action(ContextMenuActionItem(text: isMuted ? "Notify About Stories" : "Do Not Notify About Stories", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
@ -2814,11 +2811,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let hideText: String
if self.location == .chatList(groupId: .archive) {
hideText = "Unarchive"
hideText = "Unhide Stories"
} else {
hideText = "Archive"
hideText = "Hide Stories"
}
let iconName = self.location == .chatList(groupId: .archive) ? "Chat/Context Menu/MoveToChats" : "Chat/Context Menu/MoveToContacts"
let iconName = self.location == .chatList(groupId: .archive) ? "Chat/Context Menu/Unarchive" : "Chat/Context Menu/Archive"
items.append(.action(ContextMenuActionItem(text: hideText, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: iconName), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in

View File

@ -194,6 +194,7 @@ public func archiveSettingsController(context: AccountContext) -> ViewController
}
let controller = ItemListController(context: context, state: signal)
controller.navigationPresentation = .modal
presentUndoImpl = { [weak controller] content in
guard let controller else {

View File

@ -8973,6 +8973,25 @@ public extension Api.functions.users {
})
}
}
public extension Api.functions.users {
static func getStoriesMaxIDs(id: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) {
let buffer = Buffer()
buffer.appendInt32(-904087125)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(id.count))
for item in id {
item.serialize(buffer, true)
}
return (FunctionDescription(name: "users.getStoriesMaxIDs", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in
let reader = BufferReader(buffer)
var result: [Int32]?
if let _ = reader.readInt32() {
result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
}
return result
})
}
}
public extension Api.functions.users {
static func getUsers(id: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.User]>) {
let buffer = Buffer()

View File

@ -104,7 +104,7 @@ extension TelegramUser {
static func merge(_ lhs: TelegramUser?, rhs: Api.User) -> TelegramUser? {
switch rhs {
case let .user(flags, flags2, _, rhsAccessHash, _, _, _, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, _, _):
case let .user(flags, _, _, rhsAccessHash, _, _, _, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, _, _):
let isMin = (flags & (1 << 20)) != 0
if !isMin {
return TelegramUser(user: rhs)
@ -137,7 +137,8 @@ extension TelegramUser {
if (flags & (1 << 28)) != 0 {
userFlags.insert(.isPremium)
}
if (flags2 & (1 << 2)) != 0 {
if lhs.flags.contains(.isCloseFriend) {
userFlags.insert(.isCloseFriend)
}

View File

@ -1289,7 +1289,7 @@ public final class AccountViewTracker {
let messageTimestamp = self.refreshStoriesForPeerIdsAndTimestamps[peerId]
var refresh = false
if let messageTimestamp = messageTimestamp {
refresh = messageTimestamp < timestamp - 60
refresh = messageTimestamp < timestamp - 60 * 60
} else {
refresh = true
}
@ -1304,8 +1304,14 @@ public final class AccountViewTracker {
self.nextUpdatedUnsupportedMediaDisposableId += 1
if let account = self.account {
let signal = account.postbox.transaction { transaction -> [Api.InputUser] in
return addedPeerIds.compactMap { transaction.getPeer($0).flatMap(apiInputUser) }
let signal = account.postbox.transaction { transaction -> [(PeerId, Api.InputUser)] in
return addedPeerIds.compactMap { id -> (PeerId, Api.InputUser)? in
if let user = transaction.getPeer(id).flatMap(apiInputUser) {
return (id, user)
} else {
return nil
}
}
}
|> mapToSignal { inputUsers -> Signal<Never, NoError> in
guard !inputUsers.isEmpty else {
@ -1314,21 +1320,30 @@ public final class AccountViewTracker {
var requests: [Signal<Never, NoError>] = []
let batchCount = 50
let batchCount = 100
var startIndex = 0
while startIndex < inputUsers.count {
var slice: [Api.InputUser] = []
var slice: [(PeerId, Api.InputUser)] = []
for i in startIndex ..< min(startIndex + batchCount, inputUsers.count) {
slice.append(inputUsers[i])
}
startIndex += batchCount
requests.append(account.network.request(Api.functions.users.getUsers(id: slice))
|> `catch` { _ -> Signal<[Api.User], NoError> in
requests.append(account.network.request(Api.functions.users.getStoriesMaxIDs(id: slice.map(\.1)))
|> `catch` { _ -> Signal<[Int32], NoError> in
return .single([])
}
|> mapToSignal { result -> Signal<Never, NoError> in
return account.postbox.transaction { transaction in
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(users: result))
for i in 0 ..< result.count {
if i < slice.count {
let value = result[i]
if value <= 0 {
transaction.clearStoryItemsInexactMaxId(peerId: slice[i].0)
} else {
transaction.setStoryItemsInexactMaxId(peerId: slice[i].0, id: value)
}
}
}
}
|> ignoreValues
})

View File

@ -322,7 +322,7 @@ public final class ChatListNavigationBar: Component {
let storiesOffsetFraction: CGFloat
let storiesUnlocked: Bool
if allowAvatarsExpansion {
storiesOffsetFraction = max(0.0, min(1.0, -offset / ChatListNavigationBar.storiesScrollHeight))
storiesOffsetFraction = max(0.0, min(4.0, -offset / ChatListNavigationBar.storiesScrollHeight))
if offset <= -60.0 {
storiesUnlocked = true

View File

@ -3850,7 +3850,114 @@ public final class StoryItemSetContainerComponent: Component {
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
var items: [ContextMenuItem] = []
if component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) {
let isMuted = resolvedAreStoriesMuted(globalSettings: globalSettings._asGlobalNotificationSettings(), peer: component.slice.peer._asPeer(), peerSettings: settings._asNotificationSettings(), topSearchPeers: topSearchPeers)
if !component.slice.peer.isService {
items.append(.action(ContextMenuActionItem(text: isMuted ? "Notify About Stories" : "Do Not Notify About Stories", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: component.slice.additionalPeerData.isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self, let component = self.component else {
return
}
let _ = component.context.engine.peers.togglePeerStoriesMuted(peerId: component.slice.peer.id).start()
let iconColor = UIColor.white
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
if isMuted {
self.component?.presentController(UndoOverlayController(
presentationData: presentationData,
content: .universal(animation: "anim_profileunmute", scale: 0.075, colors: [
"Middle.Group 1.Fill 1": iconColor,
"Top.Group 1.Fill 1": iconColor,
"Bottom.Group 1.Fill 1": iconColor,
"EXAMPLE.Group 1.Fill 1": iconColor,
"Line.Group 1.Stroke 1": iconColor
], title: nil, text: "You will now get a notification whenever **\(component.slice.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))** posts a story.", customUndoText: nil, timeout: nil),
elevatedLayout: false,
animateInAsReplacement: false,
action: { _ in return false }
), nil)
} else {
self.component?.presentController(UndoOverlayController(
presentationData: presentationData,
content: .universal(animation: "anim_profilemute", scale: 0.075, colors: [
"Middle.Group 1.Fill 1": iconColor,
"Top.Group 1.Fill 1": iconColor,
"Bottom.Group 1.Fill 1": iconColor,
"EXAMPLE.Group 1.Fill 1": iconColor,
"Line.Group 1.Stroke 1": iconColor
], title: nil, text: "You will no longer receive a notification when **\(component.slice.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))** posts a story.", customUndoText: nil, timeout: nil),
elevatedLayout: false,
animateInAsReplacement: false,
action: { _ in return false }
), nil)
}
})))
var isHidden = false
if case let .user(user) = component.slice.peer, let storiesHidden = user.storiesHidden {
isHidden = storiesHidden
}
items.append(.action(ContextMenuActionItem(text: isHidden ? "Unhide Stories" : "Hide Stories", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: isHidden ? "Chat/Context Menu/Unarchive" : "Chat/Context Menu/Archive"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self, let component = self.component else {
return
}
let _ = component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: !isHidden)
let text = !isHidden ? "Stories from **\(component.slice.peer.compactDisplayTitle)** will now be shown in Archived Chats." : "Stories from **\(component.slice.peer.compactDisplayTitle)** will now be shown in Chats."
let tooltipScreen = TooltipScreen(
context: component.context,
account: component.context.account,
sharedContext: component.context.sharedContext,
text: .markdown(text: text),
style: .customBlur(UIColor(rgb: 0x1c1c1c), 0.0),
icon: .peer(peer: component.slice.peer, isStory: true),
action: TooltipScreen.Action(
title: "Undo",
action: {
component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: isHidden)
}
),
location: .bottom,
shouldDismissOnTouch: { _, _ in return .dismiss(consume: false) }
)
tooltipScreen.willBecomeDismissed = { [weak self] _ in
guard let self else {
return
}
self.sendMessageContext.tooltipScreen = nil
self.updateIsProgressPaused()
}
self.sendMessageContext.tooltipScreen = tooltipScreen
self.updateIsProgressPaused()
component.controller()?.present(tooltipScreen, in: .current)
})))
}
if !component.slice.item.storyItem.isForwardingDisabled {
let saveText: String = "Save to Gallery"
items.append(.action(ContextMenuActionItem(text: saveText, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self else {
return
}
self.requestSave()
})))
}
if !component.slice.peer.isService && component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) {
items.append(.action(ContextMenuActionItem(text: "Copy Link", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
@ -3878,7 +3985,7 @@ public final class StoryItemSetContainerComponent: Component {
}
})
})))
items.append(.action(ContextMenuActionItem(text: "Share", icon: { theme in
/*items.append(.action(ContextMenuActionItem(text: "Share", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
@ -3887,152 +3994,44 @@ public final class StoryItemSetContainerComponent: Component {
return
}
self.sendMessageContext.performShareAction(view: self)
})))
}
let isMuted = resolvedAreStoriesMuted(globalSettings: globalSettings._asGlobalNotificationSettings(), peer: component.slice.peer._asPeer(), peerSettings: settings._asNotificationSettings(), topSearchPeers: topSearchPeers)
items.append(.action(ContextMenuActionItem(text: isMuted ? "Notify" : "Don't Notify", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: component.slice.additionalPeerData.isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self, let component = self.component else {
return
}
let _ = component.context.engine.peers.togglePeerStoriesMuted(peerId: component.slice.peer.id).start()
let iconColor = UIColor.white
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
if isMuted {
self.component?.presentController(UndoOverlayController(
presentationData: presentationData,
content: .universal(animation: "anim_profileunmute", scale: 0.075, colors: [
"Middle.Group 1.Fill 1": iconColor,
"Top.Group 1.Fill 1": iconColor,
"Bottom.Group 1.Fill 1": iconColor,
"EXAMPLE.Group 1.Fill 1": iconColor,
"Line.Group 1.Stroke 1": iconColor
], title: nil, text: "You will now get a notification whenever **\(component.slice.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))** posts a story.", customUndoText: nil, timeout: nil),
elevatedLayout: false,
animateInAsReplacement: false,
action: { _ in return false }
), nil)
} else {
self.component?.presentController(UndoOverlayController(
presentationData: presentationData,
content: .universal(animation: "anim_profilemute", scale: 0.075, colors: [
"Middle.Group 1.Fill 1": iconColor,
"Top.Group 1.Fill 1": iconColor,
"Bottom.Group 1.Fill 1": iconColor,
"EXAMPLE.Group 1.Fill 1": iconColor,
"Line.Group 1.Stroke 1": iconColor
], title: nil, text: "You will no longer receive a notification when **\(component.slice.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder))** posts a story.", customUndoText: nil, timeout: nil),
elevatedLayout: false,
animateInAsReplacement: false,
action: { _ in return false }
), nil)
}
})))
var isHidden = false
if case let .user(user) = component.slice.peer, let storiesHidden = user.storiesHidden {
isHidden = storiesHidden
})))*/
}
items.append(.action(ContextMenuActionItem(text: isHidden ? "Unarchive" : "Archive", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: isHidden ? "Chat/Context Menu/MoveToChats" : "Chat/Context Menu/MoveToContacts"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self, let component = self.component else {
return
}
let _ = component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: !isHidden)
let text = isHidden ? "Stories from **\(component.slice.peer.compactDisplayTitle)** will now be shown in Chats, not Contacts." : "Stories from **\(component.slice.peer.compactDisplayTitle)** will now be shown in Contacts, not Chats."
let tooltipScreen = TooltipScreen(
context: component.context,
account: component.context.account,
sharedContext: component.context.sharedContext,
text: .markdown(text: text),
style: .customBlur(UIColor(rgb: 0x1c1c1c), 0.0),
icon: .peer(peer: component.slice.peer, isStory: true),
action: TooltipScreen.Action(
title: "Undo",
action: {
component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: isHidden)
}
),
location: .bottom,
shouldDismissOnTouch: { _, _ in return .dismiss(consume: false) }
)
tooltipScreen.willBecomeDismissed = { [weak self] _ in
guard let self else {
if !component.slice.peer.isService {
items.append(.action(ContextMenuActionItem(text: "Report", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Report"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] c, a in
guard let self, let component = self.component, let controller = component.controller() else {
return
}
self.sendMessageContext.tooltipScreen = nil
self.updateIsProgressPaused()
}
self.sendMessageContext.tooltipScreen = tooltipScreen
self.updateIsProgressPaused()
component.controller()?.present(tooltipScreen, in: .current)
})))
#if DEBUG
let saveText: String
if case .file = component.slice.item.storyItem.media {
saveText = "Save Video"
} else {
saveText = "Save Image"
let options: [PeerReportOption] = [.spam, .violence, .pornography, .childAbuse, .copyright, .illegalDrugs, .personalDetails, .other]
presentPeerReportOptions(
context: component.context,
parent: controller,
contextController: c,
backAction: { _ in },
subject: .story(component.slice.peer.id, component.slice.item.storyItem.id),
options: options,
passthrough: true,
forceTheme: defaultDarkPresentationTheme,
isDetailedReportingVisible: { [weak self] isReporting in
guard let self else {
return
}
self.isReporting = isReporting
self.updateIsProgressPaused()
},
completion: { [weak self] reason, _ in
guard let self, let component = self.component, let controller = component.controller(), let reason else {
return
}
let _ = component.context.engine.peers.reportPeerStory(peerId: component.slice.peer.id, storyId: component.slice.item.storyItem.id, reason: reason, message: "").start()
controller.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
}
)
})))
}
items.append(.action(ContextMenuActionItem(text: saveText, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
a(.default)
guard let self else {
return
}
self.requestSave()
})))
#endif
items.append(.action(ContextMenuActionItem(text: "Report", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Report"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] c, a in
guard let self, let component = self.component, let controller = component.controller() else {
return
}
let options: [PeerReportOption] = [.spam, .violence, .pornography, .childAbuse, .copyright, .illegalDrugs, .personalDetails, .other]
presentPeerReportOptions(
context: component.context,
parent: controller,
contextController: c,
backAction: { _ in },
subject: .story(component.slice.peer.id, component.slice.item.storyItem.id),
options: options,
passthrough: true,
forceTheme: defaultDarkPresentationTheme,
isDetailedReportingVisible: { [weak self] isReporting in
guard let self else {
return
}
self.isReporting = isReporting
self.updateIsProgressPaused()
},
completion: { [weak self] reason, _ in
guard let self, let component = self.component, let controller = component.controller(), let reason else {
return
}
let _ = component.context.engine.peers.reportPeerStory(peerId: component.slice.peer.id, storyId: component.slice.item.storyItem.id, reason: reason, message: "").start()
controller.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
}
)
})))
var hasLinkedStickers = false
let media = component.slice.item.storyItem.media._asMedia()

View File

@ -910,7 +910,7 @@ final class StoryItemSetContainerSendMessage {
component.presentController(actionSheet, nil)
} else {
var preferredAction: ShareControllerPreferredAction?
if focusedItem.storyItem.isPublic {
if focusedItem.storyItem.isPublic && !component.slice.peer.isService {
preferredAction = .custom(action: ShareControllerAction(title: "Copy Link", action: {
let _ = ((component.context.engine.messages.exportStoryLink(peerId: peerId, id: focusedItem.storyItem.id))
|> deliverOnMainQueue).start(next: { link in

View File

@ -617,9 +617,10 @@ public final class StoryPeerListComponent: Component {
var activityFraction: CGFloat
}
let targetExpandedFraction = component.collapseFraction
let mappedTargetFraction: CGFloat = component.collapseFraction
let targetFraction: CGFloat = component.collapseFraction
let targetExpandedFraction: CGFloat = mappedTargetFraction
let targetFraction: CGFloat = mappedTargetFraction
let targetScaleFraction: CGFloat
let targetMinFraction: CGFloat
@ -704,7 +705,7 @@ public final class StoryPeerListComponent: Component {
}
} else {
collapsedState = CollapseState(
globalFraction: component.collapseFraction,
globalFraction: targetFraction,
scaleFraction: targetScaleFraction,
minFraction: targetMinFraction,
maxFraction: targetMaxFraction,
@ -769,6 +770,8 @@ public final class StoryPeerListComponent: Component {
let expandedItemWidth: CGFloat = 60.0
let overscrollFraction: CGFloat = max(0.0, collapsedState.maxFraction - 1.0)
struct MeasuredItem {
var itemFrame: CGRect
var itemScale: CGFloat
@ -804,11 +807,11 @@ public final class StoryPeerListComponent: Component {
let minimizedMaxItemScale: CGFloat = (24.0 + 4.0) / 52.0
let maximizedItemScale: CGFloat = 1.0
let maximizedItemScale: CGFloat = 1.0 + overscrollFraction * 0.1
let minItemScale: CGFloat = minimizedItemScale.interpolate(to: minimizedMaxItemScale, amount: collapsedState.minFraction) * (1.0 - collapsedState.activityFraction) + 0.1 * collapsedState.activityFraction
let itemScale: CGFloat = minItemScale.interpolate(to: maximizedItemScale, amount: collapsedState.maxFraction)
let itemScale: CGFloat = minItemScale.interpolate(to: maximizedItemScale, amount: min(1.0, collapsedState.maxFraction))
let itemFrame: CGRect
if isReallyVisible {
@ -819,14 +822,16 @@ public final class StoryPeerListComponent: Component {
adjustedRegularFrame = adjustedRegularFrame.interpolate(to: itemLayout.frame(at: effectiveFirstVisibleIndex + collapseEndIndex), amount: 0.0)
}
adjustedRegularFrame.origin.x -= effectiveVisibleBounds.minX
adjustedRegularFrame.origin.y += overscrollFraction * 83.0 * 0.5
let collapsedItemPosition: CGPoint = collapsedItemFrame.center.interpolate(to: collapsedMaxItemFrame.center, amount: collapsedState.minFraction)
var itemPosition = collapsedItemPosition.interpolate(to: adjustedRegularFrame.center, amount: collapsedState.maxFraction)
let itemPosition = collapsedItemPosition.interpolate(to: adjustedRegularFrame.center, amount: min(1.0, collapsedState.maxFraction))
var bounceOffsetFraction = (adjustedRegularFrame.midX - itemLayout.frame(at: collapseStartIndex).midX) / itemLayout.containerSize.width
let _ = expandBoundsFraction
/*var bounceOffsetFraction = (adjustedRegularFrame.midX - itemLayout.frame(at: collapseStartIndex).midX) / itemLayout.containerSize.width
bounceOffsetFraction = max(-1.0, min(1.0, bounceOffsetFraction))
itemPosition.x += min(10.0, expandBoundsFraction * collapsedState.maxFraction * 1200.0) * bounceOffsetFraction
itemPosition.x += min(10.0, expandBoundsFraction * min(1.0, collapsedState.maxFraction) * 1200.0) * bounceOffsetFraction*/
let itemSize = CGSize(width: adjustedRegularFrame.width * itemScale, height: adjustedRegularFrame.height)
@ -902,7 +907,7 @@ public final class StoryPeerListComponent: Component {
var isCollapsable: Bool = false
var itemScale = measuredItem.itemScale
if itemLayout.itemCount == 1 {
let singleScaleFactor = min(1.0, collapsedState.minFraction + collapsedState.maxFraction)
let singleScaleFactor = min(1.0, collapsedState.minFraction + min(1.0, collapsedState.maxFraction))
itemScale = 0.001 * (1.0 - singleScaleFactor) + itemScale * singleScaleFactor
}
@ -920,7 +925,7 @@ public final class StoryPeerListComponent: Component {
itemAlpha = (collapsedState.sideAlphaFraction * 1.0 + (1.0 - collapsedState.sideAlphaFraction) * (1.0 - collapsedState.activityFraction)) * collapsedState.sideAlphaFraction
} else {
if itemLayout.itemCount == 1 {
itemAlpha = min(1.0, (collapsedState.minFraction + collapsedState.maxFraction) * 4.0)
itemAlpha = min(1.0, (collapsedState.minFraction + min(1.0, collapsedState.maxFraction)) * 4.0)
} else {
itemAlpha = collapsedState.sideAlphaFraction
}
@ -1165,7 +1170,7 @@ public final class StoryPeerListComponent: Component {
if self.sortedItems.isEmpty {
titleContentOffset = collapsedTitleOffset
} else {
titleContentOffset = titleMinContentOffset.interpolate(to: ((itemLayout.containerSize.width - collapsedState.titleWidth) * 0.5) as CGFloat, amount: collapsedState.maxFraction * (1.0 - collapsedState.activityFraction))
titleContentOffset = titleMinContentOffset.interpolate(to: ((itemLayout.containerSize.width - collapsedState.titleWidth) * 0.5) as CGFloat, amount: min(1.0, collapsedState.maxFraction) * (1.0 - collapsedState.activityFraction))
}
var titleIndicatorSize: CGSize?