This commit is contained in:
Isaac
2025-11-07 18:08:34 +08:00
parent a05ef5e022
commit 4616f0833c
9 changed files with 321 additions and 221 deletions

View File

@@ -240,6 +240,7 @@ public struct PresentationGroupCallState: Equatable {
public var isVideoWatchersLimitReached: Bool
public var isMyVideoActive: Bool
public var isUnifiedStream: Bool
public var defaultSendAs: EnginePeer.Id?
public init(
myPeerId: EnginePeer.Id,
@@ -260,7 +261,8 @@ public struct PresentationGroupCallState: Equatable {
isVideoEnabled: Bool,
isVideoWatchersLimitReached: Bool,
isMyVideoActive: Bool,
isUnifiedStream: Bool
isUnifiedStream: Bool,
defaultSendAs: EnginePeer.Id?
) {
self.myPeerId = myPeerId
self.networkState = networkState
@@ -281,6 +283,7 @@ public struct PresentationGroupCallState: Equatable {
self.isVideoWatchersLimitReached = isVideoWatchersLimitReached
self.isMyVideoActive = isMyVideoActive
self.isUnifiedStream = isUnifiedStream
self.defaultSendAs = defaultSendAs
}
}

View File

@@ -40,7 +40,8 @@ private extension PresentationGroupCallState {
isVideoEnabled: false,
isVideoWatchersLimitReached: false,
isMyVideoActive: false,
isUnifiedStream: false
isUnifiedStream: false,
defaultSendAs: nil
)
}
}
@@ -1565,6 +1566,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
isVideoEnabled: callInfo.isVideoEnabled,
unmutedVideoLimit: callInfo.unmutedVideoLimit,
isStream: callInfo.isStream,
sendPaidMessagesStars: self.stateValue.sendPaidMessageStars,
defaultSendAs: self.stateValue.defaultSendAs,
version: 0
),
previousServiceState: nil,
@@ -2282,19 +2285,23 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
if case let .established(callInfo, _, _, _, initialState) = internalState {
self.summaryInfoState.set(.single(SummaryInfoState(info: callInfo)))
self.stateValue.canManageCall = initialState.isCreator || initialState.adminIds.contains(self.accountContext.account.peerId)
if self.stateValue.canManageCall && initialState.defaultParticipantsAreMuted.canChange {
self.stateValue.defaultParticipantMuteState = initialState.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
var stateValue = self.stateValue
stateValue.canManageCall = initialState.isCreator || initialState.adminIds.contains(self.accountContext.account.peerId)
if stateValue.canManageCall && initialState.defaultParticipantsAreMuted.canChange {
stateValue.defaultParticipantMuteState = initialState.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
}
if self.stateValue.recordingStartTimestamp != initialState.recordingStartTimestamp {
self.stateValue.recordingStartTimestamp = initialState.recordingStartTimestamp
if stateValue.recordingStartTimestamp != initialState.recordingStartTimestamp {
stateValue.recordingStartTimestamp = initialState.recordingStartTimestamp
}
if self.stateValue.title != initialState.title {
self.stateValue.title = initialState.title
if stateValue.title != initialState.title {
stateValue.title = initialState.title
}
if self.stateValue.scheduleTimestamp != initialState.scheduleTimestamp {
self.stateValue.scheduleTimestamp = initialState.scheduleTimestamp
if stateValue.scheduleTimestamp != initialState.scheduleTimestamp {
stateValue.scheduleTimestamp = initialState.scheduleTimestamp
}
stateValue.defaultSendAs = initialState.defaultSendAs
self.stateValue = stateValue
let accountContext = self.accountContext
let peerId = self.peerId
@@ -2667,21 +2674,24 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.membersValue = members
self.stateValue.adminIds = adminIds
var stateValue = self.stateValue
stateValue.adminIds = adminIds
self.stateValue.canManageCall = state.isCreator || adminIds.contains(self.accountContext.account.peerId)
if (state.isCreator || self.stateValue.adminIds.contains(self.accountContext.account.peerId)) && state.defaultParticipantsAreMuted.canChange {
self.stateValue.defaultParticipantMuteState = state.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
stateValue.canManageCall = state.isCreator || adminIds.contains(self.accountContext.account.peerId)
if (state.isCreator || stateValue.adminIds.contains(self.accountContext.account.peerId)) && state.defaultParticipantsAreMuted.canChange {
stateValue.defaultParticipantMuteState = state.defaultParticipantsAreMuted.isMuted ? .muted : .unmuted
}
self.stateValue.messagesAreEnabled = state.messagesAreEnabled.isEnabled
self.stateValue.canEnableMessages = state.messagesAreEnabled.canChange
self.stateValue.sendPaidMessageStars = state.messagesAreEnabled.sendPaidMessagesStars
self.stateValue.recordingStartTimestamp = state.recordingStartTimestamp
self.stateValue.title = state.title
self.stateValue.scheduleTimestamp = state.scheduleTimestamp
self.stateValue.isVideoEnabled = state.isVideoEnabled && otherParticipantsWithVideo < state.unmutedVideoLimit
self.stateValue.isVideoWatchersLimitReached = videoWatchingParticipants >= configuration.videoParticipantsMaxCount
self.stateValue.isUnifiedStream = state.isStream
stateValue.messagesAreEnabled = state.messagesAreEnabled.isEnabled
stateValue.canEnableMessages = state.messagesAreEnabled.canChange
stateValue.sendPaidMessageStars = state.messagesAreEnabled.sendPaidMessagesStars
stateValue.recordingStartTimestamp = state.recordingStartTimestamp
stateValue.title = state.title
stateValue.scheduleTimestamp = state.scheduleTimestamp
stateValue.isVideoEnabled = state.isVideoEnabled && otherParticipantsWithVideo < state.unmutedVideoLimit
stateValue.isVideoWatchersLimitReached = videoWatchingParticipants >= configuration.videoParticipantsMaxCount
stateValue.isUnifiedStream = state.isStream
stateValue.defaultSendAs = state.defaultSendAs
self.stateValue = stateValue
self.summaryInfoState.set(.single(SummaryInfoState(info: GroupCallInfo(
id: callInfo.id,

View File

@@ -1220,7 +1220,8 @@ final class VideoChatScreenComponent: Component {
isVideoEnabled: true,
isVideoWatchersLimitReached: false,
isMyVideoActive: false,
isUnifiedStream: false
isUnifiedStream: false,
defaultSendAs: nil
)
return .single((callState, invitedPeers.compactMap({ peer -> VideoChatScreenComponent.InvitedPeer? in

View File

@@ -595,6 +595,8 @@ func _internal_getGroupCallParticipants(account: Account, reference: InternalGro
isVideoEnabled: isVideoEnabled,
unmutedVideoLimit: unmutedVideoLimit,
isStream: isStream,
sendPaidMessagesStars: nil,
defaultSendAs: nil,
version: version
)
}
@@ -1479,6 +1481,8 @@ public final class GroupCallParticipantsContext {
isVideoEnabled: Bool,
unmutedVideoLimit: Int,
isStream: Bool,
sendPaidMessagesStars: Int64?,
defaultSendAs: PeerId?,
version: Int32
) {
self.participants = participants
@@ -1496,6 +1500,8 @@ public final class GroupCallParticipantsContext {
self.isVideoEnabled = isVideoEnabled
self.unmutedVideoLimit = unmutedVideoLimit
self.isStream = isStream
self.sendPaidMessagesStars = sendPaidMessagesStars
self.defaultSendAs = defaultSendAs
self.version = version
}
}
@@ -1871,6 +1877,8 @@ public final class GroupCallParticipantsContext {
isVideoEnabled: strongSelf.stateValue.state.isVideoEnabled,
unmutedVideoLimit: strongSelf.stateValue.state.unmutedVideoLimit,
isStream: strongSelf.stateValue.state.isStream,
sendPaidMessagesStars: strongSelf.stateValue.state.sendPaidMessagesStars,
defaultSendAs: strongSelf.stateValue.state.defaultSendAs,
version: strongSelf.stateValue.state.version
),
overlayState: strongSelf.stateValue.overlayState,
@@ -2102,6 +2110,8 @@ public final class GroupCallParticipantsContext {
isVideoEnabled: strongSelf.stateValue.state.isVideoEnabled,
unmutedVideoLimit: strongSelf.stateValue.state.unmutedVideoLimit,
isStream: strongSelf.stateValue.state.isStream,
sendPaidMessagesStars: strongSelf.stateValue.state.sendPaidMessagesStars,
defaultSendAs: strongSelf.stateValue.state.defaultSendAs,
version: strongSelf.stateValue.state.version
),
overlayState: strongSelf.stateValue.overlayState,
@@ -2328,6 +2338,8 @@ public final class GroupCallParticipantsContext {
let isVideoEnabled = strongSelf.stateValue.state.isVideoEnabled
let isStream = strongSelf.stateValue.state.isStream
let unmutedVideoLimit = strongSelf.stateValue.state.unmutedVideoLimit
let sendPaidMessagesStars = strongSelf.stateValue.state.sendPaidMessagesStars
let defaultSendAs = strongSelf.stateValue.state.defaultSendAs
updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) })
@@ -2348,6 +2360,8 @@ public final class GroupCallParticipantsContext {
isVideoEnabled: isVideoEnabled,
unmutedVideoLimit: unmutedVideoLimit,
isStream: isStream,
sendPaidMessagesStars: sendPaidMessagesStars,
defaultSendAs: defaultSendAs,
version: update.version
),
overlayState: updatedOverlayState,
@@ -4300,7 +4314,7 @@ public final class GroupCallMessagesContext {
flags |= 1 << 0
}
var sendAs: Api.InputPeer?
if fromId != self.account.peerId {
if fromId != self.account.peerId || self.isLiveStream {
guard let fromPeer else {
return
}
@@ -4364,7 +4378,7 @@ public final class GroupCallMessagesContext {
var flags: Int32 = 0
flags |= 1 << 0
var sendAs: Api.InputPeer?
if pendingSendStars.fromPeer.id != self.account.peerId {
if pendingSendStars.fromPeer.id != self.account.peerId || self.isLiveStream {
sendAs = apiInputPeer(pendingSendStars.fromPeer)
}
if sendAs != nil {

View File

@@ -1531,10 +1531,11 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
shouldDisplayMenuButton = true
}
var displaySendAsAvatarButton = false
let mediaRecordingState = interfaceState.inputTextPanelState.mediaRecordingState
if let sendAsPeers = interfaceState.sendAsPeers, !sendAsPeers.isEmpty && interfaceState.editMessageState == nil {
menuButtonExpanded = false
self.sendAsAvatarButtonNode.isHidden = false
displaySendAsAvatarButton = true
var currentPeer = sendAsPeers.first(where: { $0.peer.id == interfaceState.currentSendAsPeerId})?.peer
if currentPeer == nil {
@@ -1554,9 +1555,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
break
}
}
self.sendAsAvatarButtonNode.isHidden = true
} else {
self.sendAsAvatarButtonNode.isHidden = true
}
if mediaRecordingState != nil || interfaceState.interfaceState.mediaDraftState != nil {
hasMenuButton = false
@@ -2968,11 +2966,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
}
transition.updateFrame(node: self.textPlaceholderNode, frame: textPlaceholderFrame)
let sendAsButtonFrame = CGRect(origin: CGPoint(x: 3.0, y: textInputContainerBackgroundFrame.height - 3.0 - 34.0), size: CGSize(width: 34.0, height: 34.0))
let sendAsAvatarButtonAlpha: CGFloat = audioRecordingItemsAlpha * (displaySendAsAvatarButton ? 1.0 : 0.0)
transition.updatePosition(node: self.sendAsAvatarButtonNode, position: sendAsButtonFrame.center)
transition.updateBounds(node: self.sendAsAvatarButtonNode, bounds: CGRect(origin: CGPoint(), size: sendAsButtonFrame.size))
transition.updateAlpha(layer: self.sendAsAvatarButtonNode.layer, alpha: audioRecordingItemsAlpha)
transition.updateTransformScale(layer: self.sendAsAvatarButtonNode.layer, scale: audioRecordingItemsAlpha == 0.0 ? 0.001 : 1.0)
transition.updateAlpha(layer: self.sendAsAvatarButtonNode.layer, alpha: sendAsAvatarButtonAlpha)
transition.updateTransformScale(layer: self.sendAsAvatarButtonNode.layer, scale: sendAsAvatarButtonAlpha == 0.0 ? 0.001 : 1.0)
transition.updateFrame(node: self.sendAsAvatarContainerNode, frame: CGRect(origin: CGPoint(), size: sendAsButtonFrame.size))
transition.updateFrame(node: self.sendAsAvatarReferenceNode, frame: CGRect(origin: CGPoint(), size: sendAsButtonFrame.size))
transition.updatePosition(node: self.sendAsAvatarNode, position: CGRect(origin: CGPoint(), size: sendAsButtonFrame.size).center)

View File

@@ -118,8 +118,9 @@ final class StoryItemContentComponent: Component {
var minMessagePrice: Int64?
var starStats: StarStats?
var isAdmin: Bool
var defaultSendAs: EnginePeer.Id?
init(isExpanded: Bool, isEmpty: Bool, hasUnseenMessages: Bool, areMessagesEnabled: Bool, minMessagePrice: Int64?, starStats: StarStats?, isAdmin: Bool) {
init(isExpanded: Bool, isEmpty: Bool, hasUnseenMessages: Bool, areMessagesEnabled: Bool, minMessagePrice: Int64?, starStats: StarStats?, isAdmin: Bool, defaultSendAs: EnginePeer.Id?) {
self.isExpanded = isExpanded
self.isEmpty = isEmpty
self.hasUnseenMessages = hasUnseenMessages
@@ -127,6 +128,7 @@ final class StoryItemContentComponent: Component {
self.minMessagePrice = minMessagePrice
self.starStats = starStats
self.isAdmin = isAdmin
self.defaultSendAs = defaultSendAs
}
}
@@ -134,12 +136,14 @@ final class StoryItemContentComponent: Component {
var areMessagesEnabled: Bool
var minMessagePrice: Int64?
var isAdmin: Bool
var defaultSendAs: EnginePeer.Id?
var isUnifiedStream: Bool
init(areMessagesEnabled: Bool, minMessagePrice: Int64?, isAdmin: Bool, isUnifiedStream: Bool) {
init(areMessagesEnabled: Bool, minMessagePrice: Int64?, isAdmin: Bool, defaultSendAs: EnginePeer.Id?, isUnifiedStream: Bool) {
self.areMessagesEnabled = areMessagesEnabled
self.minMessagePrice = minMessagePrice
self.isAdmin = isAdmin
self.defaultSendAs = defaultSendAs
self.isUnifiedStream = isUnifiedStream
}
}
@@ -229,7 +233,8 @@ final class StoryItemContentComponent: Component {
areMessagesEnabled: mediaStreamCallState?.areMessagesEnabled ?? false,
minMessagePrice: mediaStreamCallState?.minMessagePrice,
starStats: starStats,
isAdmin: mediaStreamCallState?.isAdmin ?? false
isAdmin: mediaStreamCallState?.isAdmin ?? false,
defaultSendAs: mediaStreamCallState?.defaultSendAs
)
}
@@ -1116,6 +1121,7 @@ final class StoryItemContentComponent: Component {
areMessagesEnabled: state.messagesAreEnabled,
minMessagePrice: state.sendPaidMessageStars,
isAdmin: state.canManageCall,
defaultSendAs: state.defaultSendAs,
isUnifiedStream: state.isUnifiedStream
)
if self.mediaStreamCallState != mappedState {

View File

@@ -103,7 +103,9 @@ final class StoryItemLoadingEffectView: UIView {
}
func update(size: CGSize, transition: ComponentTransition) {
if self.backgroundView.bounds.size != size {
let backgroundSize = CGSize(width: self.gradientWidth, height: size.height)
if self.backgroundView.bounds.size != backgroundSize {
self.backgroundView.layer.removeAllAnimations()
if !self.hasCustomBorder {
@@ -115,7 +117,7 @@ final class StoryItemLoadingEffectView: UIView {
}
}
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: -self.gradientWidth, y: 0.0), size: CGSize(width: self.gradientWidth, height: size.height)))
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: -self.gradientWidth, y: 0.0), size: backgroundSize))
transition.setFrame(view: self.borderContainerView, frame: CGRect(origin: CGPoint(), size: size))
transition.setFrame(view: self.borderGradientView, frame: CGRect(origin: CGPoint(x: -self.gradientWidth, y: 0.0), size: CGSize(width: self.gradientWidth, height: size.height)))

View File

@@ -3004,7 +3004,16 @@ public final class StoryItemSetContainerComponent: Component {
}
}
sendAsConfiguration = self.sendMessageContext.currentSendAsPeer.flatMap { value in
var sendAsPeer: SendAsPeer?
if let currentSendAsPeer = self.sendMessageContext.currentSendAsPeer {
sendAsPeer = currentSendAsPeer
} else {
sendAsPeer = liveChatStateValue.defaultSendAs.flatMap { defaultSendAs in
return self.sendMessageContext.sendAsData?.availablePeers.first(where: { $0.peer.id == defaultSendAs })
}
}
sendAsConfiguration = sendAsPeer.flatMap { value in
return MessageInputPanelComponent.SendAsConfiguration(
currentPeer: EnginePeer(value.peer),
subscriberCount: value.subscribers.flatMap(Int.init),
@@ -6307,8 +6316,14 @@ public final class StoryItemSetContainerComponent: Component {
return .complete()
}
var isLiveStream = false
if case .liveStream = component.slice.item.storyItem.media {
isLiveStream = true
}
var items: [ContextMenuItem] = []
if !isLiveStream {
items.append(.action(ContextMenuActionItem(text: component.strings.Stories_MenuAddToAlbum, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddToFolder"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, f in
guard let self, let c else {
f(.default)
@@ -6403,6 +6418,7 @@ public final class StoryItemSetContainerComponent: Component {
c.pushItems(items: .single(ContextController.Items(content: .list(items))))
}
})))
}
if case .file = component.slice.item.storyItem.media {
var speedValue: String = presentationData.strings.PlaybackSpeed_Normal
@@ -6466,6 +6482,7 @@ public final class StoryItemSetContainerComponent: Component {
self.openItemPrivacySettings()
})))
if !isLiveStream {
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_Edit, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
@@ -6553,6 +6570,7 @@ public final class StoryItemSetContainerComponent: Component {
}
})))
}
}
if component.slice.item.storyItem.isPublic && (component.slice.effectivePeer.addressName != nil || !component.slice.effectivePeer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in
@@ -6645,6 +6663,11 @@ public final class StoryItemSetContainerComponent: Component {
return .complete()
}
var isLiveStream = false
if case .liveStream = component.slice.item.storyItem.media {
isLiveStream = true
}
var items: [ContextMenuItem] = []
if case .file = component.slice.item.storyItem.media {
var speedValue: String = presentationData.strings.PlaybackSpeed_Normal
@@ -6676,7 +6699,7 @@ public final class StoryItemSetContainerComponent: Component {
items.append(.separator)
}
if (component.slice.item.storyItem.isMy && channel.hasPermission(.postStories)) || channel.hasPermission(.editStories) {
if !isLiveStream && ((component.slice.item.storyItem.isMy && channel.hasPermission(.postStories)) || channel.hasPermission(.editStories)) {
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_Edit, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
@@ -6706,7 +6729,7 @@ public final class StoryItemSetContainerComponent: Component {
items.append(.separator)
}
if channel.hasPermission(.editStories) {
if !isLiveStream && channel.hasPermission(.editStories) {
items.append(.action(ContextMenuActionItem(text: component.slice.item.storyItem.isPinned ? component.strings.Story_Context_RemoveFromChannel : component.strings.Story_Context_SaveToChannel, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: component.slice.item.storyItem.isPinned ? "Stories/Context Menu/Unpin" : "Stories/Context Menu/Pin"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
@@ -6746,7 +6769,7 @@ public final class StoryItemSetContainerComponent: Component {
})))
}
if component.slice.additionalPeerData.canViewStats {
if !isLiveStream && component.slice.additionalPeerData.canViewStats {
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_ViewStats, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Statistics"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, a in
@@ -6768,6 +6791,7 @@ public final class StoryItemSetContainerComponent: Component {
})))
}
if !isLiveStream {
let saveText: String = component.strings.Story_Context_SaveToGallery
items.append(.action(ContextMenuActionItem(text: saveText, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.contextMenu.primaryColor)
@@ -6779,6 +6803,7 @@ public final class StoryItemSetContainerComponent: Component {
}
self.requestSave()
})))
}
if component.slice.item.storyItem.isPublic && (component.slice.effectivePeer.addressName != nil || !component.slice.effectivePeer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in

View File

@@ -107,7 +107,17 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
var currentLiveStreamStarsIsActive: Bool = false
var currentLiveStreamStarsIsActiveTimer: Foundation.Timer?
var sendAsData: (isPremium: Bool, availablePeers: [SendAsPeer])?
struct SendAsData: Equatable {
var isPremium: Bool
var availablePeers: [SendAsPeer]
init(isPremium: Bool, availablePeers: [SendAsPeer]) {
self.isPremium = isPremium
self.availablePeers = availablePeers
}
}
var sendAsData: SendAsData?
var currentSendAsPeer: SendAsPeer?
var isSelectingSendAsPeer: Bool = false
var sendAsDisposable: Disposable?
@@ -244,26 +254,16 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
availablePeers.append(peer)
}
self.sendAsData = (
let sendAsData = SendAsData(
isPremium: isPremium,
availablePeers: availablePeers
)
if availablePeers.count > 1 {
if self.currentSendAsPeer == nil {
self.currentSendAsPeer = availablePeers.first
if self.sendAsData != sendAsData {
self.sendAsData = sendAsData
if !view.isUpdatingComponent {
view.state?.updated(transition: .spring(duration: 0.4))
}
}
} else {
if self.currentSendAsPeer != nil {
self.currentSendAsPeer = nil
if !view.isUpdatingComponent {
view.state?.updated(transition: .spring(duration: 0.4))
}
}
}
})
}
}
@@ -684,6 +684,7 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
var sendPaidMessageStars = self.currentLiveStreamMessageStars
var isAdmin = false
var sendAsPeer: SendAsPeer?
if let visibleItemView = view.visibleItems[component.slice.item.id]?.view.view as? StoryItemContentComponent.View {
if let liveChatStateValue = visibleItemView.liveChatState {
if let minMessagePrice = liveChatStateValue.minMessagePrice {
@@ -696,6 +697,14 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
}
}
isAdmin = liveChatStateValue.isAdmin
if let currentSendAsPeer = self.currentSendAsPeer {
sendAsPeer = currentSendAsPeer
} else {
sendAsPeer = liveChatStateValue.defaultSendAs.flatMap { defaultSendAs in
return self.sendAsData?.availablePeers.first(where: { $0.peer.id == defaultSendAs })
}
}
}
}
@@ -758,7 +767,7 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
let entities = generateChatInputTextEntities(text)
call.sendMessage(fromId: self.currentSendAsPeer?.peer.id, isAdmin: isAdmin, text: text.string, entities: entities, paidStars: sendPaidMessageStars?.value)
call.sendMessage(fromId: sendAsPeer?.peer.id, isAdmin: isAdmin, text: text.string, entities: entities, paidStars: sendPaidMessageStars?.value)
component.storyItemSharedState.replyDrafts.removeValue(forKey: StoryId(peerId: peerId, id: focusedItem.storyItem.id))
inputPanelView.clearSendMessageInput(updateState: true)
@@ -3991,6 +4000,7 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
var topPeers: [ReactionsMessageAttribute.TopPeer] = []
var minAmount: Int64 = 1
var sendAsPeer: SendAsPeer?
if let visibleItemView = view.visibleItems[component.slice.item.id]?.view.view as? StoryItemContentComponent.View {
if let topItems = visibleItemView.liveChatState?.starStats?.topItems {
topPeers = topItems.map { item -> ReactionsMessageAttribute.TopPeer in
@@ -4007,12 +4017,20 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
if let minMessagePrice = visibleItemView.liveChatState?.minMessagePrice {
minAmount = minMessagePrice
}
if let currentSendAsPeer = self.currentSendAsPeer {
sendAsPeer = currentSendAsPeer
} else {
sendAsPeer = visibleItemView.liveChatState?.defaultSendAs.flatMap { defaultSendAs in
return self.sendAsData?.availablePeers.first(where: { $0.peer.id == defaultSendAs })
}
}
}
let initialData = await ChatSendStarsScreen.initialData(
context: component.context,
peerId: peerId,
myPeer: (self.currentSendAsPeer?.peer).flatMap(EnginePeer.init),
myPeer: (sendAsPeer?.peer).flatMap(EnginePeer.init),
reactSubject: .liveStream(peerId: peerId, storyId: focusedItem.storyItem.id, minAmount: Int(minAmount), liveChatMessageParams: LiveChatMessageParams(appConfig: component.context.currentAppConfiguration.with({ $0 }))),
topPeers: topPeers,
completion: { [weak self, weak view] amount, _, _, _ in
@@ -4245,17 +4263,38 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
guard let call = itemView.mediaStreamCall else {
return
}
var sendAsPeer: SendAsPeer?
if let liveChatStateValue = itemView.liveChatState {
isAdmin = liveChatStateValue.isAdmin
if let currentSendAsPeer = self.currentSendAsPeer {
sendAsPeer = currentSendAsPeer
} else {
sendAsPeer = liveChatStateValue.defaultSendAs.flatMap { defaultSendAs in
return self.sendAsData?.availablePeers.first(where: { $0.peer.id == defaultSendAs })
}
}
}
call.sendStars(fromId: self.currentSendAsPeer?.peer.id, isAdmin: isAdmin, amount: Int64(count), delay: delay)
call.sendStars(fromId: sendAsPeer?.peer.id, isAdmin: isAdmin, amount: Int64(count), delay: delay)
}
func openSendAsSelection(view: StoryItemSetContainerComponent.View, sourceView: UIView, gesture: ContextGesture?) {
guard let component = view.component, let sendAsData = self.sendAsData, let currentSendAsPeer = self.currentSendAsPeer, let controller = component.controller() else {
guard let component = view.component, let sendAsData = self.sendAsData, let controller = component.controller() else {
return
}
guard let visibleItemView = view.visibleItems[component.slice.item.id]?.view.view as? StoryItemContentComponent.View else {
return
}
var currentSendAsPeer: SendAsPeer?
if let currentSendAsPeerValue = self.currentSendAsPeer {
currentSendAsPeer = currentSendAsPeerValue
} else {
currentSendAsPeer = visibleItemView.liveChatState?.defaultSendAs.flatMap { defaultSendAs in
return self.sendAsData?.availablePeers.first(where: { $0.peer.id == defaultSendAs })
}
}
let focusedItem = component.slice.item
guard let peerId = focusedItem.peerId else {
@@ -4269,7 +4308,7 @@ final class StoryItemSetContainerSendMessage: @unchecked(Sendable) {
context: component.context,
chatPeerId: peerId,
peers: sendAsData.availablePeers,
selectedPeerId: currentSendAsPeer.peer.id,
selectedPeerId: currentSendAsPeer?.peer.id,
isPremium: isPremium,
action: { [weak self, weak view] peer in
guard let self, let view else {