chore: migrate to new version + fixed several critical bugs

- Migrated project to latest Telegram iOS base (v12.3.2+)
- Fixed circular dependency between GhostModeManager and MiscSettingsManager
- Fixed multiple Bazel build configuration errors (select() default conditions)
- Fixed duplicate type definitions in PeerInfoScreen
- Fixed swiftmodule directory resolution in build scripts
- Added Ghostgram Settings tab in main Settings menu with all 5 features
- Cleared sensitive credentials from config.json (template-only now)
- Excluded bazel-cache from version control
This commit is contained in:
ichmagmaus 812
2026-02-23 23:04:32 +01:00
parent 703e291bcb
commit db53826061
1017 changed files with 62337 additions and 40559 deletions
@@ -21,7 +21,7 @@ swift_library(
"//submodules/ChatListUI",
"//submodules/SearchBarNode",
"//submodules/ContactListUI",
"//submodules/SegmentedControlNode",
"//submodules/TelegramUI/Components/SegmentControlComponent",
"//submodules/AttachmentTextInputPanelNode",
"//submodules/ChatPresentationInterfaceState",
"//submodules/ChatSendMessageActionUI",
@@ -35,6 +35,10 @@ swift_library(
"//submodules/TextFormat",
"//submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode",
"//submodules/CounterControllerTitleView",
"//submodules/TelegramUI/Components/ChatList/ChatListFilterTabContainerNode",
"//submodules/ComponentFlow",
"//submodules/Components/ComponentDisplayAdapters",
"//submodules/TelegramUI/Components/EdgeEffect",
],
visibility = [
"//visibility:public",
@@ -10,6 +10,7 @@ import AccountContext
import SearchUI
import ChatListUI
import CounterControllerTitleView
import ChatListFilterTabContainerNode
public final class PeerSelectionControllerImpl: ViewController, PeerSelectionController {
private let context: AccountContext
@@ -112,7 +113,9 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.immediatelyActivateMultipleSelection = params.immediatelyActivateMultipleSelection
self.multipleSelectionLimit = params.multipleSelectionLimit
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData, style: .glass))
self._hasGlassStyle = true
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
@@ -147,7 +150,6 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
if params.forumPeerId == nil {
self.navigationPresentation = .modal
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
}
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
@@ -206,7 +208,9 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
if force {
strongSelf.tabContainerNode?.cancelAnimations()
}
strongSelf.tabContainerNode?.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: false, isEditing: false, canReorderAllChats: false, filtersLimit: tabContainerData.2, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
if let tabContainerNode = strongSelf.tabContainerNode {
tabContainerNode.update(size: CGSize(width: layout.size.width, height: 44.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: false, isEditing: false, canReorderAllChats: false, filtersLimit: tabContainerData.2, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
}
}
self.tabContainerNode?.tabSelected = { [weak self] id, isDisabled in
@@ -244,7 +248,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
private func updateThemeAndStrings() {
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData, style: .glass), transition: .immediate)
self.searchContentNode?.updateThemeAndPlaceholder(theme: self.presentationData.theme, placeholder: self.presentationData.strings.Common_Search)
self.title = self.customTitle ?? self.presentationData.strings.Conversation_ForwardTitle
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
@@ -252,6 +256,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
}
override public func loadDisplayNode() {
self.navigationBar?.secondaryContentHeight = 44.0 + 10.0
self.displayNode = PeerSelectionControllerNode(context: self.context, controller: self, presentationData: self.presentationData, filter: self.filter, forumPeerId: self.forumPeerId, hasFilters: self.hasFilters, hasChatListSelector: self.hasChatListSelector, hasContactSelector: self.hasContactSelector, hasGlobalSearch: self.hasGlobalSearch, forwardedMessageIds: self.forwardedMessageIds, hasTypeHeaders: self.hasTypeHeaders, requestPeerType: self.requestPeerType, hasCreation: self.hasCreation, createNewGroup: self.createNewGroup, present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a)
}, presentInGlobalOverlay: { [weak self] c, a in
@@ -419,8 +425,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
if let tabContainerNode = self.tabContainerNode, let mainContainerNode = self.peerSelectionNode.mainContainerNode {
let tabContainerOffset: CGFloat = 0.0
let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0
transition.updateFrame(node: tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0)))
tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: mainContainerNode.currentItemFilter, isReordering: false, isEditing: false, canReorderAllChats: false, filtersLimit: self.tabContainerData?.2, transitionFraction: mainContainerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
transition.updateFrame(node: tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 44.0 - 8.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 44.0)))
tabContainerNode.update(size: CGSize(width: layout.size.width, height: 44.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: mainContainerNode.currentItemFilter, isReordering: false, isEditing: false, canReorderAllChats: false, filtersLimit: self.tabContainerData?.2, transitionFraction: mainContainerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
}
}
@@ -458,6 +464,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
}
private var initializedFilters = false
private(set) var chatListFiltersNonEmpty: Bool = false
private func reloadFilters(firstUpdate: (() -> Void)? = nil) {
let filterItems = chatListFilterItems(context: self.context)
var notifiedFirstUpdate = false
@@ -561,6 +569,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
let isEmpty = resolvedItems.count <= 1
strongSelf.chatListFiltersNonEmpty = !isEmpty
if wasEmpty != isEmpty, strongSelf.displayNavigationBar {
strongSelf.navigationBar?.setSecondaryContentNode(isEmpty ? nil : strongSelf.tabContainerNode, animated: false)
}
@@ -568,8 +577,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
if let layout = strongSelf.validLayout {
if wasEmpty != isEmpty {
strongSelf.containerLayoutUpdated(layout, transition: .immediate)
} else {
strongSelf.tabContainerNode?.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: false, isEditing: false, canReorderAllChats: false, filtersLimit: filtersLimit, transitionFraction: 0.0, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
} else if let tabContainerNode = strongSelf.tabContainerNode {
tabContainerNode.update(size: CGSize(width: layout.size.width, height: 44.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: false, isEditing: false, canReorderAllChats: false, filtersLimit: filtersLimit, transitionFraction: 0.0, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
}
}
@@ -11,7 +11,6 @@ import SearchBarNode
import SearchUI
import ContactListUI
import ChatListUI
import SegmentedControlNode
import AttachmentTextInputPanelNode
import ChatPresentationInterfaceState
import ChatSendMessageActionUI
@@ -25,6 +24,10 @@ import ContextUI
import TextFormat
import ForwardAccessoryPanelNode
import CounterControllerTitleView
import SegmentControlComponent
import ComponentFlow
import ComponentDisplayAdapters
import EdgeEffect
final class PeerSelectionControllerNode: ASDisplayNode {
private let context: AccountContext
@@ -58,9 +61,10 @@ final class PeerSelectionControllerNode: ASDisplayNode {
private let emptyTextNode: ImmediateTextNode
private let emptyButtonNode: SolidRoundedButtonNode
private let toolbarBackgroundNode: NavigationBackgroundNode?
private let toolbarSeparatorNode: ASDisplayNode?
private let segmentedControlNode: SegmentedControlNode?
private let bottomEdgeEffectView: EdgeEffectView?
private let segmentedControl: ComponentView<Empty>?
private var segmentedControlItems: [String]?
private var segmentedControlSelectedIndex: Int = 0
private var textInputPanelNode: AttachmentTextInputPanelNode?
private var forwardAccessoryPanelNode: ForwardAccessoryPanelNode?
@@ -127,7 +131,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self.animationCache = context.animationCache
self.animationRenderer = context.animationRenderer
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(.default), chatLocation: .peer(id: PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil, businessIntro: nil)
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(.default), chatLocation: .peer(id: PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil, businessIntro: nil)
self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds) }
self.presentationInterfaceStatePromise.set(self.presentationInterfaceState)
@@ -170,20 +174,16 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
if hasChatListSelector && hasContactSelector {
self.toolbarBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
self.bottomEdgeEffectView = EdgeEffectView()
self.toolbarSeparatorNode = ASDisplayNode()
self.toolbarSeparatorNode?.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
let items = [
self.segmentedControl = ComponentView()
self.segmentedControlItems = [
self.presentationData.strings.DialogList_TabTitle,
self.presentationData.strings.Contacts_TabTitle
]
self.segmentedControlNode = SegmentedControlNode(theme: SegmentedControlTheme(theme: self.presentationData.theme), items: items.map { SegmentedControlItem(title: $0) }, selectedIndex: 0)
} else {
self.toolbarBackgroundNode = nil
self.toolbarSeparatorNode = nil
self.segmentedControlNode = nil
self.bottomEdgeEffectView = nil
self.segmentedControl = nil
}
var chatListCategories: [ChatListNodeAdditionalCategory] = []
@@ -357,13 +357,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
if hasChatListSelector && hasContactSelector {
self.segmentedControlNode!.selectedIndexChanged = { [weak self] index in
self?.indexChanged(index)
if let bottomEdgeEffectView = self.bottomEdgeEffectView {
self.view.addSubview(bottomEdgeEffectView)
}
self.addSubnode(self.toolbarBackgroundNode!)
self.addSubnode(self.toolbarSeparatorNode!)
self.addSubnode(self.segmentedControlNode!)
}
if let requirementsBackgroundNode = self.requirementsBackgroundNode, let requirementsSeparatorNode = self.requirementsSeparatorNode, let requirementsTextNode = self.requirementsTextNode {
@@ -700,7 +696,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
}
let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text?.string ?? "", link: link, apply: { [weak self] link in
let controller = chatTextLinkEditController(context: context, updatedPresentationData: (presentationData, .never()), text: text?.string ?? "", link: link, apply: { [weak self] link in
if let strongSelf = self, let inputMode = inputMode, let selectionRange = selectionRange {
if let link = link {
strongSelf.updateChatPresentationInterfaceState(animated: true, { state in
@@ -1016,9 +1012,6 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self.updateChatPresentationInterfaceState({ $0.updatedTheme(self.presentationData.theme) })
self.requirementsBackgroundNode?.updateColor(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
self.toolbarBackgroundNode?.updateColor(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
self.toolbarSeparatorNode?.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor
self.segmentedControlNode?.updateTheme(SegmentedControlTheme(theme: self.presentationData.theme))
if let (layout, navigationBarHeight, actualNavigationBarHeight) = self.containerLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, actualNavigationBarHeight: actualNavigationBarHeight, transition: .immediate)
@@ -1085,19 +1078,51 @@ final class PeerSelectionControllerNode: ASDisplayNode {
toolbarHeight = countPanelHeight
transition.updateFrame(node: countPanelNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - countPanelHeight), size: CGSize(width: layout.size.width, height: countPanelHeight)))
}
} else if let segmentedControlNode = self.segmentedControlNode, let toolbarBackgroundNode = self.toolbarBackgroundNode, let toolbarSeparatorNode = self.toolbarSeparatorNode {
} else if let segmentedControl = self.segmentedControl, let segmentedControlItems = self.segmentedControlItems, let bottomEdgeEffectView = self.bottomEdgeEffectView {
if let textPanelHeight = textPanelHeight {
toolbarHeight = textPanelHeight + accessoryHeight
} else {
toolbarHeight += 44.0
}
transition.updateFrame(node: toolbarBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: toolbarHeight)))
toolbarBackgroundNode.update(size: toolbarBackgroundNode.bounds.size, transition: transition)
transition.updateFrame(node: toolbarSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
let controlSize = segmentedControlNode.updateLayout(.sizeToFit(maximumWidth: layout.size.width, minimumWidth: 200.0, height: 32.0), transition: transition)
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight - 10.0), size: CGSize(width: layout.size.width, height: toolbarHeight + 10.0))
transition.updateFrame(view: bottomEdgeEffectView, frame: edgeEffectFrame)
bottomEdgeEffectView.update(content: self.presentationData.theme.list.plainBackgroundColor, blur: true, alpha: 0.3, rect: edgeEffectFrame, edge: .bottom, edgeSize: min(30.0, edgeEffectFrame.height), transition: ComponentTransition(transition))
let controlSize = segmentedControl.update(
transition: ComponentTransition(transition),
component: AnyComponent(SegmentControlComponent(
theme: self.presentationData.theme,
items: (0 ..< segmentedControlItems.count).map { index in
return SegmentControlComponent.Item(
id: AnyHashable(index),
title: segmentedControlItems[index]
)
},
selectedId: AnyHashable(self.segmentedControlSelectedIndex),
action: { [weak self] id in
guard let self, let index = id.base as? Int else {
return
}
self.segmentedControlSelectedIndex = max(0, min(segmentedControlItems.count - 1, index))
if let (layout, navigationBarHeight, actualNavigationBarHeight) = self.containerLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, actualNavigationBarHeight: actualNavigationBarHeight, transition: .animated(duration: 0.4, curve: .spring))
}
self.indexChanged(index)
}
)),
environment: {},
containerSize: CGSize(width: 200.0, height: 32.0)
)
let controlOrigin = layout.size.height - (textPanelHeight == nil ? toolbarHeight : 0.0) + floor((44.0 - controlSize.height) / 2.0)
transition.updateFrame(node: segmentedControlNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - controlSize.width) / 2.0), y: controlOrigin), size: controlSize))
let segmentedControlFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - controlSize.width) / 2.0), y: controlOrigin), size: controlSize)
if let segmentedControlView = segmentedControl.view {
if segmentedControlView.superview == nil {
self.view.addSubview(segmentedControlView)
}
transition.updateFrame(view: segmentedControlView, frame: segmentedControlFrame)
}
}
insets.top += navigationBarHeight
@@ -1363,7 +1388,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
}
}, fieldStyle: placeholderNode.fieldStyle
)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
@@ -1438,7 +1463,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if let requestDeactivateSearch = self?.requestDeactivateSearch {
requestDeactivateSearch()
}
})
}, fieldStyle: placeholderNode.fieldStyle)
self.searchDisplayController?.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .immediate)
self.searchDisplayController?.activate(insertSubnode: { [weak self, weak placeholderNode] subnode, isSearchBar in
@@ -1459,7 +1484,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
self.chatListNode?.accessibilityElementsHidden = false
self.mainContainerNode?.accessibilityElementsHidden = false
self.navigationBar?.setSecondaryContentNode(self.controller?.tabContainerNode, animated: true)
if let controller = self.controller, controller.chatListFiltersNonEmpty {
self.navigationBar?.setSecondaryContentNode(self.controller?.tabContainerNode, animated: true)
}
self.controller?.setDisplayNavigationBar(true, transition: .animated(duration: 0.5, curve: .spring))
searchDisplayController.deactivate(placeholder: placeholderNode)
@@ -1587,7 +1614,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}
}
} else if let contactListNode = self.contactListNode {
self.navigationBar?.setSecondaryContentNode(self.controller?.tabContainerNode, animated: false)
if let controller = self.controller, controller.chatListFiltersNonEmpty {
self.navigationBar?.setSecondaryContentNode(self.controller?.tabContainerNode, animated: false)
}
contactListNode.enableUpdates = false
if let mainContainerNode = self.mainContainerNode {