mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
UI improvements
This commit is contained in:
parent
2f46baf863
commit
05b4d6f3ca
@ -46,15 +46,18 @@ public final class PagerComponentChildEnvironment: Equatable {
|
||||
public let containerInsets: UIEdgeInsets
|
||||
public let onChildScrollingUpdate: (ContentScrollingUpdate) -> Void
|
||||
public let onWantsExclusiveModeUpdated: (Bool) -> Void
|
||||
public let scrollToTop: ActionSlot<Void>
|
||||
|
||||
init(
|
||||
containerInsets: UIEdgeInsets,
|
||||
onChildScrollingUpdate: @escaping (ContentScrollingUpdate) -> Void,
|
||||
onWantsExclusiveModeUpdated: @escaping (Bool) -> Void
|
||||
onWantsExclusiveModeUpdated: @escaping (Bool) -> Void,
|
||||
scrollToTop: ActionSlot<Void>
|
||||
) {
|
||||
self.containerInsets = containerInsets
|
||||
self.onChildScrollingUpdate = onChildScrollingUpdate
|
||||
self.onWantsExclusiveModeUpdated = onWantsExclusiveModeUpdated
|
||||
self.scrollToTop = scrollToTop
|
||||
}
|
||||
|
||||
public static func ==(lhs: PagerComponentChildEnvironment, rhs: PagerComponentChildEnvironment) -> Bool {
|
||||
@ -296,6 +299,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
||||
var scrollingPanelOffsetToBottomEdge: CGFloat = .greatestFiniteMagnitude
|
||||
var scrollingPanelOffsetFraction: CGFloat = 0.0
|
||||
var wantsExclusiveMode: Bool = false
|
||||
let scrollToTop = ActionSlot<Void>()
|
||||
|
||||
init(view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>) {
|
||||
self.view = view
|
||||
@ -368,7 +372,7 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
||||
case .began:
|
||||
self.paneTransitionGestureState = PaneTransitionGestureState()
|
||||
case .changed:
|
||||
if let centralId = self.centralId, let component = self.component, let centralIndex = component.contents.firstIndex(where: { $0.id == centralId }), var paneTransitionGestureState = self.paneTransitionGestureState, self.bounds.width > 0.0 {
|
||||
if let centralId = self.centralId, let component = self.component, let centralIndex = component.contents.firstIndex(where: { $0.id == centralId }), let centralView = self.contentViews[centralId], !centralView.wantsExclusiveMode, var paneTransitionGestureState = self.paneTransitionGestureState, self.bounds.width > 0.0 {
|
||||
var fraction = recognizer.translation(in: self).x / self.bounds.width
|
||||
if centralIndex <= 0 {
|
||||
fraction = min(0.0, fraction)
|
||||
@ -463,6 +467,8 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
||||
if self.isTopPanelExpanded {
|
||||
updateTopPanelExpanded = true
|
||||
}
|
||||
} else {
|
||||
self.contentViews[id]?.scrollToTop.invoke(Void())
|
||||
}
|
||||
|
||||
if updateTopPanelExpanded {
|
||||
@ -843,7 +849,8 @@ public final class PagerComponent<ChildEnvironmentType: Equatable, TopPanelEnvir
|
||||
return
|
||||
}
|
||||
strongSelf.onChildWantsExclusiveModeUpdated(id: id, wantsExclusiveMode: wantsExclusiveMode)
|
||||
}
|
||||
},
|
||||
scrollToTop: contentView.scrollToTop
|
||||
)
|
||||
|
||||
let _ = contentView.view.update(
|
||||
|
@ -228,7 +228,7 @@ static int32_t fixedTimeDifferenceValue = 0;
|
||||
_isTestingEnvironment = isTestingEnvironment;
|
||||
_useTempAuthKeys = useTempAuthKeys;
|
||||
#if DEBUG
|
||||
_tempKeyExpiration = 1 * 60 * 60;
|
||||
_tempKeyExpiration = 10 * 60;
|
||||
#else
|
||||
_tempKeyExpiration = 24 * 60 * 60;
|
||||
#endif
|
||||
|
@ -552,206 +552,435 @@ public final class ShareController: ViewController {
|
||||
})
|
||||
}
|
||||
self.controllerNode.share = { [weak self] text, peerIds, topicIds, showNames, silently in
|
||||
guard let strongSelf = self else {
|
||||
guard let self else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var shareSignals: [Signal<[MessageId?], NoError>] = []
|
||||
var subject = strongSelf.subject
|
||||
if let segmentedValues = strongSelf.segmentedValues {
|
||||
let selectedValue = segmentedValues[strongSelf.controllerNode.selectedSegmentedIndex]
|
||||
subject = selectedValue.subject
|
||||
}
|
||||
|
||||
func transformMessages(_ messages: [EnqueueMessage], showNames: Bool, silently: Bool) -> [EnqueueMessage] {
|
||||
return messages.map { message in
|
||||
return message.withUpdatedAttributes({ attributes in
|
||||
var attributes = attributes
|
||||
if !showNames {
|
||||
attributes.append(ForwardOptionsMessageAttribute(hideNames: true, hideCaptions: false))
|
||||
}
|
||||
if silently {
|
||||
attributes.append(NotificationInfoMessageAttribute(flags: .muted))
|
||||
}
|
||||
return attributes
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch subject {
|
||||
case let .url(url):
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
} else {
|
||||
messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .text(string):
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .quote(string, url):
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
|
||||
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .image(representations):
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .media(mediaReference):
|
||||
var sendTextAsCaption = false
|
||||
if mediaReference.media is TelegramMediaImage || mediaReference.media is TelegramMediaFile {
|
||||
sendTextAsCaption = true
|
||||
return self.currentContext.engine.data.get(EngineDataMap(
|
||||
peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:))
|
||||
))
|
||||
|> castError(ShareControllerError.self)
|
||||
|> mapToSignal { [weak self] peers -> Signal<ShareState, ShareControllerError> in
|
||||
guard let strongSelf = self else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
var shareSignals: [Signal<[MessageId?], NoError>] = []
|
||||
var subject = strongSelf.subject
|
||||
if let segmentedValues = strongSelf.segmentedValues {
|
||||
let selectedValue = segmentedValues[strongSelf.controllerNode.selectedSegmentedIndex]
|
||||
subject = selectedValue.subject
|
||||
}
|
||||
|
||||
func transformMessages(_ messages: [EnqueueMessage], showNames: Bool, silently: Bool) -> [EnqueueMessage] {
|
||||
return messages.map { message in
|
||||
return message.withUpdatedAttributes({ attributes in
|
||||
var attributes = attributes
|
||||
if !showNames {
|
||||
attributes.append(ForwardOptionsMessageAttribute(hideNames: true, hideCaptions: false))
|
||||
}
|
||||
if silently {
|
||||
attributes.append(NotificationInfoMessageAttribute(flags: .muted))
|
||||
}
|
||||
return attributes
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
switch subject {
|
||||
case let .url(url):
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var banSendText = false
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendText) != nil {
|
||||
banSendText = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendText) {
|
||||
banSendText = true
|
||||
}
|
||||
|
||||
if banSendText {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
} else {
|
||||
messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .text(string):
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var banSendText = false
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendText) != nil {
|
||||
banSendText = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendText) {
|
||||
banSendText = true
|
||||
}
|
||||
|
||||
if banSendText {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .quote(string, url):
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var banSendText = false
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendText) != nil {
|
||||
banSendText = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendText) {
|
||||
banSendText = true
|
||||
}
|
||||
|
||||
if banSendText {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
|
||||
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .image(representations):
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var banSendPhotos = false
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendPhotos) != nil {
|
||||
banSendPhotos = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendPhotos) {
|
||||
banSendPhotos = true
|
||||
}
|
||||
|
||||
if banSendPhotos {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .media(mediaReference):
|
||||
var sendTextAsCaption = false
|
||||
if mediaReference.media is TelegramMediaImage || mediaReference.media is TelegramMediaFile {
|
||||
sendTextAsCaption = true
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty && !sendTextAsCaption {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var banSendType = false
|
||||
if mediaReference.media is TelegramMediaImage {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendPhotos) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendPhotos) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if let file = mediaReference.media as? TelegramMediaFile {
|
||||
if file.isSticker || file.isAnimated {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendStickers) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendStickers) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isInstantVideo {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendInstantVideos) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendInstantVideos) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isVoice {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendVoice) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendVoice) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isMusic {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendMusic) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendMusic) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isVideo {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendVideos) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendVideos) {
|
||||
banSendType = true
|
||||
}
|
||||
} else {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendFiles) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendFiles) {
|
||||
banSendType = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if banSendType {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty && !sendTextAsCaption {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .mapMedia(media):
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
case let .mapMedia(media):
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var banSendText = false
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendText) != nil {
|
||||
banSendText = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendText) {
|
||||
banSendText = true
|
||||
}
|
||||
|
||||
if banSendText {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
case let .messages(messages):
|
||||
for peerId in peerIds {
|
||||
guard let maybePeer = peers[peerId], let peer = maybePeer else {
|
||||
continue
|
||||
}
|
||||
|
||||
var replyToMessageId: MessageId?
|
||||
var threadId: Int64?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
threadId = topicId
|
||||
}
|
||||
|
||||
var messagesToEnqueue: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
var banSendText = false
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendText) != nil {
|
||||
banSendText = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendText) {
|
||||
banSendText = true
|
||||
}
|
||||
|
||||
if banSendText {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
for message in messages {
|
||||
for media in message.media {
|
||||
var banSendType = false
|
||||
if media is TelegramMediaImage {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendPhotos) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendPhotos) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
if file.isSticker || file.isAnimated {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendStickers) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendStickers) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isInstantVideo {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendInstantVideos) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendInstantVideos) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isVoice {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendVoice) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendVoice) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isMusic {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendMusic) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendMusic) {
|
||||
banSendType = true
|
||||
}
|
||||
} else if file.isVideo {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendVideos) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendVideos) {
|
||||
banSendType = true
|
||||
}
|
||||
} else {
|
||||
if case let .channel(channel) = peer, channel.hasBannedPermission(.banSendFiles) != nil {
|
||||
banSendType = true
|
||||
} else if case let .legacyGroup(group) = peer, group.hasBannedPermission(.banSendFiles) {
|
||||
banSendType = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if banSendType {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
messagesToEnqueue.append(.forward(source: message.id, threadId: threadId, grouping: .auto, attributes: [], correlationId: nil))
|
||||
}
|
||||
messagesToEnqueue = transformMessages(messagesToEnqueue, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .messages(messages):
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: MessageId?
|
||||
var threadId: Int64?
|
||||
if let topicId = topicIds[peerId] {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: topicId))
|
||||
threadId = topicId
|
||||
}
|
||||
|
||||
var messagesToEnqueue: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
for message in messages {
|
||||
messagesToEnqueue.append(.forward(source: message.id, threadId: threadId, grouping: .auto, attributes: [], correlationId: nil))
|
||||
}
|
||||
messagesToEnqueue = transformMessages(messagesToEnqueue, showNames: showNames, silently: silently)
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue))
|
||||
}
|
||||
case let .fromExternal(f):
|
||||
return f(peerIds, topicIds, text, strongSelf.currentAccount, silently)
|
||||
|> map { state -> ShareState in
|
||||
switch state {
|
||||
case let .fromExternal(f):
|
||||
return f(peerIds, topicIds, text, strongSelf.currentAccount, silently)
|
||||
|> map { state -> ShareState in
|
||||
switch state {
|
||||
case let .preparing(long):
|
||||
return .preparing(long)
|
||||
case let .progress(value):
|
||||
return .progress(value)
|
||||
case .done:
|
||||
return .done
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let account = strongSelf.currentAccount
|
||||
let queue = Queue.mainQueue()
|
||||
var displayedError = false
|
||||
return combineLatest(queue: queue, shareSignals)
|
||||
|> castError(ShareControllerError.self)
|
||||
|> mapToSignal { messageIdSets -> Signal<ShareState, ShareControllerError> in
|
||||
var statuses: [Signal<(MessageId, PendingMessageStatus?, PendingMessageFailureReason?), ShareControllerError>] = []
|
||||
for messageIds in messageIdSets {
|
||||
for case let id? in messageIds {
|
||||
statuses.append(account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> castError(ShareControllerError.self)
|
||||
|> map { status, error -> (MessageId, PendingMessageStatus?, PendingMessageFailureReason?) in
|
||||
return (id, status, error)
|
||||
})
|
||||
let account = strongSelf.currentAccount
|
||||
let queue = Queue.mainQueue()
|
||||
var displayedError = false
|
||||
return combineLatest(queue: queue, shareSignals)
|
||||
|> castError(ShareControllerError.self)
|
||||
|> mapToSignal { messageIdSets -> Signal<ShareState, ShareControllerError> in
|
||||
var statuses: [Signal<(MessageId, PendingMessageStatus?, PendingMessageFailureReason?), ShareControllerError>] = []
|
||||
for messageIds in messageIdSets {
|
||||
for case let id? in messageIds {
|
||||
statuses.append(account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> castError(ShareControllerError.self)
|
||||
|> map { status, error -> (MessageId, PendingMessageStatus?, PendingMessageFailureReason?) in
|
||||
return (id, status, error)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return combineLatest(queue: queue, statuses)
|
||||
|> mapToSignal { statuses -> Signal<ShareState, ShareControllerError> in
|
||||
var hasStatuses = false
|
||||
for (id, status, error) in statuses {
|
||||
if let error = error {
|
||||
Queue.mainQueue().async {
|
||||
let _ = TelegramEngine(account: account).messages.deleteMessagesInteractively(messageIds: [id], type: .forEveryone).start()
|
||||
let _ = (TelegramEngine(account: account).data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id.peerId))
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
guard let strongSelf = self, let peer = peer else {
|
||||
return
|
||||
}
|
||||
if !displayedError, case .slowmodeActive = error {
|
||||
displayedError = true
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
})
|
||||
return combineLatest(queue: queue, statuses)
|
||||
|> mapToSignal { statuses -> Signal<ShareState, ShareControllerError> in
|
||||
var hasStatuses = false
|
||||
for (id, status, error) in statuses {
|
||||
if let error = error {
|
||||
Queue.mainQueue().async {
|
||||
let _ = TelegramEngine(account: account).messages.deleteMessagesInteractively(messageIds: [id], type: .forEveryone).start()
|
||||
let _ = (TelegramEngine(account: account).data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id.peerId))
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
guard let strongSelf = self, let peer = peer else {
|
||||
return
|
||||
}
|
||||
if !displayedError {
|
||||
if case .slowmodeActive = error {
|
||||
displayedError = true
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: strongSelf.presentationData.strings.Chat_SlowmodeSendError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
} else if case .mediaRestricted = error {
|
||||
displayedError = true
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), text: restrictedSendingContentsText(peer: peer, presentationData: strongSelf.presentationData), actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if status != nil {
|
||||
hasStatuses = true
|
||||
}
|
||||
}
|
||||
if status != nil {
|
||||
hasStatuses = true
|
||||
if !hasStatuses {
|
||||
return .single(.done)
|
||||
}
|
||||
return .complete()
|
||||
}
|
||||
if !hasStatuses {
|
||||
return .single(.done)
|
||||
}
|
||||
return .complete()
|
||||
|> take(1)
|
||||
}
|
||||
|> take(1)
|
||||
}
|
||||
}
|
||||
self.controllerNode.shareExternal = { [weak self] _ in
|
||||
@ -1261,3 +1490,73 @@ public func presentExternalShare(context: AccountContext, text: String, parentCo
|
||||
}
|
||||
context.sharedContext.applicationBindings.presentNativeController(activityController)
|
||||
}
|
||||
|
||||
private func restrictedSendingContentsText(peer: EnginePeer, presentationData: PresentationData) -> String {
|
||||
//TODO:localize
|
||||
var itemList: [String] = []
|
||||
|
||||
let order: [TelegramChatBannedRightsFlags] = [
|
||||
.banSendText,
|
||||
.banSendPhotos,
|
||||
.banSendVideos,
|
||||
.banSendVoice,
|
||||
.banSendInstantVideos,
|
||||
.banSendFiles,
|
||||
.banSendMusic,
|
||||
.banSendStickers
|
||||
]
|
||||
|
||||
for right in order {
|
||||
if case let .channel(channel) = peer {
|
||||
if channel.hasBannedPermission(right) != nil {
|
||||
continue
|
||||
}
|
||||
} else if case let .legacyGroup(group) = peer {
|
||||
if group.hasBannedPermission(right) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var title: String?
|
||||
switch right {
|
||||
case .banSendText:
|
||||
title = "text messages"
|
||||
case .banSendPhotos:
|
||||
title = "photos"
|
||||
case .banSendVideos:
|
||||
title = "videos"
|
||||
case .banSendVoice:
|
||||
title = "voice messages"
|
||||
case .banSendInstantVideos:
|
||||
title = "video messages"
|
||||
case .banSendFiles:
|
||||
title = "files"
|
||||
case .banSendMusic:
|
||||
title = "music"
|
||||
case .banSendStickers:
|
||||
title = "Stickers & GIFs"
|
||||
default:
|
||||
break
|
||||
}
|
||||
if let title {
|
||||
itemList.append(title)
|
||||
}
|
||||
}
|
||||
|
||||
if itemList.isEmpty {
|
||||
return "Sending messages is disabled in \(peer.compactDisplayTitle)"
|
||||
}
|
||||
|
||||
var itemListString = ""
|
||||
for i in 0 ..< itemList.count {
|
||||
if i != 0 {
|
||||
itemListString.append(", ")
|
||||
}
|
||||
if i == itemList.count - 1 && i != 0 {
|
||||
itemListString.append("and ")
|
||||
}
|
||||
itemListString.append(itemList[i])
|
||||
}
|
||||
|
||||
return "The admins of \(peer.compactDisplayTitle) group only allow to send \(itemListString)."
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
displaySearchWithPlaceholder: nil,
|
||||
searchCategories: nil,
|
||||
searchInitiallyHidden: true,
|
||||
searchState: .empty
|
||||
searchState: .empty(hasResults: false)
|
||||
)
|
||||
))
|
||||
|
||||
@ -386,7 +386,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
displaySearchWithPlaceholder: presentationData.strings.Common_Search,
|
||||
searchCategories: searchCategories,
|
||||
searchInitiallyHidden: true,
|
||||
searchState: .empty
|
||||
searchState: .empty(hasResults: false)
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -419,7 +419,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
displaySearchWithPlaceholder: presentationData.strings.Common_Search,
|
||||
searchCategories: searchCategories,
|
||||
searchInitiallyHidden: true,
|
||||
searchState: .empty
|
||||
searchState: .empty(hasResults: false)
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -1495,7 +1495,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
)
|
||||
}
|
||||
if let emoji = inputData.emoji {
|
||||
let defaultSearchState: EmojiPagerContentComponent.SearchState = emojiSearchResult.isPreset ? .active : .empty
|
||||
let defaultSearchState: EmojiPagerContentComponent.SearchState = emojiSearchResult.isPreset ? .active : .empty(hasResults: true)
|
||||
inputData.emoji = emoji.withUpdatedItemGroups(panelItemGroups: emoji.panelItemGroups, contentItemGroups: emojiSearchResult.groups, itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: emojiSearchResult.id, version: emojiSearchResult.version), emptySearchResults: emptySearchResults, searchState: emojiSearchState.isSearching ? .searching : defaultSearchState)
|
||||
}
|
||||
} else if emojiSearchState.isSearching {
|
||||
@ -1514,7 +1514,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
)
|
||||
}
|
||||
if let stickers = inputData.stickers {
|
||||
let defaultSearchState: EmojiPagerContentComponent.SearchState = stickerSearchResult.isPreset ? .active : .empty
|
||||
let defaultSearchState: EmojiPagerContentComponent.SearchState = stickerSearchResult.isPreset ? .active : .empty(hasResults: true)
|
||||
inputData.stickers = stickers.withUpdatedItemGroups(panelItemGroups: stickers.panelItemGroups, contentItemGroups: stickerSearchResult.groups, itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: stickerSearchResult.id, version: stickerSearchResult.version), emptySearchResults: stickerSearchResults, searchState: stickerSearchState.isSearching ? .searching : defaultSearchState)
|
||||
}
|
||||
} else if stickerSearchState.isSearching {
|
||||
|
@ -1278,7 +1278,7 @@ private final class GroupEmbeddedView: UIScrollView, UIScrollViewDelegate, Pager
|
||||
}
|
||||
|
||||
for (_, itemLayer) in self.visibleItemLayers {
|
||||
if itemLayer.frame.inset(by: UIEdgeInsets(top: 6.0, left: itemLayout.itemSpacing, bottom: 6.0, right: itemLayout.itemSpacing)).contains(point) {
|
||||
if itemLayer.frame.inset(by: UIEdgeInsets(top: -6.0, left: -itemLayout.itemSpacing, bottom: -6.0, right: -itemLayout.itemSpacing)).contains(point) {
|
||||
self.performItemAction(itemLayer.item, self, itemLayer.frame, itemLayer)
|
||||
return true
|
||||
}
|
||||
@ -2104,7 +2104,7 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
||||
var hasText = false
|
||||
if let textField = self.textField {
|
||||
textField.textColor = theme.contextMenu.primaryColor
|
||||
transition.setFrame(view: textField, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + sideTextInset, y: backgroundFrame.minY), size: CGSize(width: backgroundFrame.width - sideTextInset, height: backgroundFrame.height)))
|
||||
transition.setFrame(view: textField, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + sideTextInset, y: backgroundFrame.minY), size: CGSize(width: backgroundFrame.width - sideTextInset - 32.0, height: backgroundFrame.height)))
|
||||
|
||||
if let text = textField.text, !text.isEmpty {
|
||||
hasText = true
|
||||
@ -2556,8 +2556,8 @@ public final class EmojiPagerContentComponent: Component {
|
||||
case detailed
|
||||
}
|
||||
|
||||
public enum SearchState {
|
||||
case empty
|
||||
public enum SearchState: Equatable {
|
||||
case empty(hasResults: Bool)
|
||||
case searching
|
||||
case active
|
||||
}
|
||||
@ -4382,11 +4382,11 @@ public final class EmojiPagerContentComponent: Component {
|
||||
}
|
||||
|
||||
public func scrollToItemGroup(id supergroupId: AnyHashable, subgroupId: Int32?, animated: Bool) {
|
||||
guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let itemLayout = self.itemLayout else {
|
||||
guard let component = self.component, let itemGroup = component.contentItemGroups.first(where: { $0.supergroupId == supergroupId }), let pagerEnvironment = self.pagerEnvironment, let itemLayout = self.itemLayout else {
|
||||
return
|
||||
}
|
||||
|
||||
if self.isSearchActivated {
|
||||
if !component.contentItemGroups.contains(where: { $0.groupId == supergroupId }), self.isSearchActivated {
|
||||
self.visibleSearchHeader?.clearCategorySearch()
|
||||
return
|
||||
}
|
||||
@ -4446,6 +4446,10 @@ public final class EmojiPagerContentComponent: Component {
|
||||
highlightFrame.size.width = self.scrollView.bounds.width - 4.0 - highlightFrame.minX
|
||||
}
|
||||
|
||||
if (itemGroup.isPremiumLocked || itemGroup.isFeatured), !itemGroup.isEmbedded, case .compact = itemLayout.layoutType {
|
||||
highlightFrame.size.height += 6.0
|
||||
}
|
||||
|
||||
highlightLayer.frame = highlightFrame
|
||||
self.scrollView.layer.insertSublayer(highlightLayer, at: 0)
|
||||
highlightLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, delay: 0.8, removeOnCompletion: false, completion: { [weak highlightLayer] _ in
|
||||
@ -5122,7 +5126,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
scrollView.layer.removeAllAnimations()
|
||||
}
|
||||
|
||||
if self.isSearchActivated, let component = self.component, component.searchState == .empty, !component.searchAlwaysActive, let visibleSearchHeader = self.visibleSearchHeader, visibleSearchHeader.currentPresetSearchTerm == nil {
|
||||
if self.isSearchActivated, let component = self.component, component.searchState == .empty(hasResults: false), !component.searchAlwaysActive, let visibleSearchHeader = self.visibleSearchHeader, visibleSearchHeader.currentPresetSearchTerm == nil {
|
||||
scrollView.isScrollEnabled = false
|
||||
DispatchQueue.main.async {
|
||||
scrollView.isScrollEnabled = true
|
||||
@ -6122,6 +6126,14 @@ public final class EmojiPagerContentComponent: Component {
|
||||
|
||||
self.pagerEnvironment = pagerEnvironment
|
||||
|
||||
pagerEnvironment.scrollToTop.connect { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.scrollView.setContentOffset(CGPoint(), animated: true)
|
||||
}
|
||||
|
||||
self.updateIsWarpEnabled(isEnabled: component.warpContentsOnEdges)
|
||||
|
||||
if let longTapRecognizer = self.longTapRecognizer {
|
||||
@ -7714,7 +7726,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
contentItemGroups: allItemGroups,
|
||||
itemLayoutType: .compact,
|
||||
itemContentUniqueId: nil,
|
||||
searchState: .empty,
|
||||
searchState: .empty(hasResults: false),
|
||||
warpContentsOnEdges: isReactionSelection || isStatusSelection || isProfilePhotoEmojiSelection || isGroupPhotoEmojiSelection,
|
||||
displaySearchWithPlaceholder: displaySearchWithPlaceholder,
|
||||
searchCategories: searchCategories,
|
||||
@ -8236,7 +8248,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
contentItemGroups: allItemGroups,
|
||||
itemLayoutType: .detailed,
|
||||
itemContentUniqueId: nil,
|
||||
searchState: .empty,
|
||||
searchState: .empty(hasResults: false),
|
||||
warpContentsOnEdges: isProfilePhotoEmojiSelection || isGroupPhotoEmojiSelection,
|
||||
displaySearchWithPlaceholder: hasSearch ? strings.StickersSearch_SearchStickersPlaceholder : nil,
|
||||
searchCategories: searchCategories,
|
||||
|
@ -391,7 +391,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
|
||||
contentItemGroups: self.itemGroups,
|
||||
itemLayoutType: .compact,
|
||||
itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: "main", version: 0),
|
||||
searchState: .empty,
|
||||
searchState: .empty(hasResults: false),
|
||||
warpContentsOnEdges: false,
|
||||
displaySearchWithPlaceholder: "Search Emoji",
|
||||
searchCategories: nil,
|
||||
@ -411,7 +411,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode
|
||||
iconFile: nil
|
||||
)
|
||||
}
|
||||
emojiContent = emojiContent.withUpdatedItemGroups(panelItemGroups: emojiContent.panelItemGroups, contentItemGroups: emojiSearchResult.groups, itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: emojiSearchResult.id, version: 0), emptySearchResults: emptySearchResults, searchState: .active)
|
||||
emojiContent = emojiContent.withUpdatedItemGroups(panelItemGroups: emojiContent.panelItemGroups, contentItemGroups: emojiSearchResult.groups, itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: emojiSearchResult.id, version: 0), emptySearchResults: emptySearchResults, searchState: .empty(hasResults: true))
|
||||
}
|
||||
|
||||
let _ = self.keyboardView.update(
|
||||
|
@ -1814,8 +1814,8 @@ public final class EntityKeyboardTopPanelComponent: Component {
|
||||
let itemFrame = CGRect(origin: CGPoint(x: itemOuterFrame.minX + floor((itemOuterFrame.width - itemSize.width) / 2.0), y: itemOuterFrame.minY + floor((itemOuterFrame.height - itemSize.height) / 2.0)), size: itemSize)
|
||||
itemTransition.setFrame(view: itemView, frame: itemFrame)
|
||||
|
||||
transition.setSublayerTransform(view: itemView, transform: CATransform3DMakeScale(scale, scale, 1.0))
|
||||
transition.setAlpha(view: itemView, alpha: self.visibilityFraction)
|
||||
itemTransition.setSublayerTransform(view: itemView, transform: CATransform3DMakeScale(scale, scale, 1.0))
|
||||
itemTransition.setAlpha(view: itemView, alpha: self.visibilityFraction)
|
||||
}
|
||||
}
|
||||
var removedIds: [AnyHashable] = []
|
||||
|
@ -8612,7 +8612,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
if bannedMediaInput {
|
||||
strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText()))
|
||||
strongSelf.controllerInteraction?.displayUndo(.universal(animation: "premium_unlock", scale: 1.0, colors: ["__allcolors__": UIColor(white: 1.0, alpha: 1.0)], title: nil, text: strongSelf.restrictedSendingContentsText(), customUndoText: nil))
|
||||
return
|
||||
}
|
||||
|
||||
@ -8754,7 +8754,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
switch displayType {
|
||||
case .tooltip:
|
||||
if displayToast {
|
||||
strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: banDescription))
|
||||
strongSelf.controllerInteraction?.displayUndo(.universal(animation: "premium_unlock", scale: 1.0, colors: ["__allcolors__": UIColor(white: 1.0, alpha: 1.0)], title: nil, text: banDescription, customUndoText: nil))
|
||||
} else {
|
||||
var rect: CGRect?
|
||||
let isStickers: Bool = subject == .stickers
|
||||
@ -8924,7 +8924,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
if bannedMediaInput {
|
||||
strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText()))
|
||||
strongSelf.controllerInteraction?.displayUndo(.universal(animation: "premium_unlock", scale: 1.0, colors: ["__allcolors__": UIColor(white: 1.0, alpha: 1.0)], title: nil, text: strongSelf.restrictedSendingContentsText(), customUndoText: nil))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -368,6 +368,8 @@ private func extractAssociatedData(chatLocation: ChatLocation, view: MessageHist
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if case let .replyThread(message) = chatLocation, message.isForumPost {
|
||||
automaticDownloadPeerId = message.messageId.peerId
|
||||
}
|
||||
|
||||
return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, defaultReaction: defaultReaction, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage)
|
||||
|
@ -933,7 +933,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
return
|
||||
}
|
||||
//TODO:localize
|
||||
controller.controllerInteraction?.displayUndo(.info(title: nil, text: controller.restrictedSendingContentsText()))
|
||||
controller.controllerInteraction?.displayUndo(.universal(animation: "premium_unlock", scale: 1.0, colors: ["__allcolors__": UIColor(white: 1.0, alpha: 1.0)], title: nil, text: controller.restrictedSendingContentsText(), customUndoText: nil))
|
||||
} else {
|
||||
strongSelf.ensureFocused()
|
||||
}
|
||||
|
@ -830,6 +830,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
self.avatarNode = nil
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
|
||||
self.animationNode = AnimationNode(animation: animation, colors: colors, scale: scale)
|
||||
self.animatedStickerNode = nil
|
||||
if let title = title {
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"app": "9.3.3",
|
||||
"app": "9.4",
|
||||
"bazel": "5.3.1",
|
||||
"xcode": "14.1"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user