Various fixes

This commit is contained in:
Ilya Laktyushin 2025-02-14 21:44:19 +04:00
parent fd38d2ea9b
commit c0184d4114
7 changed files with 177 additions and 140 deletions

View File

@ -13801,3 +13801,10 @@ Sorry for the inconvenience.";
"Notification.StarsGift.TransferToChannel" = "%@ transferred a unique collectible to %@";
"Notification.StarsGift.TransferToChannelYou" = "You transferred a unique collectible to %@";
"Gift.Convert.Success.ChannelText" = "**%1$@** were sent to channel's balance.";
"Gift.Convert.Success.ChannelText.Stars_1" = "%@ Star";
"Gift.Convert.Success.ChannelText.Stars_any" = "%@ Stars";
"Stars.Transfer.Terms" = "By purchasing you agree to the [Terms of Service]().";
"Stars.Transfer.Terms_URL" = "https://telegram.org/tos/stars";

View File

@ -962,7 +962,11 @@
[_coverImageCache setImage:image forKey:itemId attributes:NULL];
_coverImagePipe.sink([TGMediaImageUpdate imageUpdateWithItem:item representation:image]);
if (position != nil) {
[_coverPositions setObject:position forKey:itemId];
} else {
[_coverPositions removeObjectForKey:itemId];
}
}
- (void)setFullSizeImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item

View File

