mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-25 23:20:07 +00:00
Various improvements
This commit is contained in:
parent
66f78a352a
commit
c825438b72
@ -14736,8 +14736,8 @@ Sorry for the inconvenience.";
|
||||
"Gift.Options.Gift.BuyLimitReached_any" = "You've already sent %@ of these gifts, and it's the limit.";
|
||||
|
||||
"AgeVerification.Title" = "Age Verification";
|
||||
"AgeVerification.Text" = "To access this content, you must confirm you are at least **18** years old as required by UK law.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||
"AgeVerification.Text.gb" = "To access this content, you must confirm you are at least **18** years old as required by UK law.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||
"AgeVerification.Text" = "To access this content, you must confirm you are at least **18** years old.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||
"AgeVerification.Text.GB" = "To access this content, you must confirm you are at least **18** years old as required by UK law.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||
"AgeVerification.Verify" = "Verify My Age";
|
||||
|
||||
"AgeVerification.Success.Title" = "Age check passed!";
|
||||
|
@ -12,6 +12,7 @@ public final class BotCheckoutController: ViewController {
|
||||
public enum FetchError {
|
||||
case generic
|
||||
case disallowedStarGifts
|
||||
case starGiftsUserLimit
|
||||
}
|
||||
|
||||
public let form: BotPaymentForm
|
||||
@ -58,6 +59,8 @@ public final class BotCheckoutController: ViewController {
|
||||
switch error {
|
||||
case .disallowedStarGift:
|
||||
return .disallowedStarGifts
|
||||
case .starGiftUserLimit:
|
||||
return .starGiftsUserLimit
|
||||
default:
|
||||
return .generic
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ public enum BotPaymentFormRequestError {
|
||||
case noPaymentNeeded
|
||||
case disallowedStarGift
|
||||
case starGiftResellTooEarly(Int32)
|
||||
case starGiftUserLimit
|
||||
}
|
||||
|
||||
extension BotPaymentInvoice {
|
||||
@ -488,6 +489,8 @@ func _internal_fetchBotPaymentForm(accountPeerId: PeerId, postbox: Postbox, netw
|
||||
if let value = Int32(timeout) {
|
||||
return .fail(.starGiftResellTooEarly(value))
|
||||
}
|
||||
} else if error.errorDescription == "STARGIFT_USER_USAGE_LIMITED" {
|
||||
return .fail(.starGiftUserLimit)
|
||||
}
|
||||
return .fail(.generic)
|
||||
}
|
||||
@ -651,6 +654,7 @@ public enum SendBotPaymentFormError {
|
||||
case alreadyPaid
|
||||
case starGiftOutOfStock
|
||||
case disallowedStarGift
|
||||
case starGiftUserLimit
|
||||
}
|
||||
|
||||
public enum SendBotPaymentResult {
|
||||
|
@ -407,7 +407,12 @@ public func presentAgeVerification(context: AccountContext, parentController: Vi
|
||||
} else {
|
||||
let infoScreen = AgeVerificationScreen(context: context, completion: { [weak parentController] check, availability in
|
||||
if check {
|
||||
let scanScreen = FaceScanScreen(context: context, availability: availability, completion: { [weak parentController] passed in
|
||||
var requiredAge = 18
|
||||
if let value = context.currentAppConfiguration.with({ $0 }).data?["verify_age_min"] as? Double {
|
||||
requiredAge = Int(value)
|
||||
}
|
||||
|
||||
let scanScreen = FaceScanScreen(context: context, availability: availability, requiredAge: requiredAge, completion: { [weak parentController] passed in
|
||||
if passed {
|
||||
let _ = updateAgeVerificationState(engine: context.engine, { _ in
|
||||
return AgeVerificationState(verificationPassed: passed)
|
||||
|
@ -20,20 +20,21 @@ import ZipArchive
|
||||
import PlainButtonComponent
|
||||
import MultilineTextComponent
|
||||
|
||||
private let requiredAge = 18
|
||||
|
||||
final class FaceScanScreenComponent: Component {
|
||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
||||
let context: AccountContext
|
||||
let availability: Signal<AgeVerificationAvailability, NoError>
|
||||
let requiredAge: Int
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
availability: Signal<AgeVerificationAvailability, NoError>
|
||||
availability: Signal<AgeVerificationAvailability, NoError>,
|
||||
requiredAge: Int
|
||||
) {
|
||||
self.context = context
|
||||
self.availability = availability
|
||||
self.requiredAge = requiredAge
|
||||
}
|
||||
|
||||
static func ==(lhs: FaceScanScreenComponent, rhs: FaceScanScreenComponent) -> Bool {
|
||||
@ -109,7 +110,7 @@ final class FaceScanScreenComponent: Component {
|
||||
|
||||
self.backgroundColor = .black
|
||||
|
||||
self.previewLayer.backgroundColor = UIColor.red.cgColor
|
||||
//self.previewLayer.backgroundColor = UIColor.red.cgColor
|
||||
self.previewLayer.videoGravity = .resizeAspectFill
|
||||
self.layer.addSublayer(previewLayer)
|
||||
|
||||
@ -240,7 +241,7 @@ final class FaceScanScreenComponent: Component {
|
||||
let targetCenter = CGPoint(x: 0.5, y: 0.5)
|
||||
let distance = sqrt(pow(faceCenter.x - targetCenter.x, 2) + pow(faceCenter.y - targetCenter.y, 2))
|
||||
|
||||
if distance < 0.35 {
|
||||
if distance < 0.24 {
|
||||
switch processState {
|
||||
case .waitingForFace:
|
||||
self.processState = .positioning
|
||||
@ -306,7 +307,7 @@ final class FaceScanScreenComponent: Component {
|
||||
}
|
||||
|
||||
private func fillSegment(_ segmentIndex: Int) {
|
||||
guard !self.completedAngles.contains(segmentIndex) else {
|
||||
guard let component = self.component, !self.completedAngles.contains(segmentIndex) else {
|
||||
return
|
||||
}
|
||||
self.completedAngles.insert(segmentIndex)
|
||||
@ -320,7 +321,7 @@ final class FaceScanScreenComponent: Component {
|
||||
if !self.ages.isEmpty {
|
||||
let averageAge = self.ages.reduce(0, +) / Double(self.ages.count)
|
||||
if let environment = self.environment, let controller = environment.controller() as? FaceScanScreen {
|
||||
controller.completion(averageAge >= Double(requiredAge))
|
||||
controller.completion(averageAge >= Double(component.requiredAge))
|
||||
controller.dismiss(animated: true)
|
||||
}
|
||||
} else {
|
||||
@ -457,7 +458,6 @@ final class FaceScanScreenComponent: Component {
|
||||
self.frameView.frame = frameViewFrame
|
||||
self.frameView.update(size: frameViewFrame.size)
|
||||
|
||||
//TODO:localize
|
||||
var instructionString = environment.strings.FaceScan_Instruction_Position
|
||||
switch self.processState {
|
||||
case .waitingForFace, .positioning:
|
||||
@ -550,6 +550,7 @@ public final class FaceScanScreen: ViewControllerComponentContainer {
|
||||
public init(
|
||||
context: AccountContext,
|
||||
availability: Signal<AgeVerificationAvailability, NoError>,
|
||||
requiredAge: Int,
|
||||
completion: @escaping (Bool) -> Void
|
||||
) {
|
||||
self.context = context
|
||||
@ -557,7 +558,8 @@ public final class FaceScanScreen: ViewControllerComponentContainer {
|
||||
|
||||
super.init(context: context, component: FaceScanScreenComponent(
|
||||
context: context,
|
||||
availability: availability
|
||||
availability: availability,
|
||||
requiredAge: requiredAge
|
||||
), navigationBarAppearance: .none, theme: .default, updatedPresentationData: nil)
|
||||
|
||||
self.title = ""
|
||||
|
@ -363,6 +363,8 @@ final class GiftSetupScreenComponent: Component {
|
||||
let entities = generateChatInputTextEntities(self.textInputState.text)
|
||||
|
||||
var finalPrice: Int64
|
||||
var perUserLimit: Int32?
|
||||
var giftFile: TelegramMediaFile?
|
||||
let source: BotPaymentInvoiceSource
|
||||
switch component.subject {
|
||||
case let .premium(product):
|
||||
@ -377,6 +379,8 @@ final class GiftSetupScreenComponent: Component {
|
||||
if self.includeUpgrade, let upgradeStars = starGift.upgradeStars {
|
||||
finalPrice += upgradeStars
|
||||
}
|
||||
perUserLimit = starGift.perUserLimit?.total
|
||||
giftFile = starGift.file
|
||||
source = .starGift(hideName: self.hideName, includeUpgrade: self.includeUpgrade, peerId: peerId, giftId: starGift.id, text: self.textInputState.text.string, entities: entities)
|
||||
}
|
||||
|
||||
@ -395,6 +399,8 @@ final class GiftSetupScreenComponent: Component {
|
||||
switch error {
|
||||
case .disallowedStarGifts:
|
||||
return .fail(.disallowedStarGift)
|
||||
case .starGiftsUserLimit:
|
||||
return .fail(.starGiftUserLimit)
|
||||
default:
|
||||
return .fail(.generic)
|
||||
}
|
||||
@ -468,6 +474,14 @@ final class GiftSetupScreenComponent: Component {
|
||||
|
||||
var errorText: String?
|
||||
switch error {
|
||||
case .starGiftUserLimit:
|
||||
if let perUserLimit, let giftFile {
|
||||
let text = presentationData.strings.Gift_Options_Gift_BuyLimitReached(perUserLimit)
|
||||
let undoController = UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: giftFile, loop: true, title: nil, text: text, undoText: nil, customAction: nil), action: { _ in return false })
|
||||
controller.present(undoController, in: .current)
|
||||
return
|
||||
}
|
||||
return
|
||||
case .starGiftOutOfStock:
|
||||
errorText = presentationData.strings.Gift_Send_ErrorOutOfStock
|
||||
case .disallowedStarGift:
|
||||
|
@ -288,11 +288,14 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
}
|
||||
|
||||
var minRequiredAmount = StarsAmount(value: 100, nanos: 0)
|
||||
var canUpgrade = false
|
||||
if let resellStars = self.subject.arguments?.resellStars {
|
||||
minRequiredAmount = StarsAmount(value: resellStars, nanos: 0)
|
||||
} else if let arguments = self.subject.arguments, arguments.canUpgrade && arguments.upgradeStars == nil {
|
||||
canUpgrade = true
|
||||
}
|
||||
|
||||
if let starsContext = context.starsContext, let state = starsContext.currentState, state.balance < minRequiredAmount {
|
||||
if let starsContext = context.starsContext, let state = starsContext.currentState, state.balance < minRequiredAmount || canUpgrade {
|
||||
self.optionsDisposable = (context.engine.payments.starsTopUpOptions()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] options in
|
||||
guard let self else {
|
||||
|
@ -23,17 +23,20 @@ final class AddGiftsScreenComponent: Component {
|
||||
let context: AccountContext
|
||||
let peerId: EnginePeer.Id
|
||||
let collectionId: Int32
|
||||
let remainingCount: Int32
|
||||
let profileGifts: ProfileGiftsContext
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
peerId: EnginePeer.Id,
|
||||
collectionId: Int32,
|
||||
remainingCount: Int32,
|
||||
profileGifts: ProfileGiftsContext
|
||||
) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.collectionId = collectionId
|
||||
self.remainingCount = remainingCount
|
||||
self.profileGifts = profileGifts
|
||||
}
|
||||
|
||||
@ -128,7 +131,7 @@ final class AddGiftsScreenComponent: Component {
|
||||
if let current = self.giftsListView {
|
||||
giftsListView = current
|
||||
} else {
|
||||
giftsListView = GiftsListView(context: component.context, peerId: component.peerId, profileGifts: component.profileGifts, giftsCollections: nil, canSelect: true, ignoreCollection: component.collectionId)
|
||||
giftsListView = GiftsListView(context: component.context, peerId: component.peerId, profileGifts: component.profileGifts, giftsCollections: nil, canSelect: true, ignoreCollection: component.collectionId, remainingSelectionCount: component.remainingCount)
|
||||
giftsListView.selectionUpdated = { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
@ -248,6 +251,7 @@ public final class AddGiftsScreen: ViewControllerComponentContainer {
|
||||
context: AccountContext,
|
||||
peerId: EnginePeer.Id,
|
||||
collectionId: Int32,
|
||||
remainingCount: Int32,
|
||||
completion: @escaping ([ProfileGiftsContext.State.StarGift]) -> Void
|
||||
) {
|
||||
self.context = context
|
||||
@ -264,10 +268,10 @@ public final class AddGiftsScreen: ViewControllerComponentContainer {
|
||||
context: context,
|
||||
peerId: peerId,
|
||||
collectionId: collectionId,
|
||||
remainingCount: remainingCount,
|
||||
profileGifts: self.profileGifts
|
||||
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: nil)
|
||||
|
||||
|
||||
self.title = presentationData.strings.AddGifts_Title
|
||||
self.navigationPresentation = .modal
|
||||
|
||||
|
@ -36,6 +36,7 @@ final class GiftsListView: UIView {
|
||||
|
||||
private let canSelect: Bool
|
||||
private let ignoreCollection: Int32?
|
||||
private let remainingSelectionCount: Int32
|
||||
|
||||
private var dataDisposable: Disposable?
|
||||
|
||||
@ -124,13 +125,14 @@ final class GiftsListView: UIView {
|
||||
var contextAction: ((ProfileGiftsContext.State.StarGift, UIView, ContextGesture) -> Void)?
|
||||
var addToCollection: (() -> Void)?
|
||||
|
||||
init(context: AccountContext, peerId: PeerId, profileGifts: ProfileGiftsContext, giftsCollections: ProfileGiftsCollectionsContext?, canSelect: Bool, ignoreCollection: Int32? = nil) {
|
||||
init(context: AccountContext, peerId: PeerId, profileGifts: ProfileGiftsContext, giftsCollections: ProfileGiftsCollectionsContext?, canSelect: Bool, ignoreCollection: Int32? = nil, remainingSelectionCount: Int32 = 0) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.profileGifts = profileGifts
|
||||
self.giftsCollections = giftsCollections
|
||||
self.canSelect = canSelect
|
||||
self.ignoreCollection = ignoreCollection
|
||||
self.remainingSelectionCount = remainingSelectionCount
|
||||
|
||||
if let value = context.currentAppConfiguration.with({ $0 }).data?["stargifts_pinned_to_top_limit"] as? Double {
|
||||
self.maxPinnedCount = Int(value)
|
||||
@ -548,8 +550,10 @@ final class GiftsListView: UIView {
|
||||
if self.selectedItemIds.contains(itemReferenceId) {
|
||||
self.selectedItemIds.remove(itemReferenceId)
|
||||
} else {
|
||||
self.selectedItemIds.insert(itemReferenceId)
|
||||
self.selectedItemsMap[itemReferenceId] = product
|
||||
if self.selectedItemIds.count < self.remainingSelectionCount {
|
||||
self.selectedItemIds.insert(itemReferenceId)
|
||||
self.selectedItemsMap[itemReferenceId] = product
|
||||
}
|
||||
}
|
||||
self.selectionUpdated()
|
||||
self.updateScrolling(transition: .easeInOut(duration: 0.25))
|
||||
|
@ -242,7 +242,15 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
}
|
||||
|
||||
public func addGiftsToCollection(id: Int32) {
|
||||
let screen = AddGiftsScreen(context: self.context, peerId: self.peerId, collectionId: id, completion: { [weak self] gifts in
|
||||
var collectionGiftsMaxCount: Int32 = 1000
|
||||
if let value = self.context.currentAppConfiguration.with({ $0 }).data?["stargifts_collection_gifts_limit"] as? Double {
|
||||
collectionGiftsMaxCount = Int32(value)
|
||||
}
|
||||
var remainingCount = collectionGiftsMaxCount
|
||||
if let currentCount = self.giftsListView.profileGifts.currentState?.count {
|
||||
remainingCount = max(0, collectionGiftsMaxCount - currentCount)
|
||||
}
|
||||
let screen = AddGiftsScreen(context: self.context, peerId: self.peerId, collectionId: id, remainingCount: remainingCount, completion: { [weak self] gifts in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import PeerInfoScreen
|
||||
import PeerInfoStoryGridScreen
|
||||
import ShareWithPeersScreen
|
||||
import ChatEmptyNode
|
||||
//import FaceScanScreen
|
||||
import UndoUI
|
||||
|
||||
private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceholderNode {
|
||||
@ -237,22 +236,6 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
self.accountSettingsController = accountSettingsController
|
||||
self.rootTabController = tabBarController
|
||||
self.pushViewController(tabBarController, animated: false)
|
||||
|
||||
// Queue.mainQueue().after(1.0) {
|
||||
// let context = self.context
|
||||
// let infoScreen = AgeVerificationScreen(context: context, completion: { [weak chatListController] proceed in
|
||||
// if proceed {
|
||||
// let scanScreen = FaceScanScreen(context: context, completion: { success in
|
||||
// let controller = UndoOverlayController(presentationData: self.presentationData, content: .actionSucceeded(title: "Age check passed!", text: "You can now view this content.", cancel: nil, destructive: false), elevatedLayout: true, action: { _ in return true })
|
||||
// Queue.mainQueue().after(0.1) {
|
||||
// chatListController?.present(controller, in: .window(.root))
|
||||
// }
|
||||
// })
|
||||
// chatListController?.push(scanScreen)
|
||||
// }
|
||||
// })
|
||||
// chatListController.push(infoScreen)
|
||||
// }
|
||||
}
|
||||
|
||||
public func updateRootControllers(showCallsTab: Bool) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user