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
@@ -95,6 +95,8 @@ swift_library(
"//submodules/TelegramCallsUI",
"//submodules/TelegramUI/Components/Stories/StoryContainerScreen",
"//submodules/TelegramUI/Components/ChatEntityKeyboardInputNode",
"//submodules/TelegramUI/Components/LiquidLens",
"//submodules/TelegramUI/Components/TabSelectionRecognizer",
],
visibility = [
"//visibility:public",
@@ -2097,7 +2097,7 @@ private final class CameraScreenComponent: CombinedComponent {
if !isSticker, case .none = component.cameraState.recording, component.cameraState.isStreaming == .none && !state.isTransitioning && hasAllRequiredAccess && component.cameraState.collageProgress < 1.0 - .ulpOfOne {
let availableModeControlSize: CGSize
if isTablet {
availableModeControlSize = CGSize(width: panelWidth, height: 120.0)
availableModeControlSize = CGSize(width: floor(panelWidth), height: 120.0)
} else {
availableModeControlSize = availableSize
}
@@ -2131,7 +2131,6 @@ private final class CameraScreenComponent: CombinedComponent {
modeControlPosition = CGPoint(x: availableSize.width / 2.0, y: availableSize.height - environment.safeInsets.bottom + modeControl.size.height / 2.0 + controlsBottomInset + 16.0)
}
context.add(modeControl
.clipsToBounds(true)
.position(modeControlPosition)
.appear(.default(alpha: true))
.disappear(.default(alpha: true))
@@ -5,6 +5,8 @@ import ComponentFlow
import MultilineTextComponent
import TelegramPresentationData
import GlassBackgroundComponent
import LiquidLens
import TabSelectionRecognizer
extension CameraMode {
func title(strings: PresentationStrings) -> String {
@@ -70,28 +72,17 @@ final class ModeComponent: Component {
final class View: UIView, ComponentTaggedView {
private var component: ModeComponent?
private var state: EmptyComponentState?
final class ItemView: HighlightTrackingButton {
var pressed: () -> Void = {
}
init() {
super.init(frame: .zero)
self.isExclusiveTouch = true
self.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside)
}
required init(coder: NSCoder) {
preconditionFailure()
}
@objc func buttonPressed() {
self.pressed()
}
func update(isTablet: Bool, value: String, selected: Bool, tintColor: UIColor) -> CGSize {
let accentColor: UIColor
let normalColor: UIColor
@@ -113,9 +104,15 @@ final class ModeComponent: Component {
}
private var backgroundView = UIView()
private var glassContainerView = GlassBackgroundContainerView()
private var selectionView = GlassBackgroundView()
private var itemViews: [Int32: ItemView] = [:]
private var backgroundContainer = GlassBackgroundContainerView()
private var liquidLensView: LiquidLensView?
private var itemViews: [AnyHashable: ItemView] = [:]
private var selectedItemViews: [AnyHashable: ItemView] = [:]
private var tabSelectionRecognizer: TabSelectionRecognizer?
private var selectionGestureState: (startX: CGFloat, currentX: CGFloat, itemId: AnyHashable)?
public func matches(tag: Any) -> Bool {
if let component = self.component, let componentTag = component.tag {
@@ -132,12 +129,11 @@ final class ModeComponent: Component {
self.backgroundView.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.11)
self.backgroundView.layer.cornerRadius = 24.0
self.layer.allowsGroupOpacity = true
self.addSubview(self.backgroundView)
self.backgroundView.addSubview(self.glassContainerView)
self.glassContainerView.contentView.addSubview(self.selectionView)
self.backgroundView.addSubview(self.backgroundContainer)
}
required init?(coder aDecoder: NSCoder) {
@@ -162,14 +158,82 @@ final class ModeComponent: Component {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return self.backgroundView.frame.contains(point)
}
func update(component: ModeComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
self.component = component
let isTablet = component.isTablet
let updatedMode = component.updatedMode
private func item(at point: CGPoint) -> AnyHashable? {
var closestItem: (AnyHashable, CGFloat)?
for (id, itemView) in self.itemViews {
if itemView.frame.contains(point) {
return id
} else {
let distance = abs(point.x - itemView.center.x)
if let closestItemValue = closestItem {
if closestItemValue.1 > distance {
closestItem = (id, distance)
}
} else {
closestItem = (id, distance)
}
}
}
return closestItem?.0
}
@objc private func onTabSelectionGesture(_ recognizer: TabSelectionRecognizer) {
guard let component = self.component, let liquidLensView = self.liquidLensView else {
return
}
let location = recognizer.location(in: liquidLensView.contentView)
switch recognizer.state {
case .began:
if let itemId = self.item(at: location), let itemView = self.itemViews[itemId] {
let startX = itemView.frame.minX - 4.0
self.selectionGestureState = (startX, startX, itemId)
self.state?.updated(transition: .spring(duration: 0.4), isLocal: true)
}
case .changed:
if var selectionGestureState = self.selectionGestureState {
selectionGestureState.currentX = selectionGestureState.startX + recognizer.translation(in: self).x
if let itemId = self.item(at: location) {
selectionGestureState.itemId = itemId
}
self.selectionGestureState = selectionGestureState
self.state?.updated(transition: .immediate, isLocal: true)
}
case .ended, .cancelled:
if let selectionGestureState = self.selectionGestureState {
self.selectionGestureState = nil
if case .ended = recognizer.state {
guard let item = component.availableModes.first(where: { AnyHashable($0.rawValue) == selectionGestureState.itemId }) else {
return
}
component.updatedMode(item)
}
self.state?.updated(transition: .spring(duration: 0.4), isLocal: true)
}
default:
break
}
}
func update(component: ModeComponent, availableSize: CGSize, state: EmptyComponentState, transition: ComponentTransition) -> CGSize {
self.component = component
self.state = state
let isTablet = component.isTablet
let liquidLensView: LiquidLensView
if let current = self.liquidLensView {
liquidLensView = current
} else {
liquidLensView = LiquidLensView(kind: isTablet ? .noContainer : .externalContainer)
self.liquidLensView = liquidLensView
self.backgroundContainer.contentView.addSubview(liquidLensView)
let tabSelectionRecognizer = TabSelectionRecognizer(target: self, action: #selector(self.onTabSelectionGesture(_:)))
self.tabSelectionRecognizer = tabSelectionRecognizer
liquidLensView.addGestureRecognizer(tabSelectionRecognizer)
}
self.glassContainerView.isHidden = component.isTablet
self.backgroundView.backgroundColor = component.isTablet ? .clear : UIColor(rgb: 0xffffff, alpha: 0.11)
let inset: CGFloat = 23.0
@@ -177,28 +241,36 @@ final class ModeComponent: Component {
var i = 0
var itemFrame = CGRect(origin: isTablet ? .zero : CGPoint(x: inset, y: 0.0), size: buttonSize)
var selectedCenter = itemFrame.minX
var selectedFrame = itemFrame
var validKeys: Set<Int32> = Set()
var validKeys: Set<AnyHashable> = Set()
for mode in component.availableModes.reversed() {
let id = mode.rawValue
validKeys.insert(id)
let itemView: ItemView
if let current = self.itemViews[id] {
let selectedItemView: ItemView
if let current = self.itemViews[id], let currentSelected = self.selectedItemViews[id] {
itemView = current
selectedItemView = currentSelected
} else {
itemView = ItemView()
self.backgroundView.addSubview(itemView)
itemView.isUserInteractionEnabled = false
self.itemViews[id] = itemView
}
itemView.pressed = {
updatedMode(mode)
liquidLensView.contentView.addSubview(itemView)
selectedItemView = ItemView()
selectedItemView.isUserInteractionEnabled = false
self.selectedItemViews[id] = selectedItemView
liquidLensView.selectedContentView.addSubview(selectedItemView)
}
let itemSize = itemView.update(isTablet: component.isTablet, value: mode.title(strings: component.strings), selected: mode == component.currentMode, tintColor: component.tintColor)
let itemSize = itemView.update(isTablet: component.isTablet, value: mode.title(strings: component.strings), selected: false, tintColor: component.tintColor)
itemView.bounds = CGRect(origin: .zero, size: itemSize)
let _ = selectedItemView.update(isTablet: component.isTablet, value: mode.title(strings: component.strings), selected: true, tintColor: component.tintColor)
selectedItemView.bounds = CGRect(origin: .zero, size: itemSize)
itemFrame = CGRect(origin: itemFrame.origin, size: itemSize)
if mode == component.currentMode {
@@ -207,21 +279,17 @@ final class ModeComponent: Component {
if isTablet {
itemView.center = CGPoint(x: availableSize.width / 2.0, y: itemFrame.midY)
if mode == component.currentMode {
selectedCenter = itemFrame.midY
}
selectedItemView.center = itemView.center
itemFrame = itemFrame.offsetBy(dx: 0.0, dy: tabletButtonSize.height + spacing)
} else {
itemView.center = CGPoint(x: itemFrame.midX, y: itemFrame.midY)
if mode == component.currentMode {
selectedCenter = itemFrame.midX
}
selectedItemView.center = itemView.center
itemFrame = itemFrame.offsetBy(dx: itemFrame.width + spacing, dy: 0.0)
}
i += 1
}
var removeKeys: [Int32] = []
var removeKeys: [AnyHashable] = []
for (id, itemView) in self.itemViews {
if !validKeys.contains(id) {
removeKeys.append(id)
@@ -237,10 +305,12 @@ final class ModeComponent: Component {
let totalSize: CGSize
let size: CGSize
var cornerRadius: CGFloat?
if isTablet {
totalSize = CGSize(width: availableSize.width, height: tabletButtonSize.height * CGFloat(component.availableModes.count) + spacing * CGFloat(component.availableModes.count - 1))
size = CGSize(width: availableSize.width, height: availableSize.height)
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: 0.0, y: availableSize.height / 2.0 - selectedCenter), size: totalSize))
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: totalSize))
cornerRadius = 20.0
} else {
size = CGSize(width: availableSize.width, height: buttonSize.height)
totalSize = CGSize(width: itemFrame.minX - spacing + inset, height: buttonSize.height)
@@ -248,12 +318,26 @@ final class ModeComponent: Component {
}
let containerFrame = CGRect(origin: .zero, size: self.backgroundView.frame.size)
transition.setFrame(view: self.glassContainerView, frame: containerFrame)
transition.setFrame(view: self.backgroundContainer, frame: containerFrame)
let selectionFrame = selectedFrame.insetBy(dx: -20.0, dy: 3.0)
self.glassContainerView.update(size: containerFrame.size, isDark: true, transition: .immediate)
self.selectionView.update(size: selectionFrame.size, cornerRadius: selectionFrame.height * 0.5, isDark: true, tintColor: .init(kind: .custom, color: UIColor(rgb: 0xffffff, alpha: 0.16)), transition: transition)
transition.setFrame(view: self.selectionView, frame: selectionFrame)
let selectionFrame = selectedFrame.insetBy(dx: -23.0, dy: 3.0)
var lensSelection: (origin: CGPoint, size: CGSize)
if let selectionGestureState = self.selectionGestureState, !isTablet {
lensSelection = (CGPoint(x: selectionGestureState.currentX, y: 0.0), selectionFrame.size)
} else {
lensSelection = (CGPoint(x: selectionFrame.minX, y: selectionFrame.minY), selectionFrame.size)
}
if isTablet {
lensSelection.size.width = size.width
} else {
lensSelection.size.height = containerFrame.size.height
lensSelection.origin.y = 0.0
}
transition.setFrame(view: liquidLensView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: containerFrame.size))
liquidLensView.update(size: containerFrame.size, cornerRadius: cornerRadius, selectionOrigin: CGPoint(x: max(0.0, min(lensSelection.origin.x, containerFrame.size.width - lensSelection.size.width)), y: lensSelection.origin.y), selectionSize: lensSelection.size, inset: 3.0, isDark: true, isLifted: self.selectionGestureState != nil && !isTablet, isCollapsed: false, transition: transition)
self.backgroundContainer.update(size: containerFrame.size, isDark: true, transition: .immediate)
return size
}
@@ -264,7 +348,7 @@ final class ModeComponent: Component {
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
return view.update(component: self, availableSize: availableSize, transition: transition)
return view.update(component: self, availableSize: availableSize, state: state, transition: transition)
}
}