diff --git a/build-system/Make/Make.py b/build-system/Make/Make.py index 708145fd2c..efe4ac0209 100644 --- a/build-system/Make/Make.py +++ b/build-system/Make/Make.py @@ -622,7 +622,7 @@ def build(bazel, arguments): sys.exit(1) shutil.copyfile(ipa_paths[0], artifacts_path + '/Telegram.ipa') - dsym_paths = glob.glob('bazel-out/applebin_ios-ios_arm*-opt-ST-*/bin/Telegram/*.dSYM') + dsym_paths = glob.glob('bazel-bin/Telegram/**/.dSYM') for dsym_path in dsym_paths: file_name = os.path.basename(dsym_path) shutil.copytree(dsym_path, artifacts_path + '/DSYMs/{}'.format(file_name)) diff --git a/submodules/DrawingUI/Sources/DrawingEntitiesView.swift b/submodules/DrawingUI/Sources/DrawingEntitiesView.swift index bf291f7888..505d0748bb 100644 --- a/submodules/DrawingUI/Sources/DrawingEntitiesView.swift +++ b/submodules/DrawingUI/Sources/DrawingEntitiesView.swift @@ -631,6 +631,7 @@ public final class DrawingEntitiesView: UIView, TGPhotoDrawingEntitiesView { let location = gestureRecognzier.location(in: self) if let entityView = self.entity(at: location) { self.selectEntity(entityView.entity) + entityView.onSelection() } } @@ -949,6 +950,9 @@ public class DrawingEntityView: UIView { self.layer.animateKeyframes(values: values as [NSNumber], keyTimes: keyTimes as [NSNumber], duration: 0.3, keyPath: "transform.scale") } + func onSelection() { + } + func selectedTapAction() -> Bool { return false } diff --git a/submodules/DrawingUI/Sources/DrawingLocationEntity.swift b/submodules/DrawingUI/Sources/DrawingLocationEntity.swift index ca237ba4f3..832f8b53b2 100644 --- a/submodules/DrawingUI/Sources/DrawingLocationEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingLocationEntity.swift @@ -383,31 +383,7 @@ public final class DrawingLocationEntityView: DrawingEntityView, UITextViewDeleg } func getRenderSubEntities() -> [DrawingEntity] { -// let textSize = self.textView.bounds.size -// let textPosition = self.locationEntity.position -// let scale = self.locationEntity.scale -// let rotation = self.locationEntity.rotation -// -// let itemSize: CGFloat = floor(24.0 * self.displayFontSize * 0.78 / 17.0) - - let entities: [DrawingEntity] = [] -// for (emojiRect, emojiAttribute) in self.emojiRects { -// guard let file = emojiAttribute.file else { -// continue -// } -// let emojiTextPosition = emojiRect.center.offsetBy(dx: -textSize.width / 2.0, dy: -textSize.height / 2.0) -// -// let entity = DrawingStickerEntity(content: .file(file)) -// entity.referenceDrawingSize = CGSize(width: itemSize * 4.0, height: itemSize * 4.0) -// entity.scale = scale -// entity.position = textPosition.offsetBy( -// dx: (emojiTextPosition.x * cos(rotation) - emojiTextPosition.y * sin(rotation)) * scale, -// dy: (emojiTextPosition.y * cos(rotation) + emojiTextPosition.x * sin(rotation)) * scale -// ) -// entity.rotation = rotation -// entities.append(entity) -// } - return entities + return [] } } diff --git a/submodules/DrawingUI/Sources/DrawingStickerEntity.swift b/submodules/DrawingUI/Sources/DrawingStickerEntity.swift index 2841e1ddeb..7cf2e21e96 100644 --- a/submodules/DrawingUI/Sources/DrawingStickerEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingStickerEntity.swift @@ -29,7 +29,9 @@ public final class DrawingStickerEntityView: DrawingEntityView { private var currentSize: CGSize? - private var backgroundNode: ASImageNode? + private var backgroundView: UIImageView? + private var outlineView: UIImageView? + private let imageNode: TransformImageNode private var animationNode: AnimatedStickerNode? private var videoNode: UniversalVideoNode? @@ -47,12 +49,16 @@ public final class DrawingStickerEntityView: DrawingEntityView { super.init(context: context, entity: entity) if case .file(_, .reaction) = entity.content { - let backgroundNode = ASImageNode() - backgroundNode.layer.zPosition = -1000.0 - backgroundNode.image = UIImage(bundleImageName: "Media Editor/ReactionBackground") - backgroundNode.displaysAsynchronously = false - self.addSubnode(backgroundNode) - self.backgroundNode = backgroundNode + let backgroundView = UIImageView(image: UIImage(bundleImageName: "Stories/ReactionShadow")) + backgroundView.layer.zPosition = -1000.0 + + let outlineView = UIImageView(image: UIImage(bundleImageName: "Stories/ReactionOutline")) + outlineView.tintColor = .white + backgroundView.addSubview(outlineView) + + self.addSubview(backgroundView) + self.backgroundView = backgroundView + self.outlineView = outlineView } self.addSubview(self.imageNode.view) @@ -296,7 +302,7 @@ public final class DrawingStickerEntityView: DrawingEntityView { let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 384.0, height: 384.0)) let source = AnimatedStickerResourceSource(account: self.context.account, resource: file.resource, isVideo: file.isVideoSticker || file.mimeType == "video/webm") let pathPrefix = self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(file.resource.id) - let playbackMode: AnimatedStickerPlaybackMode = self.stickerEntity.isAnimated ? .loop : .still(.start) + let playbackMode: AnimatedStickerPlaybackMode = .loop self.animationNode?.setup(source: source, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: playbackMode, mode: .direct(cachePathPrefix: pathPrefix)) self.cachedDisposable.set((source.cachedDataPath(width: 384, height: 384) @@ -319,8 +325,9 @@ public final class DrawingStickerEntityView: DrawingEntityView { let sideSize: CGFloat = max(size.width, size.height) var boundingSize = CGSize(width: sideSize, height: sideSize) - if let backgroundNode = self.backgroundNode { - backgroundNode.frame = CGRect(origin: .zero, size: boundingSize).insetBy(dx: -5.0, dy: -5.0) + if let backgroundView = self.backgroundView, let outlineView = self.outlineView { + backgroundView.frame = CGRect(origin: .zero, size: boundingSize).insetBy(dx: -5.0, dy: -5.0) + outlineView.frame = backgroundView.bounds boundingSize = CGSize(width: floor(sideSize * 0.63), height: floor(sideSize * 0.63)) } @@ -368,150 +375,140 @@ public final class DrawingStickerEntityView: DrawingEntityView { } } + override func onSelection() { + self.presentReactionSelection() + } + func onDeselection() { let _ = self.dismissReactionSelection() } private weak var reactionContextNode: ReactionContextNode? - fileprivate func dismissReactionSelection() -> Bool { - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: nil, animatingOutToReaction: false) - self.reactionContextNode = nil - - Queue.mainQueue().after(0.35) { - reactionContextNode.view.removeFromSuperview() - } - - return false - } else { - return true + fileprivate func presentReactionSelection() { + guard let containerView = self.containerView, let superview = containerView.superview?.superview?.superview?.superview, self.reactionContextNode == nil else { + return } - } - - override func selectedTapAction() -> Bool { - if case let .file(_, type) = self.stickerEntity.content, case .reaction = type { - guard let containerView = self.containerView, let superview = containerView.superview?.superview?.superview?.superview, self.reactionContextNode == nil else { - return self.dismissReactionSelection() + + let availableSize = superview.frame.size + let reactionItems = containerView.getAvailableReactions() + + let insets = UIEdgeInsets(top: 64.0, left: 0.0, bottom: 64.0, right: 0.0) + + let layout: (ContainedViewLayoutTransition) -> Void = { [weak self, weak superview] transition in + guard let self, let superview, let reactionContextNode = self.reactionContextNode else { + return } - - let availableSize = superview.frame.size - let reactionItems = containerView.getAvailableReactions() - - let insets = UIEdgeInsets(top: 64.0, left: 0.0, bottom: 64.0, right: 0.0) - - let layout: (ContainedViewLayoutTransition) -> Void = { [weak self, weak superview] transition in - guard let self, let superview, let reactionContextNode = self.reactionContextNode else { - return - } - let anchorRect = self.convert(self.bounds, to: superview).offsetBy(dx: 0.0, dy: -20.0) - reactionContextNode.updateLayout(size: availableSize, insets: insets, anchorRect: anchorRect, centerAligned: true, isCoveredByInput: false, isAnimatingOut: false, transition: transition) - } - - let reactionContextNodeTransition: Transition = .immediate - let reactionContextNode: ReactionContextNode - reactionContextNode = ReactionContextNode( - context: self.context, - animationCache: self.context.animationCache, - presentationData: self.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkPresentationTheme), - items: reactionItems.map(ReactionContextItem.reaction), - selectedItems: Set(), - title: nil, - getEmojiContent: { [weak self] animationCache, animationRenderer in - guard let self else { - preconditionFailure() - } - - let mappedReactionItems: [EmojiComponentReactionItem] = reactionItems.map { reaction -> EmojiComponentReactionItem in - return EmojiComponentReactionItem(reaction: reaction.reaction.rawValue, file: reaction.stillAnimation) - } - - return EmojiPagerContentComponent.emojiInputData( - context: self.context, - animationCache: animationCache, - animationRenderer: animationRenderer, - isStandalone: false, - isStatusSelection: false, - isReactionSelection: true, - isEmojiSelection: false, - hasTrending: false, - topReactionItems: mappedReactionItems, - areUnicodeEmojiEnabled: false, - areCustomEmojiEnabled: true, - chatPeerId: self.context.account.peerId, - selectedItems: Set(), - premiumIfSavedMessages: false - ) - }, - isExpandedUpdated: { transition in - layout(transition) - }, - requestLayout: { transition in - layout(transition) - }, - requestUpdateOverlayWantsToBeBelowKeyboard: { transition in - layout(transition) - } - ) - reactionContextNode.displayTail = true - reactionContextNode.forceTailToRight = true - reactionContextNode.forceDark = true - self.reactionContextNode = reactionContextNode - - reactionContextNode.reactionSelected = { [weak self] updateReaction, _ in + let anchorRect = self.convert(self.bounds, to: superview).offsetBy(dx: 0.0, dy: -20.0) + reactionContextNode.updateLayout(size: availableSize, insets: insets, anchorRect: anchorRect, centerAligned: true, isCoveredByInput: false, isAnimatingOut: false, transition: transition) + } + + let reactionContextNodeTransition: Transition = .immediate + let reactionContextNode: ReactionContextNode + reactionContextNode = ReactionContextNode( + context: self.context, + animationCache: self.context.animationCache, + presentationData: self.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkPresentationTheme), + items: reactionItems.map(ReactionContextItem.reaction), + selectedItems: Set(), + title: nil, + getEmojiContent: { [weak self] animationCache, animationRenderer in guard let self else { + preconditionFailure() + } + + let mappedReactionItems: [EmojiComponentReactionItem] = reactionItems.map { reaction -> EmojiComponentReactionItem in + return EmojiComponentReactionItem(reaction: reaction.reaction.rawValue, file: reaction.stillAnimation) + } + + return EmojiPagerContentComponent.emojiInputData( + context: self.context, + animationCache: animationCache, + animationRenderer: animationRenderer, + isStandalone: false, + isStatusSelection: false, + isReactionSelection: true, + isEmojiSelection: false, + hasTrending: false, + topReactionItems: mappedReactionItems, + areUnicodeEmojiEnabled: false, + areCustomEmojiEnabled: true, + chatPeerId: self.context.account.peerId, + selectedItems: Set(), + premiumIfSavedMessages: false + ) + }, + isExpandedUpdated: { transition in + layout(transition) + }, + requestLayout: { transition in + layout(transition) + }, + requestUpdateOverlayWantsToBeBelowKeyboard: { transition in + layout(transition) + } + ) + reactionContextNode.displayTail = true + reactionContextNode.forceTailToRight = true + reactionContextNode.forceDark = true + self.reactionContextNode = reactionContextNode + + reactionContextNode.reactionSelected = { [weak self] updateReaction, _ in + guard let self else { + return + } + + let _ = (self.context.engine.stickers.availableReactions() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] availableReactions in + guard let self, let availableReactions else { return } - let _ = (self.context.engine.stickers.availableReactions() - |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] availableReactions in - guard let self, let availableReactions else { - return + var animation: TelegramMediaFile? + for reaction in availableReactions.reactions { + if reaction.value == updateReaction.reaction { + animation = reaction.selectAnimation + break } - - var animation: TelegramMediaFile? - for reaction in availableReactions.reactions { - if reaction.value == updateReaction.reaction { - animation = reaction.selectAnimation - break - } - } - - guard let animation else { - return - } - - self.stickerEntity.content = .file(animation, .reaction(updateReaction.reaction)) - - if let animationNode = self.animationNode, let snapshot = animationNode.view.snapshotView(afterScreenUpdates: false) { - snapshot.frame = animationNode.frame - snapshot.layer.transform = animationNode.transform - snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in - snapshot.removeFromSuperview() - }) - snapshot.layer.animateScale(from: 1.0, to: 0.1, duration: 0.2) - self.addSubview(snapshot) - } - self.animationNode?.removeFromSupernode() - self.animationNode = nil - self.didSetUpAnimationNode = false - self.isPlaying = false - self.currentSize = nil - - self.setup() - self.applyVisibility() - self.setNeedsLayout() - - self.animationNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - self.animationNode?.layer.animateScale(from: 0.1, to: 1.0, duration: 0.2) - - let _ = self.dismissReactionSelection() - }) - } - - reactionContextNode.premiumReactionsSelected = { [weak self] file in - let _ = self - let _ = file + } + + guard let animation else { + return + } + + if case let .file(_, type) = self.stickerEntity.content, case let .reaction(_, style) = type { + self.stickerEntity.content = .file(animation, .reaction(updateReaction.reaction, style)) + } + + if let animationNode = self.animationNode, let snapshot = animationNode.view.snapshotView(afterScreenUpdates: false) { + snapshot.frame = animationNode.frame + snapshot.layer.transform = animationNode.transform + snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in + snapshot.removeFromSuperview() + }) + snapshot.layer.animateScale(from: 1.0, to: 0.1, duration: 0.2) + self.addSubview(snapshot) + } + self.animationNode?.removeFromSupernode() + self.animationNode = nil + self.didSetUpAnimationNode = false + self.isPlaying = false + self.currentSize = nil + + self.setup() + self.applyVisibility() + self.setNeedsLayout() + + self.animationNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.animationNode?.layer.animateScale(from: 0.1, to: 1.0, duration: 0.2) + + let _ = self.dismissReactionSelection() + }) + } + + reactionContextNode.premiumReactionsSelected = { [weak self] file in + let _ = self + let _ = file // guard let self, let component = self.component else { // return // } @@ -554,14 +551,53 @@ public final class DrawingStickerEntityView: DrawingEntityView { // component.controller()?.push(controller) // }), elevatedLayout: false, animateInAsReplacement: false, blurred: true, action: { _ in true }) // component.controller()?.present(undoController, in: .current) + } + + let anchorRect = self.convert(self.bounds, to: superview).offsetBy(dx: 0.0, dy: -20.0) + reactionContextNodeTransition.setFrame(view: reactionContextNode.view, frame: CGRect(origin: CGPoint(), size: availableSize)) + reactionContextNode.updateLayout(size: availableSize, insets: insets, anchorRect: anchorRect, centerAligned: true, isCoveredByInput: false, isAnimatingOut: false, transition: reactionContextNodeTransition.containedViewLayoutTransition) + + superview.addSubnode(reactionContextNode) + reactionContextNode.animateIn(from: anchorRect) + } + + fileprivate func dismissReactionSelection() -> Bool { + if let reactionContextNode = self.reactionContextNode { + reactionContextNode.animateOut(to: nil, animatingOutToReaction: false) + self.reactionContextNode = nil + + Queue.mainQueue().after(0.35) { + reactionContextNode.view.removeFromSuperview() } - let anchorRect = self.convert(self.bounds, to: superview).offsetBy(dx: 0.0, dy: -20.0) - reactionContextNodeTransition.setFrame(view: reactionContextNode.view, frame: CGRect(origin: CGPoint(), size: availableSize)) - reactionContextNode.updateLayout(size: availableSize, insets: insets, anchorRect: anchorRect, centerAligned: true, isCoveredByInput: false, isAnimatingOut: false, transition: reactionContextNodeTransition.containedViewLayoutTransition) + return false + } else { + return true + } + } + + override func selectedTapAction() -> Bool { + if case let .file(file, type) = self.stickerEntity.content, case let .reaction(reaction, style) = type { + guard self.reactionContextNode == nil else { + let values = [self.entity.scale, self.entity.scale * 0.93, self.entity.scale] + let keyTimes = [0.0, 0.33, 1.0] + self.layer.animateKeyframes(values: values as [NSNumber], keyTimes: keyTimes as [NSNumber], duration: 0.3, keyPath: "transform.scale") - superview.addSubnode(reactionContextNode) - reactionContextNode.animateIn(from: anchorRect) + let updatedStyle: DrawingStickerEntity.Content.FileType.ReactionStyle + switch style { + case .white: + updatedStyle = .black + case .black: + updatedStyle = .white + } + self.stickerEntity.content = .file(file, .reaction(reaction, updatedStyle)) + + self.update(animated: false) + + return true + } + + self.presentReactionSelection() return true } else { @@ -577,13 +613,22 @@ public final class DrawingStickerEntityView: DrawingEntityView { self.bounds = CGRect(origin: .zero, size: self.dimensions.aspectFitted(size)) self.transform = CGAffineTransformScale(CGAffineTransformMakeRotation(self.stickerEntity.rotation), self.stickerEntity.scale, self.stickerEntity.scale) + if case let .file(_, type) = self.stickerEntity.content, case let .reaction(_, style) = type { + switch style { + case .white: + self.outlineView?.tintColor = .white + case .black: + self.outlineView?.tintColor = UIColor(rgb: 0x000000, alpha: 0.5) + } + } + let isReaction = self.isReaction let staticTransform = CATransform3DMakeScale(self.stickerEntity.mirrored ? -1.0 : 1.0, 1.0, 1.0) if animated { var isCurrentlyMirrored = ((self.imageNode.layer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0) < 0.0 if isReaction { - isCurrentlyMirrored = ((self.backgroundNode?.layer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0) < 0.0 + isCurrentlyMirrored = ((self.backgroundView?.layer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0) < 0.0 } var animationSourceTransform = CATransform3DIdentity var animationTargetTransform = CATransform3DIdentity @@ -596,7 +641,7 @@ public final class DrawingStickerEntityView: DrawingEntityView { animationTargetTransform.m34 = -1.0 / self.imageNode.frame.width } if isReaction { - self.backgroundNode?.transform = animationSourceTransform + self.backgroundView?.layer.transform = animationSourceTransform let values = [1.0, 0.01, 1.0] let keyTimes = [0.0, 0.5, 1.0] @@ -608,7 +653,7 @@ public final class DrawingStickerEntityView: DrawingEntityView { } UIView.animate(withDuration: 0.25, animations: { if isReaction { - self.backgroundNode?.transform = animationTargetTransform + self.backgroundView?.layer.transform = animationTargetTransform } else { self.imageNode.transform = animationTargetTransform self.animationNode?.transform = animationTargetTransform @@ -616,7 +661,7 @@ public final class DrawingStickerEntityView: DrawingEntityView { } }, completion: { finished in if isReaction { - self.backgroundNode?.transform = staticTransform + self.backgroundView?.layer.transform = staticTransform } else { self.imageNode.transform = staticTransform self.animationNode?.transform = staticTransform @@ -627,7 +672,7 @@ public final class DrawingStickerEntityView: DrawingEntityView { CATransaction.begin() CATransaction.setDisableActions(true) if isReaction { - self.backgroundNode?.transform = staticTransform + self.backgroundView?.layer.transform = staticTransform } else { self.imageNode.transform = staticTransform self.animationNode?.transform = staticTransform @@ -676,6 +721,8 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { private let leftHandle = SimpleShapeLayer() private let rightHandle = SimpleShapeLayer() + private var longPressGestureRecognizer: UILongPressGestureRecognizer? + override init(frame: CGRect) { let handleBounds = CGRect(origin: .zero, size: entitySelectionViewHandleSize) let handles = [ @@ -712,6 +759,10 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { entityView.onSnapUpdated(type, snapped) } } + + let longPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:))) + self.addGestureRecognizer(longPressGestureRecognizer) + self.longPressGestureRecognizer = longPressGestureRecognizer } required init?(coder: NSCoder) { @@ -730,6 +781,12 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { private let snapTool = DrawingEntitySnapTool() + @objc private func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) { + if case .began = gestureRecognizer.state { + self.longPressed() + } + } + private var currentHandle: CALayer? override func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) { guard let entityView = self.entityView as? DrawingStickerEntityView, let entity = entityView.entity as? DrawingStickerEntity else { @@ -810,6 +867,8 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { self.snapTool.rotationReset() } entityView.onInteractionUpdated(false) + + entityView.onSelection() default: break } @@ -818,7 +877,7 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { } override func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) { - guard let entityView = self.entityView, let entity = entityView.entity as? DrawingStickerEntity else { + guard let entityView = self.entityView as? DrawingStickerEntityView, let entity = entityView.entity as? DrawingStickerEntity else { return } @@ -828,23 +887,27 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { switch gestureRecognizer.state { case .began, .changed: + let _ = entityView.dismissReactionSelection() + if case .began = gestureRecognizer.state { entityView.onInteractionUpdated(true) } let scale = gestureRecognizer.scale entity.scale = entity.scale * scale - entityView.update() + entityView.update(animated: false) gestureRecognizer.scale = 1.0 case .cancelled, .ended: entityView.onInteractionUpdated(false) + + entityView.onSelection() default: break } } override func handleRotate(_ gestureRecognizer: UIRotationGestureRecognizer) { - guard let entityView = self.entityView, let entity = entityView.entity as? DrawingStickerEntity else { + guard let entityView = self.entityView as? DrawingStickerEntityView, let entity = entityView.entity as? DrawingStickerEntity else { return } @@ -858,6 +921,8 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { switch gestureRecognizer.state { case .began: + let _ = entityView.dismissReactionSelection() + self.snapTool.maybeSkipFromStart(entityView: entityView, rotation: entity.rotation) entityView.onInteractionUpdated(true) case .changed: @@ -866,12 +931,14 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { updatedRotation = self.snapTool.update(entityView: entityView, velocity: velocity, delta: rotation, updatedRotation: updatedRotation) entity.rotation = updatedRotation - entityView.update() + entityView.update(animated: false) gestureRecognizer.rotation = 0.0 case .ended, .cancelled: self.snapTool.rotationReset() entityView.onInteractionUpdated(false) + + entityView.onSelection() default: break } diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift index 0a76b21afd..dd13df6953 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift @@ -99,7 +99,7 @@ public enum CodableDrawingEntity: Equatable { ) ) case let .sticker(entity): - if case let .file(_, type) = entity.content, case let .reaction(reaction) = type { + if case let .file(_, type) = entity.content, case let .reaction(reaction, _) = type { return .reaction( coordinates: coordinates, reaction: reaction diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingStickerEntity.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingStickerEntity.swift index 206d176115..f36e0c4256 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingStickerEntity.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingStickerEntity.swift @@ -20,8 +20,12 @@ public final class DrawingStickerEntity: DrawingEntity, Codable { case dualPhoto } public enum FileType: Equatable { + public enum ReactionStyle: Int32 { + case white + case black + } case sticker - case reaction(MessageReaction.Reaction) + case reaction(MessageReaction.Reaction, ReactionStyle) } case file(TelegramMediaFile, FileType) case image(UIImage, ImageType) @@ -61,6 +65,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable { case uuid case file case reaction + case reactionStyle case imagePath case videoFile case isRectangle @@ -83,7 +88,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable { public var scale: CGFloat { didSet { if case let .file(_, type) = self.content, case .reaction = type { - self.scale = max(0.75, min(2.0, self.scale)) + self.scale = max(0.59, min(1.77, self.scale)) } } } @@ -179,7 +184,11 @@ public final class DrawingStickerEntity: DrawingEntity, Codable { } else if let file = try container.decodeIfPresent(TelegramMediaFile.self, forKey: .file) { let fileType: Content.FileType if let reaction = try container.decodeIfPresent(MessageReaction.Reaction.self, forKey: .reaction) { - fileType = .reaction(reaction) + var reactionStyle: Content.FileType.ReactionStyle = .white + if let style = try container.decodeIfPresent(Int32.self, forKey: .reactionStyle) { + reactionStyle = DrawingStickerEntity.Content.FileType.ReactionStyle(rawValue: style) ?? .white + } + fileType = .reaction(reaction, reactionStyle) } else { fileType = .sticker } @@ -220,8 +229,9 @@ public final class DrawingStickerEntity: DrawingEntity, Codable { case let .file(file, fileType): try container.encode(file, forKey: .file) switch fileType { - case let .reaction(reaction): + case let .reaction(reaction, reactionStyle): try container.encode(reaction, forKey: .reaction) + try container.encode(reactionStyle.rawValue, forKey: .reactionStyle) default: break } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 0df45bcc27..80c0d0b4e0 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -3093,12 +3093,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate let isFirstTime = self.validLayout == nil self.validLayout = layout - let isTablet: Bool - if case .regular = layout.metrics.widthClass { - isTablet = true - } else { - isTablet = false - } + let isTablet = layout.metrics.isTablet var topInset: CGFloat = (layout.statusBarHeight ?? 0.0) + 5.0 let previewSize: CGSize @@ -3240,8 +3235,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate if let reaction = self.availableReactions.first(where: { reaction in return reaction.reaction.rawValue == .builtin(heart) }) { - let stickerEntity = DrawingStickerEntity(content: .file(reaction.stillAnimation, .reaction(.builtin(heart)))) - self.interaction?.insertEntity(stickerEntity, scale: 1.33) + let stickerEntity = DrawingStickerEntity(content: .file(reaction.stillAnimation, .reaction(.builtin(heart), .white))) + self.interaction?.insertEntity(stickerEntity, scale: 1.175) } } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift index 937896d51f..e3e401561f 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift @@ -17,11 +17,16 @@ import EmojiTextAttachmentView import TextFormat final class StoryItemOverlaysView: UIView { + private static let shadowImage: UIImage = { + return UIImage(bundleImageName: "Stories/ReactionShadow")! + }() + private static let coverImage: UIImage = { return UIImage(bundleImageName: "Stories/ReactionOutline")! }() private final class ItemView: HighlightTrackingButton { + private let shadowView: UIImageView private let coverView: UIImageView private var stickerView: EmojiTextAttachmentView? private var file: TelegramMediaFile? @@ -30,10 +35,12 @@ final class StoryItemOverlaysView: UIView { var activate: ((UIView, MessageReaction.Reaction) -> Void)? override init(frame: CGRect) { + self.shadowView = UIImageView(image: StoryItemOverlaysView.shadowImage) self.coverView = UIImageView(image: StoryItemOverlaysView.coverImage) super.init(frame: frame) + self.addSubview(self.shadowView) self.addSubview(self.coverView) self.highligthedChanged = { [weak self] highlighted in @@ -75,6 +82,7 @@ final class StoryItemOverlaysView: UIView { let insets = UIEdgeInsets(top: -0.08, left: -0.05, bottom: -0.01, right: -0.02) self.coverView.frame = CGRect(origin: CGPoint(x: size.width * insets.left, y: size.height * insets.top), size: CGSize(width: size.width - size.width * insets.left - size.width * insets.right, height: size.height - size.height * insets.top - size.height * insets.bottom)) + self.shadowView.frame = self.coverView.frame let minSide = floor(min(200.0, min(size.width, size.height)) * 0.65) let itemSize = CGSize(width: minSide, height: minSide) diff --git a/submodules/TelegramUI/Images.xcassets/Media Editor/ReactionBackground.imageset/Reaction Sticker.pdf b/submodules/TelegramUI/Images.xcassets/Media Editor/ReactionBackground.imageset/Reaction Sticker.pdf deleted file mode 100644 index 80a343fff4..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Media Editor/ReactionBackground.imageset/Reaction Sticker.pdf and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/Contents.json index 6b154d429e..6aa722d216 100644 --- a/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "ReactionOutline.pdf", + "filename" : "ReactionBackground.pdf", "idiom" : "universal" } ], @@ -10,6 +10,7 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } } diff --git a/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/ReactionBackground.pdf b/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/ReactionBackground.pdf new file mode 100644 index 0000000000..e7652e8839 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/ReactionBackground.pdf @@ -0,0 +1,81 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 -0.000000 0.000000 1.000000 10.000000 6.999893 cm +1.000000 1.000000 1.000000 scn +99.999992 53.000168 m +99.999992 80.614403 77.614227 103.000168 49.999989 103.000168 c +22.385752 103.000168 -0.000011 80.614403 -0.000011 53.000168 c +-0.000011 25.385933 22.385752 3.000168 49.999989 3.000168 c +59.513222 3.000168 68.405922 5.656982 75.976578 10.269112 c +77.951065 8.841515 80.377281 8.000114 83.000015 8.000114 c +89.627434 8.000114 95.000015 13.372696 95.000015 20.000114 c +95.000015 22.622849 94.158615 25.049057 92.731018 27.023544 c +97.343163 34.594208 99.999992 43.486919 99.999992 53.000168 c +h +103.000023 5.000061 m +103.000023 2.238640 100.761444 0.000061 98.000023 0.000061 c +95.238602 0.000061 93.000023 2.238640 93.000023 5.000061 c +93.000023 7.761482 95.238602 10.000061 98.000023 10.000061 c +100.761444 10.000061 103.000023 7.761482 103.000023 5.000061 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 910 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 120.000000 120.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001000 00000 n +0000001022 00000 n +0000001197 00000 n +0000001271 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1330 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/ReactionOutline.pdf b/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/ReactionOutline.pdf deleted file mode 100644 index 80a343fff4..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Stories/ReactionOutline.imageset/ReactionOutline.pdf and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Media Editor/ReactionBackground.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Stories/ReactionShadow.imageset/Contents.json similarity index 74% rename from submodules/TelegramUI/Images.xcassets/Media Editor/ReactionBackground.imageset/Contents.json rename to submodules/TelegramUI/Images.xcassets/Stories/ReactionShadow.imageset/Contents.json index bf136df2b8..353304fdb1 100644 --- a/submodules/TelegramUI/Images.xcassets/Media Editor/ReactionBackground.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Stories/ReactionShadow.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Reaction Sticker.pdf", + "filename" : "ReactionShadow.pdf", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Stories/ReactionShadow.imageset/ReactionShadow.pdf b/submodules/TelegramUI/Images.xcassets/Stories/ReactionShadow.imageset/ReactionShadow.pdf new file mode 100644 index 0000000000..2ac18567dc Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Stories/ReactionShadow.imageset/ReactionShadow.pdf differ