mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
fd38d2ea9b
commit
c0184d4114
@ -13801,3 +13801,10 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Notification.StarsGift.TransferToChannel" = "%@ transferred a unique collectible to %@";
|
"Notification.StarsGift.TransferToChannel" = "%@ transferred a unique collectible to %@";
|
||||||
"Notification.StarsGift.TransferToChannelYou" = "You 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";
|
||||||
|
@ -962,7 +962,11 @@
|
|||||||
|
|
||||||
[_coverImageCache setImage:image forKey:itemId attributes:NULL];
|
[_coverImageCache setImage:image forKey:itemId attributes:NULL];
|
||||||
_coverImagePipe.sink([TGMediaImageUpdate imageUpdateWithItem:item representation:image]);
|
_coverImagePipe.sink([TGMediaImageUpdate imageUpdateWithItem:item representation:image]);
|
||||||
[_coverPositions setObject:position forKey:itemId];
|
if (position != nil) {
|
||||||
|
[_coverPositions setObject:position forKey:itemId];
|
||||||
|
} else {
|
||||||
|
[_coverPositions removeObjectForKey:itemId];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setFullSizeImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item
|
- (void)setFullSizeImage:(UIImage *)image forItem:(id<TGMediaEditableItem>)item
|
||||||
|
@ -355,13 +355,13 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
|||||||
let signal: Signal<([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)?, NoError>
|
let signal: Signal<([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)?, NoError>
|
||||||
if !text.isEmpty {
|
if !text.isEmpty {
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let stickers: Signal<[(String?, FoundStickerItem)], NoError> = Signal { subscriber in
|
let stickers: Signal<([(String?, FoundStickerItem)], Bool), NoError> = Signal { subscriber in
|
||||||
var signals: Signal<[Signal<(String?, [FoundStickerItem]), NoError>], NoError> = .single([])
|
var signals: Signal<[Signal<(String?, [FoundStickerItem], Bool), NoError>], NoError> = .single([])
|
||||||
|
|
||||||
let query = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
let query = text.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
if query.isSingleEmoji {
|
if query.isSingleEmoji {
|
||||||
signals = .single([context.engine.stickers.searchStickers(query: nil, emoticon: [text.basicEmoji.0])
|
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" {
|
} 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)
|
var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query.lowercased(), completeMatch: query.count < 3)
|
||||||
if !languageCode.lowercased().hasPrefix("en") {
|
if !languageCode.lowercased().hasPrefix("en") {
|
||||||
@ -377,10 +377,10 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
signals = signal
|
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 }
|
let emoticon = keywords.flatMap { $0.emoticons }.map { $0.basicEmoji.0 }
|
||||||
return [context.engine.stickers.searchStickers(query: query, emoticon: emoticon, inputLanguageCode: languageCode)
|
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)
|
return combineLatest(signals)
|
||||||
}).start(next: { results in
|
}).start(next: { results in
|
||||||
var result: [(String?, FoundStickerItem)] = []
|
var result: [(String?, FoundStickerItem)] = []
|
||||||
for (emoji, stickers) in results {
|
var allAreFinal = true
|
||||||
|
for (emoji, stickers, isFinal) in results {
|
||||||
for sticker in stickers {
|
for sticker in stickers {
|
||||||
result.append((emoji, sticker))
|
result.append((emoji, sticker))
|
||||||
}
|
}
|
||||||
|
if !isFinal {
|
||||||
|
allAreFinal = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
subscriber.putNext(result)
|
subscriber.putNext((result, allAreFinal))
|
||||||
}, completed: {
|
}, completed: {
|
||||||
// subscriber.putCompletion()
|
// subscriber.putCompletion()
|
||||||
})
|
})
|
||||||
@ -456,7 +460,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|
|||||||
|
|
||||||
signal = combineLatest(stickers, packs)
|
signal = combineLatest(stickers, packs)
|
||||||
|> map { stickers, packs -> ([(String?, FoundStickerItem)], FoundStickerSets, Bool, FoundStickerSets?)? in
|
|> 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)
|
self.updateActivity?(true)
|
||||||
} else {
|
} else {
|
||||||
|
@ -344,98 +344,93 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
let entities = generateChatInputTextEntities(self.textInputState.text)
|
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 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 completion = component.completion
|
||||||
|
|
||||||
let _ = (inputData
|
let signal = BotCheckoutController.InputData.fetch(context: component.context, source: source)
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] inputData in
|
|> `catch` { _ -> Signal<BotCheckoutController.InputData, SendBotPaymentFormError> in
|
||||||
guard let inputData else {
|
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
|
return
|
||||||
}
|
}
|
||||||
let _ = (component.context.engine.payments.sendStarsPaymentForm(formId: inputData.form.id, source: source)
|
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
if let self, peerId.namespace == Namespaces.Peer.CloudChannel, let controller = self.environment?.controller(), let navigationController = controller.navigationController as? NavigationController {
|
var controllers = navigationController.viewControllers
|
||||||
var controllers = navigationController.viewControllers
|
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) }
|
||||||
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) }
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
|
||||||
|
|
||||||
let tooltipController = UndoOverlayController(
|
|
||||||
presentationData: presentationData,
|
|
||||||
content: .sticker(
|
|
||||||
context: context,
|
|
||||||
file: starGift.file,
|
|
||||||
loop: true,
|
|
||||||
title: nil,
|
|
||||||
text: presentationData.strings.Gift_Send_Success(self.peerMap[peerId]?.compactDisplayTitle ?? "", presentationData.strings.Gift_Send_Success_Stars(Int32(starGift.price))).string,
|
|
||||||
undoText: nil,
|
|
||||||
customAction: nil
|
|
||||||
),
|
|
||||||
action: { _ in return true }
|
|
||||||
)
|
|
||||||
(navigationController.viewControllers.last as? ViewController)?.present(tooltipController, in: .current)
|
|
||||||
|
|
||||||
navigationController.view.addSubview(ConfettiView(frame: navigationController.view.bounds))
|
|
||||||
}
|
|
||||||
|
|
||||||
if let completion {
|
let tooltipController = UndoOverlayController(
|
||||||
completion()
|
presentationData: presentationData,
|
||||||
|
content: .sticker(
|
||||||
if let self, let controller = self.environment?.controller() {
|
context: context,
|
||||||
controller.dismiss()
|
file: starGift.file,
|
||||||
}
|
loop: true,
|
||||||
} else {
|
title: nil,
|
||||||
guard let self, let controller = self.environment?.controller(), let navigationController = controller.navigationController as? NavigationController else {
|
text: presentationData.strings.Gift_Send_Success(self.peerMap[peerId]?.compactDisplayTitle ?? "", presentationData.strings.Gift_Send_Success_Stars(Int32(starGift.price))).string,
|
||||||
return
|
undoText: nil,
|
||||||
}
|
customAction: nil
|
||||||
|
),
|
||||||
if peerId.namespace != Namespaces.Peer.CloudChannel {
|
action: { _ in return true }
|
||||||
var controllers = navigationController.viewControllers
|
)
|
||||||
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) && !($0 is PeerInfoScreen) && !($0 is ContactSelectionController) }
|
(navigationController.viewControllers.last as? ViewController)?.present(tooltipController, in: .current)
|
||||||
var foundController = false
|
|
||||||
for controller in controllers.reversed() {
|
navigationController.view.addSubview(ConfettiView(frame: navigationController.view.bounds))
|
||||||
if let chatController = controller as? ChatController, case .peer(id: component.peerId) = chatController.chatLocation {
|
} else if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||||
chatController.hintPlayNextOutgoingGift()
|
var controllers = navigationController.viewControllers
|
||||||
foundController = true
|
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) && !($0 is PeerInfoScreen) && !($0 is ContactSelectionController) }
|
||||||
break
|
var foundController = false
|
||||||
}
|
for controller in controllers.reversed() {
|
||||||
}
|
if let chatController = controller as? ChatController, case .peer(id: component.peerId) = chatController.chatLocation {
|
||||||
if !foundController {
|
chatController.hintPlayNextOutgoingGift()
|
||||||
let chatController = component.context.sharedContext.makeChatController(context: component.context, chatLocation: .peer(id: component.peerId), subject: nil, botStart: nil, mode: .standard(.default), params: nil)
|
foundController = true
|
||||||
chatController.hintPlayNextOutgoingGift()
|
break
|
||||||
controllers.append(chatController)
|
|
||||||
}
|
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !foundController {
|
||||||
starsContext.load(force: true)
|
let chatController = component.context.sharedContext.makeChatController(context: component.context, chatLocation: .peer(id: component.peerId), subject: nil, botStart: nil, mode: .standard(.default), params: nil)
|
||||||
}, error: { [weak self] error in
|
chatController.hintPlayNextOutgoingGift()
|
||||||
guard let self, let controller = self.environment?.controller() else {
|
controllers.append(chatController)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let completion {
|
||||||
|
completion()
|
||||||
|
|
||||||
self.inProgress = false
|
if let controller = self.environment?.controller() {
|
||||||
self.state?.updated()
|
controller.dismiss()
|
||||||
|
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
|
||||||
var errorText: String?
|
|
||||||
switch error {
|
|
||||||
case .starGiftOutOfStock:
|
|
||||||
errorText = presentationData.strings.Gift_Send_ErrorOutOfStock
|
|
||||||
default:
|
|
||||||
errorText = presentationData.strings.Gift_Send_ErrorUnknown
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if let errorText = errorText {
|
|
||||||
let alertController = textAlertController(context: component.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
starsContext.load(force: true)
|
||||||
controller.present(alertController, in: .window(.root))
|
}, error: { [weak self] error in
|
||||||
}
|
guard let self, let controller = self.environment?.controller() else {
|
||||||
})
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inProgress = false
|
||||||
|
self.state?.updated()
|
||||||
|
|
||||||
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
var errorText: String?
|
||||||
|
switch error {
|
||||||
|
case .starGiftOutOfStock:
|
||||||
|
errorText = presentationData.strings.Gift_Send_ErrorOutOfStock
|
||||||
|
default:
|
||||||
|
errorText = presentationData.strings.Gift_Send_ErrorUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
if let errorText = errorText {
|
||||||
|
let alertController = textAlertController(context: component.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
||||||
|
controller.present(alertController, in: .window(.root))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3112,10 +3112,13 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
}
|
}
|
||||||
self.entitiesView.canInteract = { [weak self] in
|
self.entitiesView.canInteract = { [weak self] in
|
||||||
if let self, let controller = self.controller {
|
if let self, let controller = self.controller {
|
||||||
return !controller.node.recording.isActive
|
if controller.node.recording.isActive {
|
||||||
} else {
|
return false
|
||||||
return true
|
} else if case .avatarEditor = controller.mode, self.drawingScreen == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.availableReactionsDisposable = (allowedStoryReactions(context: controller.context)
|
self.availableReactionsDisposable = (allowedStoryReactions(context: controller.context)
|
||||||
@ -3252,11 +3255,12 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
if let mediaEntityView = self.entitiesView.add(mediaEntity, announce: false) as? DrawingMediaEntityView {
|
if let mediaEntityView = self.entitiesView.add(mediaEntity, announce: false) as? DrawingMediaEntityView {
|
||||||
self.entitiesView.sendSubviewToBack(mediaEntityView)
|
self.entitiesView.sendSubviewToBack(mediaEntityView)
|
||||||
mediaEntityView.updated = { [weak self, weak mediaEntity] in
|
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 rotation = mediaEntity.rotation - initialRotation
|
||||||
let position = CGPoint(x: mediaEntity.position.x - initialPosition.x, y: mediaEntity.position.y - initialPosition.y)
|
let position = CGPoint(x: mediaEntity.position.x - initialPosition.x, y: mediaEntity.position.y - initialPosition.y)
|
||||||
let scale = mediaEntity.scale / initialScale
|
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)
|
self.updateMaskDrawingView(position: position, scale: scale, rotation: rotation)
|
||||||
}
|
}
|
||||||
@ -3465,6 +3469,13 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}) as? DrawingStickerEntityView {
|
}) 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
|
existingEntityView.isNightTheme = isNightTheme
|
||||||
let messageEntity = existingEntityView.entity as! DrawingStickerEntity
|
let messageEntity = existingEntityView.entity as! DrawingStickerEntity
|
||||||
messageEntity.renderImage = result.dayImage
|
messageEntity.renderImage = result.dayImage
|
||||||
@ -5613,6 +5624,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
self.previousDrawingData = self.drawingView.drawingData
|
self.previousDrawingData = self.drawingView.drawingData
|
||||||
self.previousDrawingEntities = self.entitiesView.entities
|
self.previousDrawingEntities = self.entitiesView.entities
|
||||||
|
|
||||||
|
self.cropScrollView?.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.interaction?.deactivate()
|
self.interaction?.deactivate()
|
||||||
let controller = DrawingScreen(
|
let controller = DrawingScreen(
|
||||||
context: self.context,
|
context: self.context,
|
||||||
@ -5668,6 +5681,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
|
|
||||||
self.previousDrawingData = nil
|
self.previousDrawingData = nil
|
||||||
self.previousDrawingEntities = nil
|
self.previousDrawingEntities = nil
|
||||||
|
|
||||||
|
self.cropScrollView?.isUserInteractionEnabled = true
|
||||||
}
|
}
|
||||||
controller.requestApply = { [weak controller, weak self] in
|
controller.requestApply = { [weak controller, weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -5690,6 +5705,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
|
|
||||||
self.interaction?.activate()
|
self.interaction?.activate()
|
||||||
self.entitiesView.selectEntity(nil)
|
self.entitiesView.selectEntity(nil)
|
||||||
|
|
||||||
|
self.cropScrollView?.isUserInteractionEnabled = true
|
||||||
}
|
}
|
||||||
self.controller?.present(controller, in: .current)
|
self.controller?.present(controller, in: .current)
|
||||||
self.animateOutToTool(tool: mode)
|
self.animateOutToTool(tool: mode)
|
||||||
@ -7594,6 +7611,13 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
let values = mediaEditor.values.withUpdatedCoverDimensions(dimensions)
|
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
|
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 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.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?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
|
||||||
self?.dismiss()
|
self?.dismiss()
|
||||||
|
@ -141,11 +141,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
self.updateScrolling(transition: .immediate)
|
self.updateScrolling(interactive: true, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var notify = false
|
private var notify = false
|
||||||
func updateScrolling(transition: ComponentTransition) {
|
func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
|
||||||
if let starsProducts = self.starsProducts, let params = self.currentParams {
|
if let starsProducts = self.starsProducts, let params = self.currentParams {
|
||||||
let optionSpacing: CGFloat = 10.0
|
let optionSpacing: CGFloat = 10.0
|
||||||
let itemsSideInset = params.sideInset + 16.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)
|
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()
|
self.profileGifts.loadMore()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,9 +293,11 @@ private final class SheetContent: CombinedComponent {
|
|||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: background.size.height / 2.0))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var isExtendedMedia = false
|
||||||
let subject: StarsImageComponent.Subject
|
let subject: StarsImageComponent.Subject
|
||||||
if !component.extendedMedia.isEmpty {
|
if !component.extendedMedia.isEmpty {
|
||||||
subject = .extendedMedia(component.extendedMedia)
|
subject = .extendedMedia(component.extendedMedia)
|
||||||
|
isExtendedMedia = true
|
||||||
} else if let peer = state.botPeer {
|
} else if let peer = state.botPeer {
|
||||||
if let photo = component.invoice.photo {
|
if let photo = component.invoice.photo {
|
||||||
subject = .photo(photo)
|
subject = .photo(photo)
|
||||||
@ -381,7 +383,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
contentSize.height += title.size.height
|
contentSize.height += title.size.height
|
||||||
contentSize.height += 13.0
|
contentSize.height += 13.0
|
||||||
|
|
||||||
if isBot, let peer = state.botPeer {
|
if isBot && !isExtendedMedia, let peer = state.botPeer {
|
||||||
contentSize.height -= 3.0
|
contentSize.height -= 3.0
|
||||||
let peerShortcut = peerShortcut.update(
|
let peerShortcut = peerShortcut.update(
|
||||||
component: PremiumPeerShortcutComponent(
|
component: PremiumPeerShortcutComponent(
|
||||||
@ -650,48 +652,49 @@ private final class SheetContent: CombinedComponent {
|
|||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + button.size.height / 2.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + button.size.height / 2.0))
|
||||||
)
|
)
|
||||||
contentSize.height += button.size.height
|
contentSize.height += button.size.height
|
||||||
if isSubscription {
|
|
||||||
contentSize.height += 14.0
|
let termsText = isSubscription ? strings.Stars_Subscription_Terms : strings.Stars_Transfer_Terms
|
||||||
|
let termsURL = isSubscription ? strings.Stars_Subscription_Terms_URL : strings.Stars_Transfer_Terms_URL
|
||||||
let termsTextFont = Font.regular(13.0)
|
|
||||||
let termsTextColor = theme.actionSheet.secondaryTextColor
|
contentSize.height += 14.0
|
||||||
let termsLinkColor = theme.actionSheet.controlAccentColor
|
|
||||||
let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsTextFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsTextFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsTextFont, textColor: termsLinkColor), linkAttribute: { contents in
|
let termsTextFont = Font.regular(13.0)
|
||||||
return (TelegramTextAttributes.URL, contents)
|
let termsTextColor = theme.actionSheet.secondaryTextColor
|
||||||
})
|
let termsLinkColor = theme.actionSheet.controlAccentColor
|
||||||
let info = info.update(
|
let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsTextFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsTextFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsTextFont, textColor: termsLinkColor), linkAttribute: { contents in
|
||||||
component: BalancedTextComponent(
|
return (TelegramTextAttributes.URL, contents)
|
||||||
text: .markdown(
|
})
|
||||||
text: strings.Stars_Subscription_Terms,
|
let info = info.update(
|
||||||
attributes: termsMarkdownAttributes
|
component: BalancedTextComponent(
|
||||||
),
|
text: .markdown(
|
||||||
horizontalAlignment: .center,
|
text: termsText,
|
||||||
maximumNumberOfLines: 0,
|
attributes: termsMarkdownAttributes
|
||||||
lineSpacing: 0.2,
|
|
||||||
highlightColor: linkColor.withAlphaComponent(0.2),
|
|
||||||
highlightAction: { attributes in
|
|
||||||
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
|
|
||||||
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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: {})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
|
horizontalAlignment: .center,
|
||||||
transition: .immediate
|
maximumNumberOfLines: 0,
|
||||||
)
|
lineSpacing: 0.2,
|
||||||
context.add(info
|
highlightColor: linkColor.withAlphaComponent(0.2),
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + info.size.height / 2.0))
|
highlightAction: { attributes in
|
||||||
)
|
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
|
||||||
contentSize.height += info.size.height
|
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
|
||||||
|
} else {
|
||||||
}
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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: termsURL, forceExternal: false, presentationData: presentationData, navigationController: navigationController, dismissInput: {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: constrainedTitleWidth, height: context.availableSize.height),
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
context.add(info
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + info.size.height / 2.0))
|
||||||
|
)
|
||||||
|
contentSize.height += info.size.height
|
||||||
|
|
||||||
contentSize.height += 48.0
|
contentSize.height += 48.0
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user