diff --git a/submodules/CallListUI/Sources/CallListControllerNode.swift b/submodules/CallListUI/Sources/CallListControllerNode.swift index 60175778ba..8ba77cd7da 100644 --- a/submodules/CallListUI/Sources/CallListControllerNode.swift +++ b/submodules/CallListUI/Sources/CallListControllerNode.swift @@ -118,6 +118,8 @@ private func mappedInsertEntries(context: AccountContext, presentationData: Item }), directionHint: entry.directionHint) case let .displayTabInfo(theme, text): return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: 0), directionHint: entry.directionHint) + case let .groupCall(_, peer): + preconditionFailure() case let .messageEntry(topMessage, messages, theme, strings, dateTimeFormat, editing, hasActiveRevealControls): return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListCallItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, context: context, style: showSettings ? .blocks : .plain, topMessage: topMessage, messages: messages, editing: editing, revealed: hasActiveRevealControls, interaction: nodeInteraction), directionHint: entry.directionHint) case let .holeEntry(_, theme): @@ -135,6 +137,8 @@ private func mappedUpdateEntries(context: AccountContext, presentationData: Item }), directionHint: entry.directionHint) case let .displayTabInfo(theme, text): return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: 0), directionHint: entry.directionHint) + case let .groupCall(_, peer): + preconditionFailure() case let .messageEntry(topMessage, messages, theme, strings, dateTimeFormat, editing, hasActiveRevealControls): return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListCallItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, context: context, style: showSettings ? .blocks : .plain, topMessage: topMessage, messages: messages, editing: editing, revealed: hasActiveRevealControls, interaction: nodeInteraction), directionHint: entry.directionHint) case let .holeEntry(_, theme): diff --git a/submodules/CallListUI/Sources/CallListNodeEntries.swift b/submodules/CallListUI/Sources/CallListNodeEntries.swift index 5080c7c156..4e017c5f0d 100644 --- a/submodules/CallListUI/Sources/CallListNodeEntries.swift +++ b/submodules/CallListUI/Sources/CallListNodeEntries.swift @@ -8,42 +8,9 @@ import MergeLists enum CallListNodeEntryId: Hashable { case setting(Int32) + case groupCall(PeerId) case hole(MessageIndex) case message(MessageIndex) - - var hashValue: Int { - switch self { - case let .setting(value): - return value.hashValue - case let .hole(index): - return index.hashValue - case let .message(index): - return index.hashValue - } - } - - static func ==(lhs: CallListNodeEntryId, rhs: CallListNodeEntryId) -> Bool { - switch lhs { - case let .setting(value): - if case .setting(value) = rhs { - return true - } else { - return false - } - case let .hole(index): - if case .hole(index) = rhs { - return true - } else { - return false - } - case let .message(index): - if case .message(index) = rhs { - return true - } else { - return false - } - } - } } private func areMessagesEqual(_ lhsMessage: Message, _ rhsMessage: Message) -> Bool { @@ -57,69 +24,96 @@ private func areMessagesEqual(_ lhsMessage: Message, _ rhsMessage: Message) -> B } enum CallListNodeEntry: Comparable, Identifiable { + enum SortIndex: Comparable { + case displayTab + case displayTabInfo + case groupCall(ChatListIndex) + case message(MessageIndex) + case hole(MessageIndex) + + static func <(lhs: SortIndex, rhs: SortIndex) -> Bool { + switch lhs { + case .displayTab: + return false + case .displayTabInfo: + switch rhs { + case .displayTab: + return true + default: + return false + } + case let .groupCall(lhsIndex): + switch rhs { + case .displayTab, .displayTabInfo: + return false + case let .groupCall(rhsIndex): + return lhsIndex > rhsIndex + case .message, .hole: + return true + } + case let .hole(lhsIndex): + switch rhs { + case .displayTab, .displayTabInfo, .groupCall: + return false + case let .hole(rhsIndex): + return lhsIndex < rhsIndex + case let .message(rhsIndex): + return lhsIndex < rhsIndex + } + case let .message(lhsIndex): + switch rhs { + case .displayTab, .displayTabInfo, .groupCall: + return false + case let .hole(rhsIndex): + return lhsIndex < rhsIndex + case let .message(rhsIndex): + return lhsIndex < rhsIndex + default: + return true + } + + } + } + } + case displayTab(PresentationTheme, String, Bool) case displayTabInfo(PresentationTheme, String) + case groupCall(index: ChatListIndex, peer: Peer) case messageEntry(topMessage: Message, messages: [Message], theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, editing: Bool, hasActiveRevealControls: Bool) case holeEntry(index: MessageIndex, theme: PresentationTheme) - var index: MessageIndex { + var sortIndex: SortIndex { switch self { - case .displayTab: - return MessageIndex.absoluteUpperBound() - case .displayTabInfo: - return MessageIndex.absoluteUpperBound().predecessor() - case let .messageEntry(message, _, _, _, _, _, _): - return message.index - case let .holeEntry(index, _): - return index + case .displayTab: + return .displayTab + case .displayTabInfo: + return .displayTabInfo + case let .groupCall(index, _): + return .groupCall(index) + case let .messageEntry(message, _, _, _, _, _, _): + return .message(message.index) + case let .holeEntry(index, _): + return .hole(index) } } var stableId: CallListNodeEntryId { switch self { - case .displayTab: - return .setting(0) - case .displayTabInfo: - return .setting(1) - case let .messageEntry(message, _, _, _, _, _, _): - return .message(message.index) - case let .holeEntry(index, _): - return .hole(index) + case .displayTab: + return .setting(0) + case .displayTabInfo: + return .setting(1) + case let .groupCall(_, peer): + return .groupCall(peer.id) + case let .messageEntry(message, _, _, _, _, _, _): + return .message(message.index) + case let .holeEntry(index, _): + return .hole(index) } } static func <(lhs: CallListNodeEntry, rhs: CallListNodeEntry) -> Bool { - switch lhs { - case .displayTab: - return false - case .displayTabInfo: - switch rhs { - case .displayTab: - return true - default: - return false - } - case let .holeEntry(lhsIndex, _): - switch rhs { - case let .holeEntry(rhsIndex, _): - return lhsIndex < rhsIndex - case let .messageEntry(topMessage, _, _, _, _, _, _): - return lhsIndex < topMessage.index - default: - return true - } - case let .messageEntry(lhsTopMessage, _, _, _, _, _, _): - let lhsIndex = lhsTopMessage.index - switch rhs { - case let .holeEntry(rhsIndex, _): - return lhsIndex < rhsIndex - case let .messageEntry(topMessage, _, _, _, _, _, _): - return lhsIndex < topMessage.index - default: - return true - } - - } + return lhs.sortIndex < rhs.sortIndex } static func ==(lhs: CallListNodeEntry, rhs: CallListNodeEntry) -> Bool { @@ -136,6 +130,18 @@ enum CallListNodeEntry: Comparable, Identifiable { } else { return false } + case let .groupCall(lhsIndex, lhsPeer): + if case let .groupCall(rhsIndex, rhsPeer) = rhs { + if lhsIndex != rhsIndex { + return false + } + if !lhsPeer.isEqual(rhsPeer) { + return false + } + return true + } else { + return false + } case let .messageEntry(lhsMessage, lhsMessages, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsEditing, lhsHasRevealControls): if case let .messageEntry(rhsMessage, rhsMessages, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsEditing, rhsHasRevealControls) = rhs { if lhsTheme !== rhsTheme { diff --git a/submodules/CallListUI/Sources/CallListViewTransition.swift b/submodules/CallListUI/Sources/CallListViewTransition.swift index 09f7e03c96..3fe18eec60 100644 --- a/submodules/CallListUI/Sources/CallListViewTransition.swift +++ b/submodules/CallListUI/Sources/CallListViewTransition.swift @@ -139,9 +139,11 @@ func preparedCallListNodeViewTransition(from fromView: CallListNodeView?, to toV case let .index(scrollIndex, position, directionHint, animated): var index = toView.filteredEntries.count - 1 for entry in toView.filteredEntries { - if entry.index >= scrollIndex { - scrollToItem = ListViewScrollToItem(index: index, position: position, animated: animated, curve: .Default(duration: nil), directionHint: directionHint) - break + if case let .message(messageIndex) = entry.sortIndex { + if messageIndex >= scrollIndex { + scrollToItem = ListViewScrollToItem(index: index, position: position, animated: animated, curve: .Default(duration: nil), directionHint: directionHint) + break + } } index -= 1 } @@ -149,9 +151,11 @@ func preparedCallListNodeViewTransition(from fromView: CallListNodeView?, to toV if scrollToItem == nil { var index = 0 for entry in toView.filteredEntries.reversed() { - if entry.index < scrollIndex { - scrollToItem = ListViewScrollToItem(index: index, position: position, animated: animated, curve: .Default(duration: nil), directionHint: directionHint) - break + if case let .message(messageIndex) = entry.sortIndex { + if messageIndex < scrollIndex { + scrollToItem = ListViewScrollToItem(index: index, position: position, animated: animated, curve: .Default(duration: nil), directionHint: directionHint) + break + } } index += 1 } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index b3205740fe..4d7d839852 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -702,40 +702,40 @@ public final class VoiceChatController: ViewController { if let callState = strongSelf.callState, (callState.canManageCall && !callState.adminIds.contains(peer.id)) { items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_RemovePeer, textColor: .destructive, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor) - }, action: { [weak self] _, f in - f(.dismissWithoutContent) - - guard let strongSelf = self else { - return - } - - let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme)) - var items: [ActionSheetItem] = [] - - items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: peer, chatPeer: peer, action: .removeFromGroup, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder)) - - items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - + }, action: { [weak self] c, _ in + c.dismiss(completion: { guard let strongSelf = self else { return } - - let _ = strongSelf.context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: strongSelf.context.account, peerId: strongSelf.call.peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)).start() - strongSelf.call.removedPeer(peer.id) - - strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .banned(text: strongSelf.presentationData.strings.VoiceChat_RemovedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), elevatedLayout: false, action: { _ in return false }), in: .current) - })) - actionSheet.setItemGroups([ - ActionSheetItemGroup(items: items), - ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - }) + let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme)) + var items: [ActionSheetItem] = [] + + items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: peer, chatPeer: peer, action: .removeFromGroup, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder)) + + items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.VoiceChat_RemovePeerRemove, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + + guard let strongSelf = self else { + return + } + + let _ = strongSelf.context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: strongSelf.context.account, peerId: strongSelf.call.peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)).start() + strongSelf.call.removedPeer(peer.id) + + strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .banned(text: strongSelf.presentationData.strings.VoiceChat_RemovedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), elevatedLayout: false, action: { _ in return false }), in: .current) + })) + + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: items), + ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ]) ]) - ]) - strongSelf.controller?.present(actionSheet, in: .window(.root)) + strongSelf.controller?.present(actionSheet, in: .window(.root)) + }) }))) } } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index cba2c41cb0..8a6434d980 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -502,6 +502,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } case let .groupPhoneCall(callId, accessHash, nil), let .inviteToGroupPhoneCall(callId, accessHash, _): + guard strongSelf.presentationInterfaceState.activeGroupCallInfo?.activeCall.id == callId else { + return true + } + let peerId = message.id.peerId let callResult = strongSelf.context.sharedContext.callManager?.joinGroupCall(context: strongSelf.context, peerId: peerId, initialCall: CachedChannelData.ActiveCall(id: callId, accessHash: accessHash), endCurrentIfAny: false, sourcePanel: nil) if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {