Files
GLEGram-iOS/GLEGram/SGFakeLocation/Sources/FakeLocationPickerController.swift
Leeksov 4647310322 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.
2026-04-06 09:48:12 +03:00

202 lines
8.1 KiB
Swift
Executable File

import Foundation
import UIKit
import MapKit
import CoreLocation
#if canImport(SGSimpleSettings)
import SGSimpleSettings
#endif
#if canImport(SGStrings)
import SGStrings
#endif
import Display
import TelegramPresentationData
public final class FakeLocationPickerController: ViewController {
private let presentationData: PresentationData
private var mapView: MKMapView!
private var currentPin: MKPointAnnotation?
private var saveButton: UIButton!
private var mapTypeControl: UISegmentedControl!
private var onSave: (() -> Void)?
public init(presentationData: PresentationData, onSave: (() -> Void)? = nil) {
self.presentationData = presentationData
self.onSave = onSave
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData))
let lang = presentationData.strings.baseLanguageCode
self.title = (lang == "ru" ? "Выбор местоположения" : "Pick Location")
let backItem = UIBarButtonItem(backButtonAppearanceWithTitle: presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed))
self.navigationItem.leftBarButtonItem = backItem
}
@objc private func backPressed() {
navigateBack()
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func loadView() {
super.loadView()
view.backgroundColor = presentationData.theme.list.plainBackgroundColor
mapView = MKMapView()
mapView.delegate = self
mapView.showsUserLocation = false
mapView.translatesAutoresizingMaskIntoConstraints = false
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(mapTapped(_:)))
mapView.addGestureRecognizer(tapGesture)
let lang = presentationData.strings.baseLanguageCode
let mapTypeItems = [
(lang == "ru" ? "Обычная" : "Standard"),
(lang == "ru" ? "Спутник" : "Satellite"),
(lang == "ru" ? "Гибрид" : "Hybrid")
]
mapTypeControl = UISegmentedControl(items: mapTypeItems)
mapTypeControl.selectedSegmentIndex = 0
mapTypeControl.addTarget(self, action: #selector(mapTypeChanged(_:)), for: .valueChanged)
mapTypeControl.translatesAutoresizingMaskIntoConstraints = false
saveButton = UIButton(type: .system)
let saveButtonTitle = (lang == "ru" ? "Сохранить" : "Save")
saveButton.setTitle(saveButtonTitle, for: .normal)
saveButton.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
saveButton.backgroundColor = presentationData.theme.list.itemAccentColor
saveButton.setTitleColor(.white, for: .normal)
saveButton.layer.cornerRadius = 12
saveButton.addTarget(self, action: #selector(savePressed), for: .touchUpInside)
saveButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(mapView)
view.addSubview(mapTypeControl)
view.addSubview(saveButton)
NSLayoutConstraint.activate([
mapView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
saveButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
saveButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),
saveButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16),
saveButton.heightAnchor.constraint(equalToConstant: 50),
mapTypeControl.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
mapTypeControl.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),
mapTypeControl.bottomAnchor.constraint(equalTo: saveButton.topAnchor, constant: -12),
mapTypeControl.heightAnchor.constraint(equalToConstant: 32)
])
view.bringSubviewToFront(saveButton)
view.bringSubviewToFront(mapTypeControl)
loadSavedLocation()
}
@objc private func mapTapped(_ gesture: UITapGestureRecognizer) {
let point = gesture.location(in: mapView)
let coordinate = mapView.convert(point, toCoordinateFrom: mapView)
addPinAt(coordinate: coordinate)
#if canImport(SGSimpleSettings)
SGSimpleSettings.shared.fakeLatitude = coordinate.latitude
SGSimpleSettings.shared.fakeLongitude = coordinate.longitude
SGSimpleSettings.shared.synchronizeShared()
#endif
}
@objc private func mapTypeChanged(_ sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
mapView.mapType = .standard
case 1:
mapView.mapType = .satellite
case 2:
mapView.mapType = .hybrid
default:
break
}
}
@objc private func savePressed() {
#if canImport(SGSimpleSettings)
if let coordinate = currentPin?.coordinate {
SGSimpleSettings.shared.fakeLatitude = coordinate.latitude
SGSimpleSettings.shared.fakeLongitude = coordinate.longitude
SGSimpleSettings.shared.synchronizeShared()
onSave?()
}
#endif
navigateBack()
}
private func navigateBack() {
if let nav = self.navigationController, nav.viewControllers.count > 1 {
nav.popViewController(animated: true)
} else {
self.dismiss(animated: true)
}
}
private func loadSavedLocation() {
#if canImport(SGSimpleSettings)
let latitude = SGSimpleSettings.shared.fakeLatitude
let longitude = SGSimpleSettings.shared.fakeLongitude
if latitude != 0.0 && longitude != 0.0 {
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
addPinAt(coordinate: coordinate)
let region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 1000, longitudinalMeters: 1000)
mapView.setRegion(region, animated: false)
} else {
// Default to Moscow if no location is set
let defaultCoordinate = CLLocationCoordinate2D(latitude: 55.7558, longitude: 37.6176)
let region = MKCoordinateRegion(center: defaultCoordinate, latitudinalMeters: 10000, longitudinalMeters: 10000)
mapView.setRegion(region, animated: false)
}
#else
let defaultCoordinate = CLLocationCoordinate2D(latitude: 55.7558, longitude: 37.6176)
let region = MKCoordinateRegion(center: defaultCoordinate, latitudinalMeters: 10000, longitudinalMeters: 10000)
mapView.setRegion(region, animated: false)
#endif
}
private func addPinAt(coordinate: CLLocationCoordinate2D) {
if let existingPin = currentPin {
mapView.removeAnnotation(existingPin)
}
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
currentPin = annotation
mapView.addAnnotation(annotation)
}
}
extension FakeLocationPickerController: MKMapViewDelegate {
public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let identifier = "FakeLocationPin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}