@ -355,13 +355,13 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
let signal: Signal<([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)?, NoError>
if !text.isEmpty {
let context = self.context
let stickers: Signal<[(String?, FoundStickerItem)], NoError> = Signal { subscriber in
var signals: Signal<[Signal<(String?, [FoundStickerItem]), NoError>], NoError> = .single([])
let stickers: Signal<([(String?, FoundStickerItem)], Bool), NoError> = Signal { subscriber in
var signals: Signal<[Signal<(String?, [FoundStickerItem], Bool), NoError>], NoError> = .single([])
let query = text.trimmingCharacters(in: .whitespacesAndNewlines)
if query.isSingleEmoji {
signals = .single([context.engine.stickers.searchStickers(query: nil, emoticon: [text.basicEmoji.0])
|> map { (nil, $0.items) }])
|> map { (nil, $0.items, $0.isFinalResult) }])
} else if query.count > 1, let languageCode = languageCode, !languageCode.isEmpty && languageCode != "emoji" {
var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query.lowercased(), completeMatch: query.count < 3)
if !languageCode.lowercased().hasPrefix("en") {
@ -377,10 +377,10 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
}
}
signals = signal
|> map { keywords -> [Signal<(String?, [FoundStickerItem]), NoError>] in
|> map { keywords -> [Signal<(String?, [FoundStickerItem], Bool), NoError>] in
let emoticon = keywords.flatMap { $0.emoticons }.map { $0.basicEmoji.0 }
return [context.engine.stickers.searchStickers(query: query, emoticon: emoticon, inputLanguageCode: languageCode)
|> map { (nil, $0.items) }]
|> map { (nil, $0.items, $0.isFinalResult) }]
}
}
@ -389,12 +389,16 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
return combineLatest(signals)
}).start(next: { results in
var result: [(String?, FoundStickerItem)] = []
for (emoji, stickers) in results {
var allAreFinal = true
for (emoji, stickers, isFinal) in results {
for sticker in stickers {
result.append((emoji, sticker))
}
if !isFinal {
allAreFinal = false
}
subscriber.putNext(result)
}
subscriber.putNext((result, allAreFinal))
}, completed: {
// subscriber.putCompletion()
})
@ -456,7 +460,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
signal = combineLatest(stickers, packs)
|> map { stickers, packs -> ([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)? in
return (stickers, packs.0, packs.1, packs.2)
return (stickers.0, packs.0, packs.1 && stickers.1, packs.2)
}
self.updateActivity?(true)
} else {

View File

@ -344,22 +344,24 @@ final class GiftSetupScreenComponent: Component {
let entities = generateChatInputTextEntities(self.textInputState.text)
let source: BotPaymentInvoiceSource = .starGift(hideName: self.hideName, includeUpgrade: self.includeUpgrade, peerId: peerId, giftId: starGift.id, text: self.textInputState.text.string, entities: entities)
let inputData = BotCheckoutController.InputData.fetch(context: component.context, source: source)
|> map(Optional.init)
|> `catch` { _ -> Signal<BotCheckoutController.InputData?, NoError> in
return .single(nil)
}
let completion = component.completion
let _ = (inputData
|> deliverOnMainQueue).startStandalone(next: { [weak self] inputData in
guard let inputData else {
let signal = BotCheckoutController.InputData.fetch(context: component.context, source: source)
|> `catch` { _ -> Signal<BotCheckoutController.InputData, SendBotPaymentFormError> in
return .fail(.generic)
}
|> mapToSignal { inputData -> Signal<SendBotPaymentResult, SendBotPaymentFormError> in
return component.context.engine.payments.sendStarsPaymentForm(formId: inputData.form.id, source: source)
}
|> deliverOnMainQueue
let _ = signal.start(next: { [weak self] result in
guard let self, let controller = self.environment?.controller(), let navigationController = controller.navigationController as? NavigationController else {
return
}
let _ = (component.context.engine.payments.sendStarsPaymentForm(formId: inputData.form.id, source: source)
|> deliverOnMainQueue).start(next: { [weak self] result in
if let self, peerId.namespace == Namespaces.Peer.CloudChannel, let controller = self.environment?.controller(), let navigationController = controller.navigationController as? NavigationController {
if peerId.namespace == Namespaces.Peer.CloudChannel {
var controllers = navigationController.viewControllers
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) }
navigationController.setViewControllers(controllers, animated: true)
@ -380,20 +382,7 @@ final class GiftSetupScreenComponent: Component {
(navigationController.viewControllers.last as? ViewController)?.present(tooltipController, in: .current)
navigationController.view.addSubview(ConfettiView(frame: navigationController.view.bounds))
}
if let completion {
completion()
if let self, let controller = self.environment?.controller() {
controller.dismiss()
}
} else {
guard let self, let controller = self.environment?.controller(), let navigationController = controller.navigationController as? NavigationController else {
return
}
if peerId.namespace != Namespaces.Peer.CloudChannel {
} else if peerId.namespace == Namespaces.Peer.CloudUser {
var controllers = navigationController.viewControllers
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) && !($0 is PeerInfoScreen) && !($0 is ContactSelectionController) }
var foundController = false
@ -411,6 +400,13 @@ final class GiftSetupScreenComponent: Component {
}
navigationController.setViewControllers(controllers, animated: true)
}
if let completion {
completion()
if let controller = self.environment?.controller() {
controller.dismiss()
}
}
starsContext.load(force: true)
@ -436,7 +432,6 @@ final class GiftSetupScreenComponent: Component {
controller.present(alertController, in: .window(.root))
}
})
})
}
if starsState.balance < StarsAmount(value: finalPrice, nanos: 0) {

View File

@ -3112,11 +3112,14 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
}
self.entitiesView.canInteract = { [weak self] in
if let self, let controller = self.controller {
return !controller.node.recording.isActive
} else {
return true
if controller.node.recording.isActive {
return false
} else if case .avatarEditor = controller.mode, self.drawingScreen == nil {
return false
}
}
return true
}
self.availableReactionsDisposable = (allowedStoryReactions(context: controller.context)
|> deliverOnMainQueue).start(next: { [weak self] reactions in
@ -3252,11 +3255,12 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
if let mediaEntityView = self.entitiesView.add(mediaEntity, announce: false) as? DrawingMediaEntityView {
self.entitiesView.sendSubviewToBack(mediaEntityView)
mediaEntityView.updated = { [weak self, weak mediaEntity] in
if let self, let mediaEntity {
if let self, let mediaEditor = self.mediaEditor, let mediaEntity {
let rotation = mediaEntity.rotation - initialRotation
let position = CGPoint(x: mediaEntity.position.x - initialPosition.x, y: mediaEntity.position.y - initialPosition.y)
let scale = mediaEntity.scale / initialScale
self.mediaEditor?.setCrop(offset: position, scale: scale, rotation: rotation, mirroring: false)
let mirroring = mediaEditor.values.cropMirroring
mediaEditor.setCrop(offset: position, scale: scale, rotation: rotation, mirroring: mirroring)
self.updateMaskDrawingView(position: position, scale: scale, rotation: rotation)
}
@ -3465,6 +3469,13 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
}
return false
}) as? DrawingStickerEntityView {
#if DEBUG
if let data = result.dayImage.pngData() {
let path = NSTemporaryDirectory() + "\(Int(Date().timeIntervalSince1970)).png"
try? data.write(to: URL(fileURLWithPath: path))
}
#endif
existingEntityView.isNightTheme = isNightTheme
let messageEntity = existingEntityView.entity as! DrawingStickerEntity
messageEntity.renderImage = result.dayImage
@ -5613,6 +5624,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
self.previousDrawingData = self.drawingView.drawingData
self.previousDrawingEntities = self.entitiesView.entities
self.cropScrollView?.isUserInteractionEnabled = false
self.interaction?.deactivate()
let controller = DrawingScreen(
context: self.context,
@ -5668,6 +5681,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
self.previousDrawingData = nil
self.previousDrawingEntities = nil
self.cropScrollView?.isUserInteractionEnabled = true
}
controller.requestApply = { [weak controller, weak self] in
guard let self else {
@ -5690,6 +5705,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
self.interaction?.activate()
self.entitiesView.selectEntity(nil)
self.cropScrollView?.isUserInteractionEnabled = true
}
self.controller?.present(controller, in: .current)
self.animateOutToTool(tool: mode)
@ -7594,6 +7611,13 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
let values = mediaEditor.values.withUpdatedCoverDimensions(dimensions)
makeEditorImageComposition(context: self.node.ciContext, postbox: self.context.account.postbox, inputImage: image, dimensions: storyDimensions, outputDimensions: dimensions.aspectFitted(CGSize(width: 1080, height: 1080)), values: values, time: .zero, textScale: 2.0, completion: { [weak self] resultImage in
if let self, let resultImage {
#if DEBUG
if let data = resultImage.jpegData(compressionQuality: 0.7) {
let path = NSTemporaryDirectory() + "\(Int(Date().timeIntervalSince1970)).jpg"
try? data.write(to: URL(fileURLWithPath: path))
}
#endif
self.completion(MediaEditorScreenImpl.Result(media: .image(image: resultImage, dimensions: PixelDimensions(resultImage.size))), { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()

View File

@ -141,11 +141,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.updateScrolling(transition: .immediate)
self.updateScrolling(interactive: true, transition: .immediate)
}
private var notify = false
func updateScrolling(transition: ComponentTransition) {
func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
if let starsProducts = self.starsProducts, let params = self.currentParams {
let optionSpacing: CGFloat = 10.0
let itemsSideInset = params.sideInset + 16.0
@ -644,7 +644,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
let bottomContentOffset = max(0.0, self.scrollNode.view.contentSize.height - self.scrollNode.view.contentOffset.y - self.scrollNode.view.frame.height)
if bottomContentOffset < 200.0 {
if interactive, bottomContentOffset < 200.0 {
self.profileGifts.loadMore()
}
}

View File

@ -293,9 +293,11 @@ private final class SheetContent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0))
)
var isExtendedMedia = false
let subject: StarsImageComponent.Subject
if !component.extendedMedia.isEmpty {
subject = .extendedMedia(component.extendedMedia)
isExtendedMedia = true
} else if let peer = state.botPeer {
if let photo = component.invoice.photo {
subject = .photo(photo)
@ -381,7 +383,7 @@ private final class SheetContent: CombinedComponent {
contentSize.height += title.size.height
contentSize.height += 13.0
if isBot, let peer = state.botPeer {
if isBot && !isExtendedMedia, let peer = state.botPeer {
contentSize.height -= 3.0
let peerShortcut = peerShortcut.update(
component: PremiumPeerShortcutComponent(
@ -650,7 +652,10 @@ private final class SheetContent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + button.size.height / 2.0))
)
contentSize.height += button.size.height
if isSubscription {
let termsText = isSubscription ? strings.Stars_Subscription_Terms : strings.Stars_Transfer_Terms
let termsURL = isSubscription ? strings.Stars_Subscription_Terms_URL : strings.Stars_Transfer_Terms_URL
contentSize.height += 14.0
let termsTextFont = Font.regular(13.0)
@ -662,7 +667,7 @@ private final class SheetContent: CombinedComponent {
let info = info.update(
component: BalancedTextComponent(
text: .markdown(
text: strings.Stars_Subscription_Terms,
text: termsText,
attributes: termsMarkdownAttributes
),
horizontalAlignment: .center,
@ -679,7 +684,7 @@ private final class SheetContent: CombinedComponent {
tapAction: { [weak controller] attributes, _ in
if let controller, let navigationController = controller.navigationController as? NavigationController {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: strings.Stars_Subscription_Terms_URL, forceExternal: false, presentationData: presentationData, navigationController: navigationController, dismissInput: {})
component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: termsURL, forceExternal: false, presentationData: presentationData, navigationController: navigationController, dismissInput: {})
}
}
),
@ -691,8 +696,6 @@ private final class SheetContent: CombinedComponent {
)
contentSize.height += info.size.height
}
contentSize.height += 48.0
return contentSize