mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Conference updates
This commit is contained in:
parent
e03a9d818e
commit
e8b7f53c84
@ -15,17 +15,20 @@ final class VideoChatListInviteComponent: Component {
|
|||||||
let title: String
|
let title: String
|
||||||
let icon: Icon
|
let icon: Icon
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
|
let hasNext: Bool
|
||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
title: String,
|
title: String,
|
||||||
icon: Icon,
|
icon: Icon,
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
|
hasNext: Bool,
|
||||||
action: @escaping () -> Void
|
action: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.title = title
|
self.title = title
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.hasNext = hasNext
|
||||||
self.action = action
|
self.action = action
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +42,9 @@ final class VideoChatListInviteComponent: Component {
|
|||||||
if lhs.theme !== rhs.theme {
|
if lhs.theme !== rhs.theme {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.hasNext != rhs.hasNext {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +58,11 @@ final class VideoChatListInviteComponent: Component {
|
|||||||
private var highlightBackgroundLayer: SimpleLayer?
|
private var highlightBackgroundLayer: SimpleLayer?
|
||||||
private var highlightBackgroundFrame: CGRect?
|
private var highlightBackgroundFrame: CGRect?
|
||||||
|
|
||||||
|
private let separatorLayer: SimpleLayer
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
|
self.separatorLayer = SimpleLayer()
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.highligthedChanged = { [weak self] isHighlighted in
|
self.highligthedChanged = { [weak self] isHighlighted in
|
||||||
@ -74,6 +84,15 @@ final class VideoChatListInviteComponent: Component {
|
|||||||
}
|
}
|
||||||
highlightBackgroundLayer.frame = highlightBackgroundFrame
|
highlightBackgroundLayer.frame = highlightBackgroundFrame
|
||||||
highlightBackgroundLayer.opacity = 1.0
|
highlightBackgroundLayer.opacity = 1.0
|
||||||
|
if component.hasNext {
|
||||||
|
highlightBackgroundLayer.maskedCorners = []
|
||||||
|
highlightBackgroundLayer.masksToBounds = false
|
||||||
|
highlightBackgroundLayer.cornerRadius = 0.0
|
||||||
|
} else {
|
||||||
|
highlightBackgroundLayer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
|
||||||
|
highlightBackgroundLayer.masksToBounds = true
|
||||||
|
highlightBackgroundLayer.cornerRadius = 10.0
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if let highlightBackgroundLayer = self.highlightBackgroundLayer {
|
if let highlightBackgroundLayer = self.highlightBackgroundLayer {
|
||||||
self.highlightBackgroundLayer = nil
|
self.highlightBackgroundLayer = nil
|
||||||
@ -152,7 +171,14 @@ final class VideoChatListInviteComponent: Component {
|
|||||||
transition.setFrame(view: iconView, frame: iconFrame)
|
transition.setFrame(view: iconView, frame: iconFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
//self.highlightBackgroundFrame = CGRect(origin: CGPoint(), size: size)
|
self.highlightBackgroundFrame = CGRect(origin: CGPoint(), size: size)
|
||||||
|
|
||||||
|
if self.separatorLayer.superlayer == nil {
|
||||||
|
self.layer.addSublayer(self.separatorLayer)
|
||||||
|
}
|
||||||
|
self.separatorLayer.backgroundColor = component.theme.list.itemBlocksSeparatorColor.cgColor
|
||||||
|
transition.setFrame(layer: self.separatorLayer, frame: CGRect(origin: CGPoint(x: 62.0, y: size.height), size: CGSize(width: size.width - 62.0, height: UIScreenPixel)))
|
||||||
|
self.separatorLayer.isHidden = !component.hasNext
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
@ -1760,74 +1760,6 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let measureListItemSize = self.measureListItemView.update(
|
|
||||||
transition: .immediate,
|
|
||||||
component: AnyComponent(PeerListItemComponent(
|
|
||||||
context: component.call.accountContext,
|
|
||||||
theme: component.theme,
|
|
||||||
strings: component.strings,
|
|
||||||
style: .generic,
|
|
||||||
sideInset: 0.0,
|
|
||||||
title: "AAA",
|
|
||||||
peer: nil,
|
|
||||||
subtitle: PeerListItemComponent.Subtitle(text: "bbb", color: .neutral),
|
|
||||||
subtitleAccessory: .none,
|
|
||||||
presence: nil,
|
|
||||||
selectionState: .none,
|
|
||||||
hasNext: true,
|
|
||||||
action: { _, _, _ in
|
|
||||||
}
|
|
||||||
)),
|
|
||||||
environment: {},
|
|
||||||
containerSize: CGSize(width: availableSize.width, height: 1000.0)
|
|
||||||
)
|
|
||||||
|
|
||||||
var inviteListItemSizes: [CGSize] = []
|
|
||||||
for (inviteOption) in component.participants?.inviteOptions ?? [] {
|
|
||||||
let inviteText: String
|
|
||||||
let iconType: VideoChatListInviteComponent.Icon
|
|
||||||
switch inviteOption.type {
|
|
||||||
case let .invite(isMultiple):
|
|
||||||
//TODO:localize
|
|
||||||
if isMultiple {
|
|
||||||
inviteText = component.strings.VoiceChat_InviteMember
|
|
||||||
} else {
|
|
||||||
inviteText = "Add Member"
|
|
||||||
}
|
|
||||||
iconType = .addUser
|
|
||||||
case .shareLink:
|
|
||||||
inviteText = component.strings.VoiceChat_Share
|
|
||||||
iconType = .link
|
|
||||||
}
|
|
||||||
|
|
||||||
let inviteListItemView: ComponentView<Empty>
|
|
||||||
var inviteListItemTransition = transition
|
|
||||||
if let current = self.inviteListItemViews[inviteOption.id] {
|
|
||||||
inviteListItemView = current
|
|
||||||
} else {
|
|
||||||
inviteListItemView = ComponentView()
|
|
||||||
self.inviteListItemViews[inviteOption.id] = inviteListItemView
|
|
||||||
inviteListItemTransition = inviteListItemTransition.withAnimation(.none)
|
|
||||||
}
|
|
||||||
|
|
||||||
inviteListItemSizes.append(inviteListItemView.update(
|
|
||||||
transition: inviteListItemTransition,
|
|
||||||
component: AnyComponent(VideoChatListInviteComponent(
|
|
||||||
title: inviteText,
|
|
||||||
icon: iconType,
|
|
||||||
theme: component.theme,
|
|
||||||
action: { [weak self] in
|
|
||||||
guard let self, let component = self.component else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
component.openInviteMembers(inviteOption.type)
|
|
||||||
}
|
|
||||||
)),
|
|
||||||
environment: {},
|
|
||||||
containerSize: CGSize(width: availableSize.width, height: 1000.0)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
var gridParticipants: [VideoParticipant] = []
|
var gridParticipants: [VideoParticipant] = []
|
||||||
var listParticipants: [GroupCallParticipantsContext.Participant] = []
|
var listParticipants: [GroupCallParticipantsContext.Participant] = []
|
||||||
if let participants = component.participants {
|
if let participants = component.participants {
|
||||||
@ -1868,6 +1800,90 @@ final class VideoChatParticipantsComponent: Component {
|
|||||||
self.gridParticipants = gridParticipants
|
self.gridParticipants = gridParticipants
|
||||||
self.listParticipants = listParticipants
|
self.listParticipants = listParticipants
|
||||||
|
|
||||||
|
let measureListItemSize = self.measureListItemView.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(PeerListItemComponent(
|
||||||
|
context: component.call.accountContext,
|
||||||
|
theme: component.theme,
|
||||||
|
strings: component.strings,
|
||||||
|
style: .generic,
|
||||||
|
sideInset: 0.0,
|
||||||
|
title: "AAA",
|
||||||
|
peer: nil,
|
||||||
|
subtitle: PeerListItemComponent.Subtitle(text: "bbb", color: .neutral),
|
||||||
|
subtitleAccessory: .none,
|
||||||
|
presence: nil,
|
||||||
|
selectionState: .none,
|
||||||
|
hasNext: true,
|
||||||
|
action: { _, _, _ in
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: availableSize.width, height: 1000.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
var inviteListItemSizes: [CGSize] = []
|
||||||
|
if let participants = component.participants {
|
||||||
|
let tempItemLayout = ItemLayout(
|
||||||
|
containerSize: availableSize,
|
||||||
|
layout: component.layout,
|
||||||
|
isUIHidden: component.expandedVideoState?.isUIHidden ?? false,
|
||||||
|
expandedInsets: component.expandedInsets,
|
||||||
|
safeInsets: component.safeInsets,
|
||||||
|
gridItemCount: gridParticipants.count,
|
||||||
|
listItemCount: listParticipants.count + component.invitedPeers.count,
|
||||||
|
listItemHeight: measureListItemSize.height,
|
||||||
|
listTrailingItemHeights: []
|
||||||
|
)
|
||||||
|
|
||||||
|
for i in 0 ..< participants.inviteOptions.count {
|
||||||
|
let inviteOption = participants.inviteOptions[i]
|
||||||
|
let inviteText: String
|
||||||
|
let iconType: VideoChatListInviteComponent.Icon
|
||||||
|
switch inviteOption.type {
|
||||||
|
case let .invite(isMultiple):
|
||||||
|
//TODO:localize
|
||||||
|
if isMultiple {
|
||||||
|
inviteText = component.strings.VoiceChat_InviteMember
|
||||||
|
} else {
|
||||||
|
inviteText = "Add Member"
|
||||||
|
}
|
||||||
|
iconType = .addUser
|
||||||
|
case .shareLink:
|
||||||
|
inviteText = component.strings.VoiceChat_Share
|
||||||
|
iconType = .link
|
||||||
|
}
|
||||||
|
|
||||||
|
let inviteListItemView: ComponentView<Empty>
|
||||||
|
var inviteListItemTransition = transition
|
||||||
|
if let current = self.inviteListItemViews[inviteOption.id] {
|
||||||
|
inviteListItemView = current
|
||||||
|
} else {
|
||||||
|
inviteListItemView = ComponentView()
|
||||||
|
self.inviteListItemViews[inviteOption.id] = inviteListItemView
|
||||||
|
inviteListItemTransition = inviteListItemTransition.withAnimation(.none)
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteListItemSizes.append(inviteListItemView.update(
|
||||||
|
transition: inviteListItemTransition,
|
||||||
|
component: AnyComponent(VideoChatListInviteComponent(
|
||||||
|
title: inviteText,
|
||||||
|
icon: iconType,
|
||||||
|
theme: component.theme,
|
||||||
|
hasNext: i != participants.inviteOptions.count - 1,
|
||||||
|
action: { [weak self] in
|
||||||
|
guard let self, let component = self.component else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
component.openInviteMembers(inviteOption.type)
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: availableSize.width - tempItemLayout.list.sideInset * 2.0, height: 1000.0)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let itemLayout = ItemLayout(
|
let itemLayout = ItemLayout(
|
||||||
containerSize: availableSize,
|
containerSize: availableSize,
|
||||||
layout: component.layout,
|
layout: component.layout,
|
||||||
|
@ -1301,6 +1301,70 @@ public final class AccountViewTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func refreshInlineGroupCallsForMessageIds(messageIds: Set<MessageId>) {
|
||||||
|
self.queue.async {
|
||||||
|
var addedMessageIds: [MessageId] = []
|
||||||
|
let timestamp = Int32(CFAbsoluteTimeGetCurrent())
|
||||||
|
for messageId in messageIds {
|
||||||
|
let messageTimestamp = self.updatedUnsupportedMediaMessageIdsAndTimestamps[MessageAndThreadId(messageId: messageId, threadId: nil)]
|
||||||
|
var refresh = false
|
||||||
|
if let messageTimestamp = messageTimestamp {
|
||||||
|
refresh = messageTimestamp < timestamp - 60
|
||||||
|
} else {
|
||||||
|
refresh = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if refresh {
|
||||||
|
self.updatedUnsupportedMediaMessageIdsAndTimestamps[MessageAndThreadId(messageId: messageId, threadId: nil)] = timestamp
|
||||||
|
addedMessageIds.append(messageId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !addedMessageIds.isEmpty {
|
||||||
|
for (_, messageIds) in messagesIdsGroupedByPeerId(Set(addedMessageIds)) {
|
||||||
|
let disposableId = self.nextUpdatedUnsupportedMediaDisposableId
|
||||||
|
self.nextUpdatedUnsupportedMediaDisposableId += 1
|
||||||
|
|
||||||
|
if let account = self.account {
|
||||||
|
let signal = account.postbox.transaction { transaction -> [MessageId] in
|
||||||
|
var result: [MessageId] = []
|
||||||
|
for id in messageIds {
|
||||||
|
if let message = transaction.getMessage(id) {
|
||||||
|
for media in message.media {
|
||||||
|
if let _ = media as? TelegramMediaAction {
|
||||||
|
result.append(id)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|> mapToSignal { ids -> Signal<Never, NoError> in
|
||||||
|
guard !ids.isEmpty else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
var requests: [Signal<Never, NoError>] = []
|
||||||
|
|
||||||
|
for id in ids {
|
||||||
|
requests.append(_internal_refreshInlineGroupCall(account: account, messageId: id))
|
||||||
|
}
|
||||||
|
|
||||||
|
return combineLatest(requests)
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
|> afterDisposed { [weak self] in
|
||||||
|
self?.queue.async {
|
||||||
|
self?.updatedUnsupportedMediaDisposables.set(nil, forKey: disposableId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.updatedUnsupportedMediaDisposables.set(signal.start(), forKey: disposableId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func refreshStoryStatsForPeerIds(peerIds: [PeerId]) {
|
public func refreshStoryStatsForPeerIds(peerIds: [PeerId]) {
|
||||||
self.queue.async {
|
self.queue.async {
|
||||||
self.pendingRefreshStoriesForPeerIds.append(contentsOf: peerIds)
|
self.pendingRefreshStoriesForPeerIds.append(contentsOf: peerIds)
|
||||||
|
@ -241,6 +241,53 @@ func _internal_getCurrentGroupCall(account: Account, reference: InternalGroupCal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_getCurrentGroupCallInfo(account: Account, reference: InternalGroupCallReference) -> Signal<(participants: [PeerId], duration: Int32?)?, NoError> {
|
||||||
|
let accountPeerId = account.peerId
|
||||||
|
let inputCall: Api.InputGroupCall
|
||||||
|
switch reference {
|
||||||
|
case let .id(id, accessHash):
|
||||||
|
inputCall = .inputGroupCall(id: id, accessHash: accessHash)
|
||||||
|
case let .link(slug):
|
||||||
|
inputCall = .inputGroupCallSlug(slug: slug)
|
||||||
|
case let .message(id):
|
||||||
|
if id.peerId.namespace != Namespaces.Peer.CloudUser {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
if id.namespace != Namespaces.Message.Cloud {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
inputCall = .inputGroupCallInviteMessage(msgId: id.id)
|
||||||
|
}
|
||||||
|
return account.network.request(Api.functions.phone.getGroupCall(call: inputCall, limit: 4))
|
||||||
|
|> map(Optional.init)
|
||||||
|
|> `catch` { _ -> Signal<Api.phone.GroupCall?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<(participants: [PeerId], duration: Int32?)?, NoError> in
|
||||||
|
guard let result else {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
switch result {
|
||||||
|
case let .groupCall(call, participants, _, chats, users):
|
||||||
|
return account.postbox.transaction { transaction -> (participants: [PeerId], duration: Int32?)? in
|
||||||
|
if case let .groupCallDiscarded(_, _, duration) = call {
|
||||||
|
return ([], duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||||
|
|
||||||
|
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||||
|
|
||||||
|
let parsedParticipants = participants.compactMap { GroupCallParticipantsContext.Participant($0, transaction: transaction) }
|
||||||
|
return (
|
||||||
|
parsedParticipants.map(\.peer.id),
|
||||||
|
nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum CreateGroupCallError {
|
public enum CreateGroupCallError {
|
||||||
case generic
|
case generic
|
||||||
case anonymousNotAllowed
|
case anonymousNotAllowed
|
||||||
@ -3050,3 +3097,59 @@ func _internal_sendConferenceCallBroadcast(account: Account, callId: Int64, acce
|
|||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_refreshInlineGroupCall(account: Account, messageId: MessageId) -> Signal<Never, NoError> {
|
||||||
|
return _internal_getCurrentGroupCallInfo(account: account, reference: .message(id: messageId))
|
||||||
|
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||||
|
return account.postbox.transaction { transaction -> Void in
|
||||||
|
transaction.updateMessage(messageId, update: { currentMessage in
|
||||||
|
var storeForwardInfo: StoreMessageForwardInfo?
|
||||||
|
if let forwardInfo = currentMessage.forwardInfo {
|
||||||
|
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
|
||||||
|
}
|
||||||
|
var updatedMedia = currentMessage.media
|
||||||
|
|
||||||
|
for i in 0 ..< updatedMedia.count {
|
||||||
|
if let action = updatedMedia[i] as? TelegramMediaAction, case let .conferenceCall(conferenceCall) = action.action {
|
||||||
|
var otherParticipants: [PeerId] = []
|
||||||
|
var duration: Int32? = conferenceCall.duration
|
||||||
|
if let result {
|
||||||
|
for id in result.participants {
|
||||||
|
if id != account.peerId {
|
||||||
|
otherParticipants.append(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
duration = result.duration
|
||||||
|
} else {
|
||||||
|
duration = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedMedia[i] = TelegramMediaAction(action: .conferenceCall(TelegramMediaActionType.ConferenceCall(
|
||||||
|
callId: conferenceCall.callId,
|
||||||
|
duration: duration,
|
||||||
|
flags: conferenceCall.flags,
|
||||||
|
otherParticipants: otherParticipants
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .update(StoreMessage(
|
||||||
|
id: currentMessage.id,
|
||||||
|
globallyUniqueId: currentMessage.globallyUniqueId,
|
||||||
|
groupingKey: currentMessage.groupingKey,
|
||||||
|
threadId: currentMessage.threadId,
|
||||||
|
timestamp: currentMessage.timestamp,
|
||||||
|
flags: StoreMessageFlags(currentMessage.flags),
|
||||||
|
tags: currentMessage.tags,
|
||||||
|
globalTags: currentMessage.globalTags,
|
||||||
|
localTags: currentMessage.localTags,
|
||||||
|
forwardInfo: storeForwardInfo,
|
||||||
|
authorId: currentMessage.author?.id,
|
||||||
|
text: currentMessage.text,
|
||||||
|
attributes: currentMessage.attributes,
|
||||||
|
media: updatedMedia
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -142,6 +142,9 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
#else
|
#else
|
||||||
missedTimeout = 30
|
missedTimeout = 30
|
||||||
#endif
|
#endif
|
||||||
|
if conferenceCall.duration != nil {
|
||||||
|
hasCallButton = false
|
||||||
|
}
|
||||||
let currentTime = Int32(Date().timeIntervalSince1970)
|
let currentTime = Int32(Date().timeIntervalSince1970)
|
||||||
if conferenceCall.flags.contains(.isMissed) {
|
if conferenceCall.flags.contains(.isMissed) {
|
||||||
titleString = "Declined Group Call"
|
titleString = "Declined Group Call"
|
||||||
@ -149,7 +152,6 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
titleString = "Missed Group Call"
|
titleString = "Missed Group Call"
|
||||||
} else if conferenceCall.duration != nil {
|
} else if conferenceCall.duration != nil {
|
||||||
titleString = "Cancelled Group Call"
|
titleString = "Cancelled Group Call"
|
||||||
hasCallButton = true
|
|
||||||
} else {
|
} else {
|
||||||
if incoming {
|
if incoming {
|
||||||
titleString = "Incoming Group Call"
|
titleString = "Incoming Group Call"
|
||||||
|
@ -586,6 +586,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
private let translationProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 1.0)
|
private let translationProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 1.0)
|
||||||
private let refreshStoriesProcessingManager = ChatMessageThrottledProcessingManager()
|
private let refreshStoriesProcessingManager = ChatMessageThrottledProcessingManager()
|
||||||
private let factCheckProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 1.0)
|
private let factCheckProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 1.0)
|
||||||
|
private let inlineGroupCallsProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 1.0)
|
||||||
|
|
||||||
let prefetchManager: InChatPrefetchManager
|
let prefetchManager: InChatPrefetchManager
|
||||||
private var currentEarlierPrefetchMessages: [(Message, Media)] = []
|
private var currentEarlierPrefetchMessages: [(Message, Media)] = []
|
||||||
@ -978,6 +979,10 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
strongSelf.context.account.viewTracker.updatedExtendedMediaForMessageIds(messageIds: Set(messageIds.map(\.messageId)))
|
strongSelf.context.account.viewTracker.updatedExtendedMediaForMessageIds(messageIds: Set(messageIds.map(\.messageId)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.inlineGroupCallsProcessingManager.process = { [weak context] messageIds in
|
||||||
|
context?.account.viewTracker.refreshInlineGroupCallsForMessageIds(messageIds: Set(messageIds.map(\.messageId)))
|
||||||
|
}
|
||||||
|
|
||||||
self.preloadPages = false
|
self.preloadPages = false
|
||||||
|
|
||||||
self.beginChatHistoryTransitions(resetScrolling: false)
|
self.beginChatHistoryTransitions(resetScrolling: false)
|
||||||
@ -2728,6 +2733,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
var messageIdsWithUnseenPersonalMention: [MessageId] = []
|
var messageIdsWithUnseenPersonalMention: [MessageId] = []
|
||||||
var messageIdsWithUnseenReactions: [MessageId] = []
|
var messageIdsWithUnseenReactions: [MessageId] = []
|
||||||
var messageIdsWithInactiveExtendedMedia = Set<MessageId>()
|
var messageIdsWithInactiveExtendedMedia = Set<MessageId>()
|
||||||
|
var messageIdsWithGroupCalls: [MessageId] = []
|
||||||
var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = []
|
var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = []
|
||||||
var allVisibleAnchorMessageIds: [(MessageId, Int)] = []
|
var allVisibleAnchorMessageIds: [(MessageId, Int)] = []
|
||||||
var visibleAdOpaqueIds: [Data] = []
|
var visibleAdOpaqueIds: [Data] = []
|
||||||
@ -2826,6 +2832,13 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
storiesRequiredValidation = true
|
storiesRequiredValidation = true
|
||||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let _ = content.story {
|
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let _ = content.story {
|
||||||
storiesRequiredValidation = true
|
storiesRequiredValidation = true
|
||||||
|
} else if let media = media as? TelegramMediaAction {
|
||||||
|
if case let .conferenceCall(conferenceCall) = media.action {
|
||||||
|
if conferenceCall.duration != nil {
|
||||||
|
} else {
|
||||||
|
messageIdsWithGroupCalls.append(message.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if contentRequiredValidation {
|
if contentRequiredValidation {
|
||||||
@ -3083,6 +3096,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
if !peerIdsWithRefreshStories.isEmpty {
|
if !peerIdsWithRefreshStories.isEmpty {
|
||||||
self.context.account.viewTracker.refreshStoryStatsForPeerIds(peerIds: peerIdsWithRefreshStories)
|
self.context.account.viewTracker.refreshStoryStatsForPeerIds(peerIds: peerIdsWithRefreshStories)
|
||||||
}
|
}
|
||||||
|
if !messageIdsWithGroupCalls.isEmpty {
|
||||||
|
self.inlineGroupCallsProcessingManager.add(messageIdsWithGroupCalls.map { MessageAndThreadId(messageId: $0, threadId: nil) })
|
||||||
|
}
|
||||||
|
|
||||||
self.currentEarlierPrefetchMessages = toEarlierMediaMessages
|
self.currentEarlierPrefetchMessages = toEarlierMediaMessages
|
||||||
self.currentLaterPrefetchMessages = toLaterMediaMessages
|
self.currentLaterPrefetchMessages = toLaterMediaMessages
|
||||||
|
Loading…
x
Reference in New Issue
Block a user