Various fixes

This commit is contained in:
Ilya Laktyushin 2025-07-20 12:18:17 +01:00
parent f97c2b9924
commit e7e2fa1e83
10 changed files with 116 additions and 72 deletions

View file

@ -14700,5 +14700,48 @@ Sorry for the inconvenience.";
"AccessDenied.AgeVerificationCamera" = "Telegram needs access to your camera for age verification.\n\nOpen your device's Settings > Privacy > Camera and set Telegram to ON.";
"PeerInfo.Gifts.AddGiftsButton" = "Add Gifts";
"PeerInfo.Gifts.AddCollection" = "Add Collection";
"PeerInfo.Gifts.AddGifts" = "Add Gifts";
"PeerInfo.Gifts.RenameCollection" = "Rename";
"PeerInfo.Gifts.ShareCollection" = "Share";
"PeerInfo.Gifts.DeleteCollection" = "Delete Collection";
"PeerInfo.Gifts.CreateCollection.Title" = "Create a New Collection";
"PeerInfo.Gifts.CreateCollection.Text" = "Choose a name for your collection and start adding your gifts there.";
"PeerInfo.Gifts.CreateCollection.Placeholder" = "Title";
"PeerInfo.Gifts.RenameCollection.Title" = "Create a New Collection";
"PeerInfo.Gifts.Context.AddToCollection" = "Add to Collection";
"PeerInfo.Gifts.Context.NewCollection" = "New Collection";
"PeerInfo.Gifts.Context.RemoveFromCollection" = "Remove from Collection";
"PeerInfo.Gifts.CollectionLimitReached.Title" = "Limit Reached";
"PeerInfo.Gifts.CollectionLimitReached.Text" = "Please remove one of the existing collections to add a new one.";
"PeerInfo.Gifts.RemoveCollectionConfirmation" = "This will remove the collection.";
"PeerInfo.Gifts.RemoveCollectionAction" = "Remove";
"PeerInfo.Gifts.EmptyCollection.Title" = "Organize Your Gifts";
"PeerInfo.Gifts.EmptyCollection.Text" = "Add some gifts to this collection.";
"PeerInfo.Gifts.EmptyCollection.Action" = "Add to Collection";
"AddGifts.Title" = "Add Gifts";
"AddGifts.AddGifts_1" = "Add %@ Gift";
"AddGifts.AddGifts_any" = "Add %@ Gifts";
"Gift.Options.Gift.BuyLimitReached_1" = "You've already sent %@ of these gifts, and it's the limit.";
"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.Verify" = "Verify My Age";
"AgeVerification.Success.Title" = "Age check passed!";
"AgeVerification.Success.Text" = "You can now view this content.";
"AgeVerification.Fail.Title" = "Age check failed";
"AgeVerification.Fail.Text" = "Sorry, you can't view this content.";

View file

@ -84,7 +84,7 @@ private final class SheetContent: CombinedComponent {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
let theme = presentationData.theme
//let strings = presentationData.strings
let strings = presentationData.strings
var contentSize = CGSize(width: context.availableSize.width, height: 18.0)
@ -144,7 +144,7 @@ private final class SheetContent: CombinedComponent {
contentSize.height += 124.0
let title = title.update(
component: Text(text: "Age Verification", font: Font.bold(24.0), color: theme.list.itemPrimaryTextColor),
component: Text(text: strings.AgeVerification_Title, font: Font.bold(24.0), color: theme.list.itemPrimaryTextColor),
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
transition: .immediate
)
@ -162,6 +162,7 @@ private final class SheetContent: CombinedComponent {
return (TelegramTextAttributes.URL, contents)
})
//TODO:localize
let textString = "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."
let text = text.update(
@ -195,7 +196,7 @@ private final class SheetContent: CombinedComponent {
),
content: AnyComponentWithIdentity(
id: AnyHashable(0),
component: AnyComponent(MultilineTextComponent(text: .plain(NSMutableAttributedString(string: "Verify My Age", font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
component: AnyComponent(MultilineTextComponent(text: .plain(NSMutableAttributedString(string: strings.AgeVerification_Verify, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
),
isEnabled: true,
displaysProgress: false,
@ -410,11 +411,11 @@ public func presentAgeVerification(context: AccountContext, parentController: Vi
let navigationController = parentController?.navigationController
Queue.mainQueue().after(2.0) {
let controller = UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: "Age check passed!", text: "You can now view this content.", cancel: nil, destructive: false), action: { _ in return true })
let controller = UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.AgeVerification_Success_Title, text: presentationData.strings.AgeVerification_Success_Text, cancel: nil, destructive: false), action: { _ in return true })
(navigationController?.viewControllers.last as? ViewController)?.present(controller, in: .window(.root))
}
} else {
let controller = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_banned", scale: 0.066, colors: [:], title: "Age check failed!", text: "Sorry, you can't view this content.", customUndoText: nil, timeout: nil), action: { _ in return true })
let controller = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_banned", scale: 0.066, colors: [:], title: presentationData.strings.AgeVerification_Fail_Title, text: presentationData.strings.AgeVerification_Fail_Text, customUndoText: nil, timeout: nil), action: { _ in return true })
parentController?.present(controller, in: .window(.root))
}
})

View file

@ -67,6 +67,7 @@ final class FaceScanScreenComponent: Component {
case completed
}
private var processState: State = .waitingForFace
private var transitioningToViewFinder = false
private var lastFaceYaw: NSNumber?
private var lastFacePitch: NSNumber?
@ -108,7 +109,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)
@ -239,7 +240,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.2 {
if distance < 0.35 {
switch processState {
case .waitingForFace:
self.processState = .positioning
@ -337,6 +338,9 @@ final class FaceScanScreenComponent: Component {
self.faceDetectionTimer?.invalidate()
self.segmentTimer?.invalidate()
if self.processState != .waitingForFace && self.processState != .positioning {
self.transitioningToViewFinder = true
}
self.processState = .waitingForFace
self.completedAngles.removeAll()
self.currentSegment = nil
@ -433,7 +437,7 @@ final class FaceScanScreenComponent: Component {
let center = CGPoint(x: availableSize.width / 2, y: environment.statusBarHeight + 10.0 + widthRadius * 1.3)
var previewScale = 1.0
if self.processState == .tracking || self.processState == .readyToStart || self.processState == .completed {
if self.processState == .tracking || self.processState == .readyToStart || self.processState == .completed || self.transitioningToViewFinder {
let circlePath = CGPath(roundedRect: CGRect(x: center.x - radius, y: center.y - radius, width: radius * 2, height: radius * 2), cornerWidth: radius, cornerHeight: radius, transform: nil)
path.addPath(circlePath)
@ -457,7 +461,12 @@ final class FaceScanScreenComponent: Component {
var instructionString = "Position your face\nwithin the frame"
switch self.processState {
case .waitingForFace, .positioning:
self.frameView.update(state: .viewFinder, transition: .spring(duration: 0.3))
self.frameView.update(state: .viewFinder, intermediateCompletion: { [weak self] in
if let self {
self.transitioningToViewFinder = false
self.state?.updated(transition: .spring(duration: 0.3))
}
}, transition: .spring(duration: 0.3))
instructionString = "Position your face\nwithin the frame"
case .readyToStart:
self.frameView.update(state: .segments(Set()), transition: .spring(duration: 0.3))

View file

@ -3,31 +3,28 @@ import Display
import ComponentFlow
final class FrameView: UIView {
enum State {
enum State: Equatable {
case viewFinder
case segments(Set<Int>)
case success
case failure
}
private let maskLayer = CALayer()
private let viewFinderLayer = ViewFinderLayer()
private let transitionLayer = TransitionLayer()
private let segmentsLayer = SegmentsLayer()
private var currentState: State = .viewFinder
private var scheduledState: State?
private var isTransitioning = false
private var currentLayout: CGSize?
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .clear
//self.layer.mask = self.maskLayer
self.transitionLayer.isHidden = true
self.segmentsLayer.isHidden = true
@ -40,7 +37,7 @@ final class FrameView: UIView {
preconditionFailure()
}
func update(state: State, transition: ComponentTransition) {
func update(state: State, intermediateCompletion: (() -> Void)? = nil, transition: ComponentTransition) {
guard !self.isTransitioning else {
self.scheduledState = state
return
@ -62,6 +59,7 @@ final class FrameView: UIView {
self.transitionLayer.animateOut(transition: transition) {
self.transitionLayer.isHidden = true
self.viewFinderLayer.isHidden = false
intermediateCompletion?()
self.viewFinderLayer.animateIn(transition: transition) {
self.isTransitioning = false
self.maybeApplyScheduledState()
@ -118,18 +116,21 @@ final class FrameView: UIView {
self.update(state: state, transition: .spring(duration: 0.3))
}
}
func update(size: CGSize) {
let bounds = CGRect(origin: .zero, size: size)
guard self.currentLayout != size else {
return
}
self.currentLayout = size
self.maskLayer.frame = bounds
let bounds = CGRect(origin: .zero, size: size)
//let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
//let viewFinderWidth = bounds.width - 34.0
//let viewFinderSize = CGSize(width: viewFinderWidth, height: floor(viewFinderWidth * 1.17778))
let viewFinderFrame = bounds.insetBy(dx: 29.0, dy: 29.0) //viewFinderSize.centered(around: center)
self.viewFinderLayer.update(size: viewFinderFrame.size, closed: false, transition: .immediate)
self.viewFinderLayer.update(size: viewFinderFrame.size, closed: self.currentState != .viewFinder, transition: .immediate)
self.viewFinderLayer.frame = viewFinderFrame
let transitionFrame = bounds.insetBy(dx: 29.0, dy: 29.0) //viewFinderSize.centered(around: center)
@ -373,7 +374,7 @@ final class SegmentsLayer: SimpleLayer {
let stripeLayer = SimpleShapeLayer()
stripeLayer.path = path.cgPath
stripeLayer.strokeColor = UIColor.white.cgColor
stripeLayer.strokeColor = UIColor(rgb: 0xaaaaaa).cgColor
stripeLayer.lineWidth = lineWidth
stripeLayer.fillColor = UIColor.clear.cgColor
stripeLayer.lineCap = .round

View file

@ -460,9 +460,9 @@ final class GiftOptionsScreenComponent: Component {
}
if case let .generic(gift) = gift {
if let perUserLimit = gift.perUserLimit, perUserLimit.remains == 0 {
//TODO:localize
let text = environment.strings.Gift_Options_Gift_BuyLimitReached(perUserLimit.total)
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: gift.file, loop: true, title: nil, text: "You've already sent \(perUserLimit.total) of these gifts, and it's the limit.", undoText: nil, customAction: nil), action: { _ in return false })
let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: gift.file, loop: true, title: nil, text: text, undoText: nil, customAction: nil), action: { _ in return false })
mainController.present(controller, in: .current)
return
}

View file

@ -11366,10 +11366,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|> map { [weak self, weak pane, weak giftsContext] filter, sorting, canReorder -> ContextController.Items in
var items: [ContextMenuItem] = []
if canReorder && hasVisibility {
//TODO:localize
if hasVisibility {
if let pane, case .all = pane.currentCollection {
items.append(.action(ContextMenuActionItem(text: "Add Collection", icon: { theme in
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_AddCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddCollection"), color: theme.contextMenu.primaryColor)
}, action: { [weak pane] _, f in
f(.default)
@ -11379,7 +11378,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
})))
} else {
items.append(.action(ContextMenuActionItem(text: "Add Gifts", icon: { theme in
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_AddGifts, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddGift"), color: theme.contextMenu.primaryColor)
}, action: { [weak pane] _, f in
f(.default)
@ -11389,27 +11388,29 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
})))
items.append(.action(ContextMenuActionItem(text: "Share", icon: { theme in
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
//TODO:release
self?.openShareLink(url: "https://t.me/")
})))
}
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Reorder, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor)
}, action: { [weak pane] _, f in
f(.default)
if let pane {
pane.beginReordering()
}
})))
if canReorder {
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Reorder, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor)
}, action: { [weak pane] _, f in
f(.default)
if let pane {
pane.beginReordering()
}
})))
}
if let pane, case let .collection(id) = pane.currentCollection {
items.append(.action(ContextMenuActionItem(text: "Delete Collection", textColor: .destructive, icon: { theme in
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_DeleteCollection, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak pane] _, f in
f(.default)

View file

@ -153,15 +153,7 @@ final class AddGiftsScreenComponent: Component {
let bottomPanelOffset: CGFloat = giftsListView.selectedItems.count > 0 ? 0.0 : bottomPanelHeight
//TODO:localize
var buttonString = ""
if giftsListView.selectedItems.count > 1 {
buttonString = "Add \(giftsListView.selectedItems.count) Gifts"
} else {
buttonString = "Add 1 Gift"
}
let buttonString = environment.strings.AddGifts_AddGifts(Int32(giftsListView.selectedItems.count))
let bottomPanelSize = self.buttonBackground.update(
transition: transition,
component: AnyComponent(BlurredBackgroundComponent(
@ -276,8 +268,7 @@ public final class AddGiftsScreen: ViewControllerComponentContainer {
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: nil)
//TODO:localize
self.title = "Add Gifts"
self.title = presentationData.strings.AddGifts_Title
self.navigationPresentation = .modal
self.scrollToTop = { [weak self] in

View file

@ -783,12 +783,11 @@ final class GiftsListView: UIView {
panelTransition.setFrame(view: self.emptyResultsClippingView, frame: CGRect(origin: CGPoint(x: 0.0, y: 48.0), size: params.size))
panelTransition.setBounds(view: self.emptyResultsClippingView, bounds: CGRect(origin: CGPoint(x: 0.0, y: 48.0), size: params.size))
//TODO:localize
let emptyResultsTitleSize = self.emptyResultsTitle.update(
transition: .immediate,
component: AnyComponent(
MultilineTextComponent(
text: .plain(NSAttributedString(string: "Organize Your Gifts", font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor)),
text: .plain(NSAttributedString(string: presentationData.strings.PeerInfo_Gifts_EmptyCollection_Title, font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor)),
horizontalAlignment: .center
)
),
@ -799,14 +798,14 @@ final class GiftsListView: UIView {
transition: .immediate,
component: AnyComponent(
MultilineTextComponent(
text: .plain(NSAttributedString(string: "Add some gifts to this collection.", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)),
text: .plain(NSAttributedString(string: presentationData.strings.PeerInfo_Gifts_EmptyCollection_Text, font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)),
horizontalAlignment: .center
)
),
environment: {},
containerSize: CGSize(width: params.size.width - sideInset * 2.0, height: params.size.height)
)
let buttonAttributedString = NSAttributedString(string: "Add to Collection", font: Font.semibold(17.0), textColor: .white, paragraphAlignment: .center)
let buttonAttributedString = NSAttributedString(string: presentationData.strings.PeerInfo_Gifts_EmptyCollection_Action, font: Font.semibold(17.0), textColor: .white, paragraphAlignment: .center)
let emptyResultsActionSize = self.emptyResultsAction.update(
transition: .immediate,
component: AnyComponent(

View file

@ -196,13 +196,12 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
return
}
if let collections = self.collections, collections.count >= self.collectionsMaxCount {
let alertController = textAlertController(context: self.context, title: "Limit Reached", text: "Please remove one of the existing collections to add a new one.", actions: [TextAlertAction(type: .defaultAction, title: params.presentationData.strings.Common_OK, action: {})])
let alertController = textAlertController(context: self.context, title: params.presentationData.strings.PeerInfo_Gifts_CollectionLimitReached_Title, text: params.presentationData.strings.PeerInfo_Gifts_CollectionLimitReached_Text, actions: [TextAlertAction(type: .defaultAction, title: params.presentationData.strings.Common_OK, action: {})])
self.parentController?.present(alertController, in: .window(.root))
return
}
//TODO:localize
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: "Create a New Collection", titleFont: .bold, subtitle: "Choose a name for your collection and start adding your gifts there.", value: "", placeholder: "Title", characterLimit: 20, displayCharacterLimit: true, apply: { [weak self] value in
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Title, titleFont: .bold, subtitle: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Text, value: "", placeholder: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Placeholder, characterLimit: 20, displayCharacterLimit: true, apply: { [weak self] value in
guard let self, let value else {
return
}
@ -253,11 +252,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
public func renameCollection(id: Int32) {
guard let collection = self.collections?.first(where: { $0.id == id }) else {
guard let params = self.currentParams, let collection = self.collections?.first(where: { $0.id == id }) else {
return
}
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: "Rename Collection", titleFont: .bold, value: collection.title, placeholder: "Title", characterLimit: 20, displayCharacterLimit: true, apply: { [weak self] value in
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: params.presentationData.strings.PeerInfo_Gifts_RenameCollection_Title, titleFont: .bold, value: collection.title, placeholder: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Placeholder, characterLimit: 20, displayCharacterLimit: true, apply: { [weak self] value in
guard let self, let value else {
return
}
@ -440,8 +439,8 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
var items: [ContextMenuItem] = []
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Add Gifts", icon: { theme in
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_AddGifts, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddGift"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
@ -453,7 +452,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.addGiftsToCollection(id: id)
})))
items.append(.action(ContextMenuActionItem(text: "Rename", icon: { theme in
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_RenameCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
@ -464,7 +463,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.renameCollection(id: id)
})))
items.append(.action(ContextMenuActionItem(text: "Share", icon: { theme in
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] _, f in
guard let self else {
@ -472,10 +471,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
f(.default)
//TODO:release
let _ = self
})))
items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_Reorder, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] c, f in
c?.dismiss(completion: { [weak self] in
@ -486,7 +486,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
})
})))
items.append(.action(ContextMenuActionItem(text: "Delete Collection", textColor: .destructive, icon: { theme in
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_DeleteCollection, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
guard let self else {
@ -684,13 +684,12 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
let buttonSideInset = sideInset + 16.0
//TODO:localize
let buttonTitle: String
if self.peerId == self.context.account.peerId {
if case .all = self.currentCollection {
buttonTitle = params.presentationData.strings.PeerInfo_Gifts_Send
} else {
buttonTitle = "Add Gifts"
buttonTitle = params.presentationData.strings.PeerInfo_Gifts_AddGiftsButton
}
} else {
buttonTitle = params.presentationData.strings.PeerInfo_Gifts_SendGift
@ -891,7 +890,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
var items: [ContextMenuItem] = []
if canManage {
items.append(.action(ContextMenuActionItem(text: "Add to Collection", textLayout: .twoLinesMax, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddToCollection"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, f in
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Context_AddToCollection, textLayout: .twoLinesMax, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddToCollection"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, f in
var subItems: [ContextMenuItem] = []
subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, textColor: .primary, icon: { theme in
@ -902,7 +901,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
subItems.append(.separator)
subItems.append(.action(ContextMenuActionItem(text: "New Collection", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddCollection"), color: theme.contextMenu.primaryColor) }, iconPosition: .left, action: { [weak self] c, f in
subItems.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Context_NewCollection, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/AddCollection"), color: theme.contextMenu.primaryColor) }, iconPosition: .left, action: { [weak self] c, f in
f(.default)
self?.createCollection(gifts: [gift])
@ -1215,7 +1214,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
if case let .collection(id) = self.currentCollection {
items.append(.action(ContextMenuActionItem(text: "Remove From Collection", textColor: .destructive, textLayout: .twoLinesMax, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/RemoveFromCollection"), color: theme.contextMenu.destructiveColor) }, action: { [weak self] c, f in
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Context_RemoveFromCollection, textColor: .destructive, textLayout: .twoLinesMax, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/RemoveFromCollection"), color: theme.contextMenu.destructiveColor) }, action: { [weak self] c, f in
f(.default)
if let reference = gift.reference {

View file

@ -129,7 +129,7 @@ extension ChatControllerImpl {
}
if "".isEmpty {
//TODO:localize
//TODO:release
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Todo_ReplyToItem, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.actionSheet.primaryTextColor)
}, action: { [weak self] c, _ in