mirror of
https://github.com/GLEGram/GLEGram-iOS.git
synced 2026-04-23 19:36:26 +02:00
4647310322
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.
260 lines
17 KiB
Swift
Executable File
260 lines
17 KiB
Swift
Executable File
// MARK: Swiftgram – Fake Profile settings: target user, name/username/phone/ID, badges
|
||
import Foundation
|
||
import UIKit
|
||
import Display
|
||
import SwiftSignalKit
|
||
import TelegramPresentationData
|
||
import ItemListUI
|
||
import PresentationDataUtils
|
||
import AccountContext
|
||
import SGItemListUI
|
||
import SGSimpleSettings
|
||
|
||
private enum FakeProfileSection: Int32, SGItemListSection {
|
||
case targetUser = 0
|
||
case personalData
|
||
case badges
|
||
}
|
||
|
||
private enum FakeProfileEntry: ItemListNodeEntry {
|
||
case targetHeader(id: Int, text: String)
|
||
case targetUserId(id: Int, text: String, placeholder: String)
|
||
case targetNotice(id: Int, text: String)
|
||
case personalHeader(id: Int, text: String)
|
||
case firstName(id: Int, text: String, placeholder: String)
|
||
case lastName(id: Int, text: String, placeholder: String)
|
||
case username(id: Int, text: String, placeholder: String)
|
||
case phone(id: Int, text: String, placeholder: String)
|
||
case fakeId(id: Int, text: String, placeholder: String)
|
||
case personalNotice(id: Int, text: String)
|
||
case badgesHeader(id: Int, text: String)
|
||
case premium(id: Int, title: String, subtext: String?, value: Bool)
|
||
case verified(id: Int, title: String, subtext: String?, value: Bool)
|
||
case scam(id: Int, title: String, subtext: String?, value: Bool)
|
||
case fake(id: Int, title: String, subtext: String?, value: Bool)
|
||
case support(id: Int, title: String, subtext: String?, value: Bool)
|
||
case bot(id: Int, title: String, subtext: String?, value: Bool)
|
||
case badgesNotice(id: Int, text: String)
|
||
|
||
var id: Int { stableId }
|
||
var section: ItemListSectionId {
|
||
switch self {
|
||
case .targetHeader, .targetUserId, .targetNotice: return FakeProfileSection.targetUser.rawValue
|
||
case .personalHeader, .firstName, .lastName, .username, .phone, .fakeId, .personalNotice: return FakeProfileSection.personalData.rawValue
|
||
default: return FakeProfileSection.badges.rawValue
|
||
}
|
||
}
|
||
var stableId: Int {
|
||
switch self {
|
||
case .targetHeader(let i, _), .targetUserId(let i, _, _), .targetNotice(let i, _),
|
||
.personalHeader(let i, _), .firstName(let i, _, _), .lastName(let i, _, _), .username(let i, _, _),
|
||
.phone(let i, _, _), .fakeId(let i, _, _), .personalNotice(let i, _),
|
||
.badgesHeader(let i, _), .premium(let i, _, _, _), .verified(let i, _, _, _), .scam(let i, _, _, _),
|
||
.fake(let i, _, _, _), .support(let i, _, _, _), .bot(let i, _, _, _), .badgesNotice(let i, _): return i
|
||
}
|
||
}
|
||
static func < (lhs: FakeProfileEntry, rhs: FakeProfileEntry) -> Bool { lhs.stableId < rhs.stableId }
|
||
static func == (lhs: FakeProfileEntry, rhs: FakeProfileEntry) -> Bool {
|
||
switch (lhs, rhs) {
|
||
case let (.targetHeader(a, t1), .targetHeader(b, t2)): return a == b && t1 == t2
|
||
case let (.targetUserId(a, t1, p1), .targetUserId(b, t2, p2)): return a == b && t1 == t2 && p1 == p2
|
||
case let (.targetNotice(a, t1), .targetNotice(b, t2)): return a == b && t1 == t2
|
||
case let (.personalHeader(a, t1), .personalHeader(b, t2)): return a == b && t1 == t2
|
||
case let (.firstName(a, t1, p1), .firstName(b, t2, p2)): return a == b && t1 == t2 && p1 == p2
|
||
case let (.lastName(a, t1, p1), .lastName(b, t2, p2)): return a == b && t1 == t2 && p1 == p2
|
||
case let (.username(a, t1, p1), .username(b, t2, p2)): return a == b && t1 == t2 && p1 == p2
|
||
case let (.phone(a, t1, p1), .phone(b, t2, p2)): return a == b && t1 == t2 && p1 == p2
|
||
case let (.fakeId(a, t1, p1), .fakeId(b, t2, p2)): return a == b && t1 == t2 && p1 == p2
|
||
case let (.personalNotice(a, t1), .personalNotice(b, t2)): return a == b && t1 == t2
|
||
case let (.badgesHeader(a, t1), .badgesHeader(b, t2)): return a == b && t1 == t2
|
||
case let (.premium(a, t1, s1, v1), .premium(b, t2, s2, v2)): return a == b && t1 == t2 && s1 == s2 && v1 == v2
|
||
case let (.verified(a, t1, s1, v1), .verified(b, t2, s2, v2)): return a == b && t1 == t2 && s1 == s2 && v1 == v2
|
||
case let (.scam(a, t1, s1, v1), .scam(b, t2, s2, v2)): return a == b && t1 == t2 && s1 == s2 && v1 == v2
|
||
case let (.fake(a, t1, s1, v1), .fake(b, t2, s2, v2)): return a == b && t1 == t2 && s1 == s2 && v1 == v2
|
||
case let (.support(a, t1, s1, v1), .support(b, t2, s2, v2)): return a == b && t1 == t2 && s1 == s2 && v1 == v2
|
||
case let (.bot(a, t1, s1, v1), .bot(b, t2, s2, v2)): return a == b && t1 == t2 && s1 == s2 && v1 == v2
|
||
case let (.badgesNotice(a, t1), .badgesNotice(b, t2)): return a == b && t1 == t2
|
||
default: return false
|
||
}
|
||
}
|
||
|
||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||
let theme = presentationData.theme
|
||
let args = arguments as! FakeProfileArguments
|
||
switch self {
|
||
case .targetHeader(_, let text):
|
||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: section)
|
||
case .targetUserId(_, let text, let placeholder):
|
||
return ItemListSingleLineInputItem(presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: "ID", textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearType: .always, sectionId: section, textUpdated: { args.updateTargetUserId($0) }, action: {})
|
||
case .targetNotice(_, let text):
|
||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: section)
|
||
case .personalHeader(_, let text):
|
||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: section)
|
||
case .firstName(_, let text, let placeholder):
|
||
return ItemListSingleLineInputItem(presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: (presentationData.strings.baseLanguageCode == "ru" ? "Имя" : "First name"), textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .regular(capitalization: true, autocorrection: false), clearType: .always, sectionId: section, textUpdated: { args.updateFirstName($0) }, action: {})
|
||
case .lastName(_, let text, let placeholder):
|
||
return ItemListSingleLineInputItem(presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: (presentationData.strings.baseLanguageCode == "ru" ? "Фамилия" : "Last name"), textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .regular(capitalization: true, autocorrection: false), clearType: .always, sectionId: section, textUpdated: { args.updateLastName($0) }, action: {})
|
||
case .username(_, let text, let placeholder):
|
||
return ItemListSingleLineInputItem(presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: (presentationData.strings.baseLanguageCode == "ru" ? "Юзернейм (без @)" : "Username (no @)"), textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearType: .always, sectionId: section, textUpdated: { args.updateUsername($0) }, action: {})
|
||
case .phone(_, let text, let placeholder):
|
||
return ItemListSingleLineInputItem(presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: (presentationData.strings.baseLanguageCode == "ru" ? "Телефон (без +)" : "Phone (no +)"), textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .number, clearType: .always, sectionId: section, textUpdated: { args.updatePhone($0) }, action: {})
|
||
case .fakeId(_, let text, let placeholder):
|
||
return ItemListSingleLineInputItem(presentationData: presentationData, systemStyle: .glass, title: NSAttributedString(string: "Telegram ID", textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .number, clearType: .always, sectionId: section, textUpdated: { args.updateFakeId($0) }, action: {})
|
||
case .personalNotice(_, let text):
|
||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: section)
|
||
case .badgesHeader(_, let text):
|
||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: section)
|
||
case .premium(_, let title, let subtext, let value):
|
||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, text: subtext, value: value, sectionId: section, style: .blocks, updated: { args.updatePremium($0) })
|
||
case .verified(_, let title, let subtext, let value):
|
||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, text: subtext, value: value, sectionId: section, style: .blocks, updated: { args.updateVerified($0) })
|
||
case .scam(_, let title, let subtext, let value):
|
||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, text: subtext, value: value, sectionId: section, style: .blocks, updated: { args.updateScam($0) })
|
||
case .fake(_, let title, let subtext, let value):
|
||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, text: subtext, value: value, sectionId: section, style: .blocks, updated: { args.updateFake($0) })
|
||
case .support(_, let title, let subtext, let value):
|
||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, text: subtext, value: value, sectionId: section, style: .blocks, updated: { args.updateSupport($0) })
|
||
case .bot(_, let title, let subtext, let value):
|
||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: title, text: subtext, value: value, sectionId: section, style: .blocks, updated: { args.updateBot($0) })
|
||
case .badgesNotice(_, let text):
|
||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: section)
|
||
}
|
||
}
|
||
}
|
||
|
||
private final class FakeProfileArguments {
|
||
let reload: () -> Void
|
||
init(reload: @escaping () -> Void) { self.reload = reload }
|
||
|
||
func updateTargetUserId(_ value: String) {
|
||
SGSimpleSettings.shared.fakeProfileTargetUserId = value
|
||
reload()
|
||
}
|
||
func updateFirstName(_ value: String) {
|
||
SGSimpleSettings.shared.fakeProfileFirstName = value
|
||
reload()
|
||
}
|
||
func updateLastName(_ value: String) {
|
||
SGSimpleSettings.shared.fakeProfileLastName = value
|
||
reload()
|
||
}
|
||
func updateUsername(_ value: String) {
|
||
SGSimpleSettings.shared.fakeProfileUsername = value
|
||
reload()
|
||
}
|
||
func updatePhone(_ value: String) {
|
||
SGSimpleSettings.shared.fakeProfilePhone = value
|
||
reload()
|
||
}
|
||
func updateFakeId(_ value: String) {
|
||
SGSimpleSettings.shared.fakeProfileId = value
|
||
reload()
|
||
}
|
||
func updatePremium(_ value: Bool) {
|
||
SGSimpleSettings.shared.fakeProfilePremium = value
|
||
reload()
|
||
}
|
||
func updateVerified(_ value: Bool) {
|
||
SGSimpleSettings.shared.fakeProfileVerified = value
|
||
reload()
|
||
}
|
||
func updateScam(_ value: Bool) {
|
||
SGSimpleSettings.shared.fakeProfileScam = value
|
||
reload()
|
||
}
|
||
func updateFake(_ value: Bool) {
|
||
SGSimpleSettings.shared.fakeProfileFake = value
|
||
reload()
|
||
}
|
||
func updateSupport(_ value: Bool) {
|
||
SGSimpleSettings.shared.fakeProfileSupport = value
|
||
reload()
|
||
}
|
||
func updateBot(_ value: Bool) {
|
||
SGSimpleSettings.shared.fakeProfileBot = value
|
||
reload()
|
||
}
|
||
}
|
||
|
||
private func fakeProfileEntries(presentationData: PresentationData) -> [FakeProfileEntry] {
|
||
let lang = presentationData.strings.baseLanguageCode
|
||
let s = SGSimpleSettings.shared
|
||
var entries: [FakeProfileEntry] = []
|
||
var id = 0
|
||
|
||
entries.append(.targetHeader(id: id, text: lang == "ru" ? "ЦЕЛЕВОЙ ПОЛЬЗОВАТЕЛЬ" : "TARGET USER"))
|
||
id += 1
|
||
entries.append(.targetUserId(id: id, text: s.fakeProfileTargetUserId, placeholder: lang == "ru" ? "Оставьте пустым для своего профиля" : "Leave empty for your profile"))
|
||
id += 1
|
||
entries.append(.targetNotice(id: id, text: lang == "ru" ? "Чтобы узнать ID, используйте @userinfobot" : "Use @userinfobot to get user ID"))
|
||
id += 1
|
||
|
||
entries.append(.personalHeader(id: id, text: lang == "ru" ? "ЛИЧНЫЕ ДАННЫЕ" : "PERSONAL DATA"))
|
||
id += 1
|
||
entries.append(.firstName(id: id, text: s.fakeProfileFirstName, placeholder: lang == "ru" ? "Имя" : "First name"))
|
||
id += 1
|
||
entries.append(.lastName(id: id, text: s.fakeProfileLastName, placeholder: lang == "ru" ? "Фамилия" : "Last name"))
|
||
id += 1
|
||
entries.append(.username(id: id, text: s.fakeProfileUsername, placeholder: lang == "ru" ? "без @" : "no @"))
|
||
id += 1
|
||
entries.append(.phone(id: id, text: s.fakeProfilePhone, placeholder: lang == "ru" ? "без +" : "no +"))
|
||
id += 1
|
||
entries.append(.fakeId(id: id, text: s.fakeProfileId, placeholder: lang == "ru" ? "Визуально изменить ID" : "Override displayed ID"))
|
||
id += 1
|
||
entries.append(.personalNotice(id: id, text: lang == "ru" ? "Пустые поля — реальные данные." : "Empty = real data."))
|
||
id += 1
|
||
|
||
entries.append(.badgesHeader(id: id, text: lang == "ru" ? "СТАТУСЫ И ЗНАЧКИ" : "BADGES"))
|
||
id += 1
|
||
let premiumTitle = lang == "ru" ? "Premium" : "Premium"
|
||
let premiumSub = lang == "ru" ? "Визуально добавляет иконку Premium." : "Shows Premium badge."
|
||
entries.append(.premium(id: id, title: premiumTitle, subtext: premiumSub, value: s.fakeProfilePremium))
|
||
id += 1
|
||
let verifiedTitle = lang == "ru" ? "Верификация" : "Verified"
|
||
let verifiedSub = lang == "ru" ? "Визуально добавляет галочку." : "Shows verification badge."
|
||
entries.append(.verified(id: id, title: verifiedTitle, subtext: verifiedSub, value: s.fakeProfileVerified))
|
||
id += 1
|
||
let scamTitle = lang == "ru" ? "Scam" : "Scam"
|
||
let scamSub = lang == "ru" ? "Помечает как скам." : "Marks as scam."
|
||
entries.append(.scam(id: id, title: scamTitle, subtext: scamSub, value: s.fakeProfileScam))
|
||
id += 1
|
||
let fakeTitle = lang == "ru" ? "Fake" : "Fake"
|
||
let fakeSub = lang == "ru" ? "Помечает как фейк." : "Marks as fake."
|
||
entries.append(.fake(id: id, title: fakeTitle, subtext: fakeSub, value: s.fakeProfileFake))
|
||
id += 1
|
||
let supportTitle = lang == "ru" ? "Support" : "Support"
|
||
let supportSub = lang == "ru" ? "Официальная поддержка." : "Official support badge."
|
||
entries.append(.support(id: id, title: supportTitle, subtext: supportSub, value: s.fakeProfileSupport))
|
||
id += 1
|
||
let botTitle = lang == "ru" ? "Бот" : "Bot"
|
||
let botSub = lang == "ru" ? "Помечает как бота." : "Marks as bot."
|
||
entries.append(.bot(id: id, title: botTitle, subtext: botSub, value: s.fakeProfileBot))
|
||
id += 1
|
||
entries.append(.badgesNotice(id: id, text: lang == "ru" ? "Для полного применения может потребоваться перезапуск." : "Restart may be required for full effect."))
|
||
return entries
|
||
}
|
||
|
||
/// Fake Profile settings: target user ID, first/last name, username, phone, fake ID, badge toggles.
|
||
public func FakeProfileSettingsController(context: AccountContext, onSave: @escaping () -> Void) -> ViewController {
|
||
let reloadPromise = ValuePromise(true, ignoreRepeated: false)
|
||
let arguments = FakeProfileArguments(reload: { reloadPromise.set(true) })
|
||
|
||
let signal = combineLatest(reloadPromise.get(), context.sharedContext.presentationData)
|
||
|> map { _, presentationData -> (ItemListControllerState, (ItemListNodeState, FakeProfileArguments)) in
|
||
let lang = presentationData.strings.baseLanguageCode
|
||
let controllerState = ItemListControllerState(
|
||
presentationData: ItemListPresentationData(presentationData),
|
||
title: .text(lang == "ru" ? "Настройки Fake Profile" : "Fake Profile settings"),
|
||
leftNavigationButton: nil,
|
||
rightNavigationButton: nil,
|
||
backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)
|
||
)
|
||
let entries = fakeProfileEntries(presentationData: presentationData)
|
||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, ensureVisibleItemTag: nil, initialScrollToItem: nil)
|
||
return (controllerState, (listState, arguments))
|
||
}
|
||
|
||
let controller = ItemListController(context: context, state: signal)
|
||
return controller
|
||
}
|