GLEGram 12.5 — Initial public release

Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
This commit is contained in:
Leeksov
2026-04-06 09:48:12 +03:00
commit 4647310322
39685 changed files with 11052678 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ScreenCaptureDetection",
module_name = "ScreenCaptureDetection",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
],
visibility = [
"//visibility:public",
],
)
@@ -0,0 +1,133 @@
import Foundation
import SwiftSignalKit
import UIKit
public enum ScreenCaptureEvent {
case still
case video
}
private final class ScreenRecordingObserver: NSObject {
let f: (Bool) -> Void
init(_ f: @escaping (Bool) -> Void) {
self.f = f
super.init()
UIScreen.main.addObserver(self, forKeyPath: "captured", options: [.new], context: nil)
}
func clear() {
UIScreen.main.removeObserver(self, forKeyPath: "captured")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "captured" {
if let value = change?[.newKey] as? Bool {
self.f(value)
}
}
}
}
private func screenRecordingActive() -> Signal<Bool, NoError> {
return Signal { subscriber in
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
subscriber.putNext(UIScreen.main.isCaptured)
let observer = ScreenRecordingObserver({ value in
subscriber.putNext(value)
})
return ActionDisposable {
Queue.mainQueue().async {
observer.clear()
}
}
} else {
subscriber.putNext(false)
return EmptyDisposable
}
} |> runOn(Queue.mainQueue())
}
public func screenCaptureEvents() -> Signal<ScreenCaptureEvent, NoError> {
return Signal { subscriber in
let observer = NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: .main, using: { _ in
subscriber.putNext(.still)
})
var previous = false
let screenRecordingDisposable = screenRecordingActive().start(next: { value in
if value != previous {
previous = value
if value {
subscriber.putNext(.video)
}
}
})
return ActionDisposable {
Queue.mainQueue().async {
NotificationCenter.default.removeObserver(observer)
screenRecordingDisposable.dispose()
}
}
}
|> runOn(Queue.mainQueue())
}
public final class ScreenCaptureDetectionManager {
private var observer: NSObjectProtocol?
private var screenRecordingDisposable: Disposable?
private var screenRecordingCheckTimer: SwiftSignalKit.Timer?
public var isRecordingActive = false
public init(check: @escaping () -> Bool) {
self.observer = NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: .main, using: { [weak self] _ in
guard let _ = self else {
return
}
let _ = check()
})
self.screenRecordingDisposable = screenRecordingActive().start(next: { [weak self] value in
Queue.mainQueue().async {
guard let strongSelf = self else {
return
}
var value = value
#if DEBUG
value = !"".isEmpty
#endif
strongSelf.isRecordingActive = value
if value {
if strongSelf.screenRecordingCheckTimer == nil {
strongSelf.screenRecordingCheckTimer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: {
guard let strongSelf = self else {
return
}
if check() {
strongSelf.screenRecordingCheckTimer?.invalidate()
strongSelf.screenRecordingCheckTimer = nil
}
}, queue: Queue.mainQueue())
strongSelf.screenRecordingCheckTimer?.start()
}
} else if strongSelf.screenRecordingCheckTimer != nil {
strongSelf.screenRecordingCheckTimer?.invalidate()
strongSelf.screenRecordingCheckTimer = nil
}
}
})
}
deinit {
if let observer = self.observer {
NotificationCenter.default.removeObserver(observer)
}
self.screenRecordingDisposable?.dispose()
self.screenRecordingCheckTimer?.invalidate()
self.screenRecordingCheckTimer = nil
}
}