mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-05-13 00:42:20 +02:00
feat: новые функции, исправлены критические ошибки сборки и баги интерфейса, больше подписей в файлах
This commit is contained in:
@@ -692,6 +692,44 @@ extension ChatControllerImpl {
|
||||
|
||||
self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, statusBar: self.statusBar, backgroundNode: self.chatBackgroundNode, controller: self)
|
||||
|
||||
// Seed the title pill synchronously from whatever data is available at this point,
|
||||
// so the header shows the peer name immediately instead of staying blank until
|
||||
// the first async contentDataUpdated() fires.
|
||||
let initialTitleContent: ChatTitleContent? = self.contentData?.state.chatTitleContent
|
||||
?? self.presentationInterfaceState.renderedPeer.flatMap { renderedPeer -> ChatTitleContent? in
|
||||
guard let peer = renderedPeer.peer else { return nil }
|
||||
let peerData = ChatTitleContent.PeerData(
|
||||
peerId: renderedPeer.peerId,
|
||||
peer: peer,
|
||||
isContact: false,
|
||||
isSavedMessages: peer.id == self.context.account.peerId,
|
||||
notificationSettings: nil,
|
||||
peerPresences: [:],
|
||||
cachedData: nil
|
||||
)
|
||||
return .peer(
|
||||
peerView: peerData,
|
||||
customTitle: nil,
|
||||
customSubtitle: nil,
|
||||
onlineMemberCount: (nil, nil),
|
||||
isScheduledMessages: false,
|
||||
isMuted: nil,
|
||||
customMessageCount: nil,
|
||||
isEnabled: true
|
||||
)
|
||||
}
|
||||
if let initialTitleContent {
|
||||
self.chatTitleView?.update(
|
||||
context: self.context,
|
||||
theme: self.presentationData.theme,
|
||||
strings: self.presentationData.strings,
|
||||
dateTimeFormat: self.presentationData.dateTimeFormat,
|
||||
nameDisplayOrder: self.presentationData.nameDisplayOrder,
|
||||
content: initialTitleContent,
|
||||
transition: .immediate
|
||||
)
|
||||
}
|
||||
|
||||
if let currentItem = self.globalControlPanelsContext?.tempVoicePlaylistCurrentItem {
|
||||
self.chatDisplayNode.historyNode.voicePlaylistItemChanged(nil, currentItem)
|
||||
}
|
||||
|
||||
@@ -146,7 +146,6 @@ import ChatTextInputPanelNode
|
||||
import ChatInputAccessoryPanel
|
||||
import GlobalControlPanelsContext
|
||||
import ChatSearchNavigationContentNode
|
||||
import ChatAgeRestrictionAlertController
|
||||
|
||||
public final class ChatControllerOverlayPresentationData {
|
||||
public let expandData: (ASDisplayNode?, () -> Void)
|
||||
@@ -830,7 +829,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return true
|
||||
}
|
||||
|
||||
let controllerInteraction = ChatControllerInteraction(openMessage: { [weak self] message, params in
|
||||
let openMessage: (Message, OpenMessageParams) -> Bool = { [weak self] message, params in
|
||||
guard let self, self.isNodeLoaded, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) else {
|
||||
return false
|
||||
}
|
||||
@@ -1566,7 +1565,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.controllerInteraction?.isOpeningMediaSignal = openChatMessageParams.blockInteraction.get()
|
||||
|
||||
return context.sharedContext.openChatMessage(openChatMessageParams)
|
||||
}, openPeer: { [weak self] peer, navigation, fromMessage, source in
|
||||
}
|
||||
|
||||
let openPeer: (EnginePeer, ChatControllerInteractionNavigateToPeer, MessageReference?, ChatControllerInteraction.OpenPeerSource) -> Void = { [weak self] peer, navigation, fromMessage, source in
|
||||
var expandAvatar = false
|
||||
if case let .groupParticipant(storyStats, avatarHeaderNode) = source {
|
||||
if let storyStats, storyStats.totalCount != 0, let avatarHeaderNode = avatarHeaderNode as? ChatMessageAvatarHeaderNodeImpl {
|
||||
@@ -1581,20 +1582,28 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
fromReactionMessageId = fromMessage?.id
|
||||
}
|
||||
self?.openPeer(peer: peer, navigation: navigation, fromMessage: fromMessage, fromReactionMessageId: fromReactionMessageId, expandAvatar: expandAvatar)
|
||||
}, openPeerMention: { [weak self] name, progress in
|
||||
}
|
||||
|
||||
let openPeerMention: (String, Promise<Bool>?) -> Void = { [weak self] name, progress in
|
||||
self?.openPeerMention(name, progress: progress)
|
||||
}, openMessageContextMenu: { [weak self] message, selectAll, node, frame, anyRecognizer, location in
|
||||
}
|
||||
|
||||
let openMessageContextMenu: (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?, CGPoint?) -> Void = { [weak self] message, selectAll, node, frame, anyRecognizer, location in
|
||||
guard let self, self.isNodeLoaded else {
|
||||
return
|
||||
}
|
||||
self.openMessageContextMenu(message: message, selectAll: selectAll, node: node, frame: frame, anyRecognizer: anyRecognizer, location: location)
|
||||
}, openMessageReactionContextMenu: { [weak self] message, sourceView, gesture, value in
|
||||
}
|
||||
|
||||
let openMessageReactionContextMenu: (Message, ContextExtractedContentContainingView, ContextGesture?, MessageReaction.Reaction) -> Void = { [weak self] message, sourceView, gesture, value in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.openMessageReactionContextMenu(message: message, sourceView: sourceView, gesture: gesture, value: value)
|
||||
}, updateMessageReaction: { [weak self] initialMessage, reaction, force, sourceView in
|
||||
}
|
||||
|
||||
let updateMessageReaction: (Message, ChatControllerInteractionReaction, Bool, ContextExtractedContentContainingView?) -> Void = { [weak self] initialMessage, reaction, force, sourceView in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@@ -2062,7 +2071,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
})
|
||||
}, activateMessagePinch: { [weak self] sourceNode in
|
||||
}
|
||||
|
||||
let controllerInteraction = ChatControllerInteraction(
|
||||
openMessage: openMessage,
|
||||
openPeer: openPeer,
|
||||
openPeerMention: openPeerMention,
|
||||
openMessageContextMenu: openMessageContextMenu,
|
||||
openMessageReactionContextMenu: openMessageReactionContextMenu,
|
||||
updateMessageReaction: updateMessageReaction,
|
||||
activateMessagePinch: { [weak self] sourceNode in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -893,7 +893,8 @@ extension ChatControllerImpl {
|
||||
peerVerification = cachedChannelData.verification
|
||||
}
|
||||
}
|
||||
copyProtectionEnabled = peer.isCopyProtectionEnabled
|
||||
// GHOSTGRAM: Bypass copy protection if enabled in Misc settings
|
||||
copyProtectionEnabled = MiscSettingsManager.shared.shouldBypassCopyProtection ? false : peer.isCopyProtectionEnabled
|
||||
if let cachedGroupData = peerView.cachedData as? CachedGroupData {
|
||||
if !cachedGroupData.botInfos.isEmpty {
|
||||
hasBots = true
|
||||
@@ -1371,7 +1372,8 @@ extension ChatControllerImpl {
|
||||
var alwaysShowGiftButton = false
|
||||
var disallowedGifts: TelegramDisallowedGifts?
|
||||
if let peer = peerView.peers[peerView.peerId] {
|
||||
copyProtectionEnabled = peer.isCopyProtectionEnabled
|
||||
// GHOSTGRAM: Bypass copy protection if enabled in Misc settings
|
||||
copyProtectionEnabled = MiscSettingsManager.shared.shouldBypassCopyProtection ? false : peer.isCopyProtectionEnabled
|
||||
if let cachedData = peerView.cachedData as? CachedUserData {
|
||||
contactStatus = ChatContactStatus(canAddContact: !peerView.peerIsContact, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: nil, managingBot: managingBot)
|
||||
if case let .known(value) = cachedData.businessIntro {
|
||||
|
||||
@@ -1129,7 +1129,9 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
let isSecret = self.chatPresentationInterfaceState.copyProtectionEnabled || self.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat || self.chatLocation.peerId?.isVerificationCodes == true
|
||||
// GHOSTGRAM: Bypass screenshot protection if enabled in Misc settings
|
||||
let effectiveCopyProtection = MiscSettingsManager.shared.shouldBypassScreenshotProtection ? false : self.chatPresentationInterfaceState.copyProtectionEnabled
|
||||
let isSecret = effectiveCopyProtection || self.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat || self.chatLocation.peerId?.isVerificationCodes == true
|
||||
if self.historyNodeContainer.isSecret != isSecret {
|
||||
self.historyNodeContainer.isSecret = isSecret
|
||||
setLayerDisableScreenshots(self.titleAccessoryPanelContainer.layer, isSecret)
|
||||
@@ -4600,12 +4602,10 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
self.setupSendActionOnViewUpdate({ [weak self] in
|
||||
guard let self, let textInputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode else {
|
||||
return
|
||||
}
|
||||
// GHOSTGRAM: When send delay is active, scheduled messages
|
||||
// don't trigger history view update, so clear input immediately.
|
||||
if SendDelayManager.shared.isEnabled {
|
||||
self.collapseInput()
|
||||
|
||||
self.ignoreUpdateHeight = true
|
||||
textInputPanelNode.text = ""
|
||||
self.requestUpdateChatInterfaceState(.immediate, overrideThreadId == nil, { state in
|
||||
@@ -4624,7 +4624,33 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
return state
|
||||
})
|
||||
self.ignoreUpdateHeight = false
|
||||
}, usedCorrelationId)
|
||||
} else {
|
||||
self.setupSendActionOnViewUpdate({ [weak self] in
|
||||
guard let self, let textInputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode else {
|
||||
return
|
||||
}
|
||||
self.collapseInput()
|
||||
|
||||
self.ignoreUpdateHeight = true
|
||||
textInputPanelNode.text = ""
|
||||
self.requestUpdateChatInterfaceState(.immediate, overrideThreadId == nil, { state in
|
||||
var state = state
|
||||
state = state.withUpdatedReplyMessageSubject(nil)
|
||||
state = state.withUpdatedSendMessageEffect(nil)
|
||||
|
||||
if state.postSuggestionState != nil {
|
||||
state = state.withUpdatedPostSuggestionState(nil)
|
||||
state = state.withUpdatedEditMessage(nil)
|
||||
}
|
||||
|
||||
state = state.withUpdatedForwardMessageIds(nil)
|
||||
state = state.withUpdatedForwardOptionsState(nil)
|
||||
state = state.withUpdatedComposeDisableUrlPreviews([])
|
||||
return state
|
||||
})
|
||||
self.ignoreUpdateHeight = false
|
||||
}, usedCorrelationId)
|
||||
}
|
||||
completion()
|
||||
|
||||
self.sendMessages(messages, silentPosting, scheduleTime, repeatPeriod, messages.count > 1, postpone)
|
||||
|
||||
@@ -2056,6 +2056,10 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
}
|
||||
}
|
||||
}
|
||||
// GHOSTGRAM: Bypass copy protection if enabled in Misc settings
|
||||
if MiscSettingsManager.shared.shouldBypassCopyProtection {
|
||||
isCopyProtectionEnabled = false
|
||||
}
|
||||
let alwaysDisplayTranscribeButton = ChatMessageItemAssociatedData.DisplayTranscribeButton(
|
||||
canBeDisplayed: suggestAudioTranscription.0 < 2,
|
||||
displayForNotConsumed: suggestAudioTranscription.1,
|
||||
@@ -2102,7 +2106,8 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
selectedMessages: selectedMessages,
|
||||
presentationData: chatPresentationData,
|
||||
historyAppearsCleared: historyAppearsCleared,
|
||||
skipViewOnceMedia: mode != .bubbles,
|
||||
// GHOSTGRAM: Keep view-once media visible if bypass is enabled
|
||||
skipViewOnceMedia: MiscSettingsManager.shared.shouldDisableViewOnceAutoDelete ? false : (mode != .bubbles),
|
||||
pendingUnpinnedAllMessages: pendingUnpinnedAllMessages,
|
||||
pendingRemovedMessages: pendingRemovedMessages,
|
||||
associatedData: associatedData,
|
||||
@@ -2110,8 +2115,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
customChannelDiscussionReadState: customChannelDiscussionReadState,
|
||||
customThreadOutgoingReadState: customThreadOutgoingReadState,
|
||||
cachedData: data.cachedData,
|
||||
adMessage: allAdMessages.fixed,
|
||||
dynamicAdMessages: allAdMessages.opportunistic
|
||||
// GHOSTGRAM: Block ads if enabled in Misc settings
|
||||
adMessage: MiscSettingsManager.shared.shouldBlockAds ? nil : allAdMessages.fixed,
|
||||
dynamicAdMessages: MiscSettingsManager.shared.shouldBlockAds ? [] : allAdMessages.opportunistic
|
||||
)
|
||||
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
|
||||
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id, locationInput: update.2, ignoreMessagesInTimestampRange: update.3, ignoreMessageIds: update.4)
|
||||
|
||||
@@ -31,7 +31,7 @@ final class ChatSearchNavigationContentNode: NavigationBarContentNode {
|
||||
self.chatLocation = chatLocation
|
||||
self.interaction = interaction
|
||||
|
||||
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasBackground: false, hasSeparator: false), strings: strings, fieldStyle: .modern)
|
||||
self.searchBar = SearchBarNode(theme: SearchBarNodeTheme(theme: theme, hasBackground: false, hasSeparator: false), presentationTheme: theme, strings: strings, fieldStyle: .modern)
|
||||
let placeholderText: String
|
||||
switch chatLocation {
|
||||
case .peer, .replyThread, .customChatContents:
|
||||
@@ -90,10 +90,11 @@ final class ChatSearchNavigationContentNode: NavigationBarContentNode {
|
||||
return 54.0
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
let searchBarFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height - self.nominalHeight), size: CGSize(width: size.width, height: 54.0))
|
||||
self.searchBar.frame = searchBarFrame
|
||||
self.searchBar.updateLayout(boundingSize: searchBarFrame.size, leftInset: leftInset, rightInset: rightInset, transition: transition)
|
||||
return size
|
||||
}
|
||||
|
||||
func activate() {
|
||||
@@ -106,7 +107,7 @@ final class ChatSearchNavigationContentNode: NavigationBarContentNode {
|
||||
|
||||
func update(presentationInterfaceState: ChatPresentationInterfaceState) {
|
||||
if let search = presentationInterfaceState.search {
|
||||
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationInterfaceState.theme, hasBackground: false, hasSeparator: false), strings: presentationInterfaceState.strings)
|
||||
self.searchBar.updateThemeAndStrings(theme: SearchBarNodeTheme(theme: presentationInterfaceState.theme, hasBackground: false, hasSeparator: false), presentationTheme: presentationInterfaceState.theme, strings: presentationInterfaceState.strings)
|
||||
|
||||
switch search.domain {
|
||||
case .everything, .tag:
|
||||
|
||||
@@ -1,16 +1,4 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import ChatPresentationInterfaceState
|
||||
import AccountContext
|
||||
import class LegacyChatHeaderPanelComponent.LegacyChatTitleAccessoryPanelNode
|
||||
|
||||
class ChatTitleAccessoryPanelNode: ASDisplayNode {
|
||||
typealias LayoutResult = ChatControllerCustomNavigationPanelNode.LayoutResult
|
||||
|
||||
var interfaceInteraction: ChatPanelInterfaceInteraction?
|
||||
|
||||
func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> LayoutResult {
|
||||
preconditionFailure()
|
||||
}
|
||||
class ChatTitleAccessoryPanelNode: LegacyChatTitleAccessoryPanelNode {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user