Created
June 12, 2025 05:51
-
-
Save BekNaji/8170cf40479546dbc0f56b3bb5164a1b to your computer and use it in GitHub Desktop.
pretend screenshot in flutter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import Flutter | |
@main | |
@objc class AppDelegate: FlutterAppDelegate { | |
var eventSink: FlutterEventSink? | |
var field = UITextField() | |
override func application( | |
_ application: UIApplication, | |
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? | |
) -> Bool { | |
GeneratedPluginRegistrant.register(with: self) | |
let result = super.application(application, didFinishLaunchingWithOptions: launchOptions) | |
let controller = window.rootViewController as! FlutterViewController | |
let eventChannel = FlutterEventChannel(name: "screen_capture_event", binaryMessenger: controller.binaryMessenger) | |
eventChannel.setStreamHandler(self) | |
NotificationCenter.default.addObserver( | |
self, | |
selector: #selector(handleScreenCaptureChange), | |
name: UIScreen.capturedDidChangeNotification, | |
object: nil | |
) | |
addSecuredView() | |
return result | |
//return super.application(application, didFinishLaunchingWithOptions: launchOptions) | |
} | |
override func applicationWillResignActive(_ application: UIApplication) { | |
field.isSecureTextEntry = false | |
} | |
override func applicationDidBecomeActive(_ application: UIApplication) { | |
field.isSecureTextEntry = true | |
} | |
private func addSecuredView() { | |
if (!window.subviews.contains(field)) { | |
window.addSubview(field) | |
field.centerYAnchor.constraint(equalTo: window.centerYAnchor).isActive = true | |
field.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true | |
window.layer.superlayer?.addSublayer(field.layer) | |
if #available(iOS 17.0, *) { | |
field.layer.sublayers?.last?.addSublayer(window.layer) | |
} else { | |
field.layer.sublayers?.first?.addSublayer(window.layer) | |
} | |
} | |
} | |
@objc func handleScreenCaptureChange() { | |
let isCaptured = UIScreen.main.isCaptured | |
eventSink?(isCaptured) | |
} | |
@objc func userDidTakeScreenshot() { | |
print("📸 Screenshot detected!") | |
eventSink?(true) | |
} | |
} | |
extension UIWindow { | |
func makeSecure() { | |
let secureField = UITextField() | |
secureField.isSecureTextEntry = true | |
secureField.isHidden = true | |
self.addSubview(secureField) | |
secureField.translatesAutoresizingMaskIntoConstraints = false | |
secureField.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true | |
secureField.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true | |
// Important: Add its layer to your window | |
self.layer.superlayer?.addSublayer(secureField.layer) | |
} | |
} | |
extension AppDelegate: FlutterStreamHandler { | |
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { | |
self.eventSink = events | |
events(UIScreen.main.isCaptured) | |
return nil | |
} | |
func onCancel(withArguments arguments: Any?) -> FlutterError? { | |
self.eventSink = nil | |
return nil | |
} | |
func sendDataToFlutter(data: Any) { | |
eventSink?(data) | |
} | |
} | |
class ScreenCaptureHandler: NSObject, FlutterStreamHandler { | |
var isCaptured: Bool | |
init(isCaptured: Bool) { | |
self.isCaptured = isCaptured | |
} | |
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { | |
events(isCaptured) | |
return nil | |
} | |
func onCancel(withArguments arguments: Any?) -> FlutterError? { | |
return nil | |
} | |
} | |
//class CustomViewController: UIViewController { | |
// private var sdkViewController: UIViewController? | |
// | |
// override func viewDidLoad() { | |
// super.viewDidLoad() | |
// view.backgroundColor = .white | |
// | |
// if let sdkVC = sdkViewController { | |
// addChild(sdkVC) | |
// view.addSubview(sdkVC.view) | |
// sdkVC.view.frame = view.bounds | |
// sdkVC.didMove(toParent: self) | |
// } | |
// | |
// let backButton = UIBarButtonItem(image: UIImage(systemName: "chevron.backward"), style: .plain, target: self, action: #selector(dismissViewController)) | |
// backButton.tintColor = UIColor(hex: "#a30041") | |
// self.navigationItem.leftBarButtonItem = backButton | |
// self.navigationItem.title = "Чат" | |
// } | |
// | |
// @objc func dismissViewController() { | |
// self.dismiss(animated: true, completion: nil) | |
// } | |
// | |
// func setSDKViewController(_ viewController: UIViewController) { | |
// self.sdkViewController = viewController | |
// } | |
//} | |
// | |
//extension UIColor { | |
// convenience init?(hex: String) { | |
// var hexCleaned = hex.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "#", with: "") | |
// var rgb: UInt64 = 0 | |
// Scanner(string: hexCleaned).scanHexInt64(&rgb) | |
// self.init( | |
// red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, | |
// green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0, | |
// blue: CGFloat(rgb & 0x0000FF) / 255.0, | |
// alpha: 1.0 | |
// ) | |
// } | |
//} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment