Merge commit '7621e2f8dec938cf48181c8b10afc9b01f444e68' into beta

This commit is contained in:
Ilya Laktyushin
2025-12-06 02:17:48 +04:00
commit 8344b97e03
28070 changed files with 7995182 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
load("@build_bazel_rules_apple//apple:ios.bzl",
"ios_application",
)
load("@build_bazel_rules_swift//swift:swift.bzl",
"swift_library",
)
load("//build-system/bazel-utils:plist_fragment.bzl",
"plist_fragment",
)
load(
"@rules_xcodeproj//xcodeproj:defs.bzl",
"top_level_target",
"top_level_targets",
"xcodeproj",
"xcode_provisioning_profile",
)
load("@build_bazel_rules_apple//apple:apple.bzl", "local_provisioning_profile")
load(
"@build_configuration//:variables.bzl",
"telegram_bazel_path",
)
filegroup(
name = "AppResources",
srcs = glob([
"Resources/**/*",
], exclude = ["Resources/**/.*"]),
)
swift_library(
name = "Lib",
srcs = glob([
"Sources/**/*.swift",
]),
data = [
":AppResources",
],
deps = [
"//submodules/Display",
"//submodules/MetalEngine",
"//submodules/TelegramPresentationData",
"//submodules/TelegramUI/Components/Calls/CallScreen",
],
)
plist_fragment(
name = "BuildNumberInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleVersion</key>
<string>1</string>
"""
)
plist_fragment(
name = "VersionInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleShortVersionString</key>
<string>1.0</string>
"""
)
plist_fragment(
name = "AppNameInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleDisplayName</key>
<string>Test</string>
"""
)
plist_fragment(
name = "AppInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Test</string>
<key>CFBundleIdentifier</key>
<string>org.telegram.Telegram-iOS</string>
<key>CFBundleName</key>
<string>Telegram</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIFileSharingEnabled</key>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIViewEdgeAntialiasing</key>
<false/>
<key>UIViewGroupOpacity</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
"""
)
ios_application(
name = "CallUITest",
bundle_id = "org.telegram.Telegram-iOS",
families = ["iphone", "ipad"],
minimum_os_version = "12.0",
provisioning_profile = "@build_configuration//provisioning:Telegram.mobileprovision",
infoplists = [
":AppInfoPlist",
":BuildNumberInfoPlist",
":VersionInfoPlist",
],
resources = [
"//Tests/Common:LaunchScreen",
],
frameworks = [
],
deps = [
"//Tests/Common:Main",
":Lib",
],
visibility = ["//visibility:public"],
)
xcodeproj(
name = "CallUITest_xcodeproj",
build_mode = "bazel",
bazel_path = telegram_bazel_path,
project_name = "CallUITest",
tags = ["manual"],
top_level_targets = top_level_targets(
labels = [
":CallUITest",
],
target_environments = ["device", "simulator"],
),
xcode_configurations = {
"Debug": {
"//command_line_option:compilation_mode": "dbg",
},
"Release": {
"//command_line_option:compilation_mode": "opt",
},
},
default_xcode_configuration = "Debug"
)
Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
import Foundation
import UIKit
@objc(Application)
public final class Application: UIApplication {
}
@objc(AppDelegate)
public final class AppDelegate: NSObject, UIApplicationDelegate {
public var window: UIWindow?
public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let window = UIWindow()
self.window = window
window.rootViewController = ViewController()
window.makeKeyAndVisible()
application.internalSetStatusBarStyle(.lightContent, animated: false)
return true
}
}
@@ -0,0 +1,212 @@
import Foundation
import UIKit
import MetalEngine
import Display
import CallScreen
import ComponentFlow
import TelegramPresentationData
private extension UIScreen {
private static let cornerRadiusKey: String = {
let components = ["Radius", "Corner", "display", "_"]
return components.reversed().joined()
}()
var displayCornerRadius: CGFloat {
guard let cornerRadius = self.value(forKey: Self.cornerRadiusKey) as? CGFloat else {
assertionFailure("Failed to detect screen corner radius")
return 0
}
return cornerRadius
}
}
public final class ViewController: UIViewController {
private var callScreenView: PrivateCallScreen?
private var callState: PrivateCallScreen.State = PrivateCallScreen.State(
strings: defaultPresentationStrings,
lifecycleState: .connecting,
name: "Emma Walters",
shortName: "Emma",
avatarImage: UIImage(named: "test"),
audioOutput: .internalSpeaker,
isLocalAudioMuted: false,
isRemoteAudioMuted: false,
localVideo: nil,
remoteVideo: nil,
isRemoteBatteryLow: false,
enableVideoSharpening: false
)
private var currentLayout: (size: CGSize, insets: UIEdgeInsets)?
private var viewLayoutTransition: Transition?
private var audioLevelTimer: Foundation.Timer?
override public func viewDidLoad() {
super.viewDidLoad()
self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
MetalEngine.shared.rootLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: -101.0), size: CGSize(width: 100.0, height: 100.0))
self.view.backgroundColor = .black
SharedDisplayLinkDriver.shared.updateForegroundState(true)
let callScreenView = PrivateCallScreen(frame: self.view.bounds)
self.callScreenView = callScreenView
self.view.addSubview(callScreenView)
callScreenView.speakerAction = { [weak self] in
guard let self else {
return
}
switch self.callState.lifecycleState {
case .requesting:
self.callState.lifecycleState = .ringing
case .ringing:
self.callState.lifecycleState = .connecting
case .connecting:
self.callState.lifecycleState = .active(PrivateCallScreen.State.ActiveState(
startTime: Date().timeIntervalSince1970,
signalInfo: PrivateCallScreen.State.SignalInfo(quality: 1.0),
emojiKey: ["😂", "😘", "😍", "😊"]
))
case var .active(activeState):
activeState.signalInfo.quality = activeState.signalInfo.quality == 1.0 ? 0.1 : 1.0
self.callState.lifecycleState = .active(activeState)
case .reconnecting:
self.callState.lifecycleState = .active(PrivateCallScreen.State.ActiveState(
startTime: Date().timeIntervalSince1970,
signalInfo: PrivateCallScreen.State.SignalInfo(quality: 1.0),
emojiKey: ["😂", "😘", "😍", "😊"]
))
case .terminated:
self.callState.lifecycleState = .active(PrivateCallScreen.State.ActiveState(
startTime: Date().timeIntervalSince1970,
signalInfo: PrivateCallScreen.State.SignalInfo(quality: 1.0),
emojiKey: ["😂", "😘", "😍", "😊"]
))
}
switch self.callState.lifecycleState {
case .terminated:
if let audioLevelTimer = self.audioLevelTimer {
self.audioLevelTimer = nil
audioLevelTimer.invalidate()
}
default:
if self.audioLevelTimer == nil {
let startTime = CFAbsoluteTimeGetCurrent()
self.audioLevelTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 1.0 / 60.0, repeats: true, block: { [weak self] _ in
guard let self, let callScreenView = self.callScreenView else {
return
}
let timestamp = CFAbsoluteTimeGetCurrent() - startTime
let stream1 = sin(timestamp * Double.pi * 2.0)
let stream2 = sin(2.0 * timestamp * Double.pi * 2.0)
let stream3 = sin(3.0 * timestamp * Double.pi * 2.0)
let result = stream1 + stream2 + stream3
callScreenView.addIncomingAudioLevel(value: abs(Float(result)))
})
}
}
self.update(transition: .spring(duration: 0.4))
}
callScreenView.flipCameraAction = { [weak self] in
guard let self else {
return
}
if let input = self.callState.localVideo as? FileVideoSource {
input.sourceId = input.sourceId == 0 ? 1 : 0
//input.fixedRotationAngle = input.sourceId == 0 ? Float.pi * 0.5 : Float.pi * 0.5
//input.sizeMultiplicator = input.sourceId == 0 ? CGPoint(x: 1.0, y: 1.0) : CGPoint(x: 1.0, y: 0.5)
}
}
callScreenView.videoAction = { [weak self] in
guard let self else {
return
}
if self.callState.localVideo == nil {
self.callState.localVideo = FileVideoSource(device: MetalEngine.shared.device, url: Bundle.main.url(forResource: "test3", withExtension: "mp4")!, fixedRotationAngle: Float.pi * 0.5)
} else {
self.callState.localVideo = nil
}
self.update(transition: .spring(duration: 0.4))
}
callScreenView.microhoneMuteAction = {
if self.callState.remoteVideo == nil {
self.callState.remoteVideo = FileVideoSource(device: MetalEngine.shared.device, url: Bundle.main.url(forResource: "test4", withExtension: "mp4")!, fixedRotationAngle: Float.pi * 1.0)
} else {
self.callState.remoteVideo = nil
}
self.update(transition: .spring(duration: 0.4))
}
callScreenView.endCallAction = { [weak self] in
guard let self else {
return
}
self.callState.lifecycleState = .terminated(PrivateCallScreen.State.TerminatedState(duration: 82.0, reason: .hangUp))
self.callState.remoteVideo = nil
self.callState.localVideo = nil
self.callState.isLocalAudioMuted = false
self.callState.isRemoteBatteryLow = false
self.update(transition: .spring(duration: 0.4))
}
callScreenView.backAction = { [weak self] in
guard let self else {
return
}
self.callState.isLocalAudioMuted = !self.callState.isLocalAudioMuted
self.update(transition: .spring(duration: 0.4))
}
callScreenView.closeAction = { [weak self] in
guard let self else {
return
}
self.callScreenView?.speakerAction?()
}
}
private func update(transition: Transition) {
if let (size, insets) = self.currentLayout {
self.update(size: size, insets: insets, interfaceOrientation: self.interfaceOrientation, transition: transition)
}
}
private func update(size: CGSize, insets: UIEdgeInsets, interfaceOrientation: UIInterfaceOrientation, transition: Transition) {
guard let callScreenView = self.callScreenView else {
return
}
transition.setFrame(view: callScreenView, frame: CGRect(origin: CGPoint(), size: size))
callScreenView.update(size: size, insets: insets, interfaceOrientation: interfaceOrientation, screenCornerRadius: UIScreen.main.displayCornerRadius, state: self.callState, transition: transition)
}
override public func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let safeAreaLayoutGuide = self.view.safeAreaLayoutGuide
let size = self.view.bounds.size
let insets = UIEdgeInsets(top: safeAreaLayoutGuide.layoutFrame.minY, left: safeAreaLayoutGuide.layoutFrame.minX, bottom: size.height - safeAreaLayoutGuide.layoutFrame.maxY, right: safeAreaLayoutGuide.layoutFrame.minX)
let transition = self.viewLayoutTransition ?? .immediate
self.viewLayoutTransition = nil
if let currentLayout = self.currentLayout, currentLayout == (size, insets) {
} else {
self.currentLayout = (size, insets)
self.update(size: size, insets: insets, interfaceOrientation: self.interfaceOrientation, transition: transition)
}
}
override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.viewLayoutTransition = .easeInOut(duration: 0.3)
}
}