diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index 504bcf075a..8edb125876 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -183,6 +183,7 @@ public class AttachmentController: ViewController { private let fromMenu: Bool private let hasTextInput: Bool private let makeEntityInputView: () -> AttachmentTextInputPanelInputView? + public var animateAppearance: Bool = false public var willDismiss: () -> Void = {} public var didDismiss: () -> Void = {} @@ -619,14 +620,26 @@ public class AttachmentController: ViewController { private var animating = false func animateIn() { - guard let layout = self.validLayout else { + guard let layout = self.validLayout, let controller = self.controller else { return } self.animating = true if case .regular = layout.metrics.widthClass { - self.animating = false - + if controller.animateAppearance { + let targetPosition = self.position + let startPosition = targetPosition.offsetBy(dx: 0.0, dy: layout.size.height) + + self.position = startPosition + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) + transition.animateView(allowUserInteraction: true, { + self.position = targetPosition + }, completion: { _ in + self.animating = false + }) + } else { + self.animating = false + } ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 0.1) } else { ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear).updateAlpha(node: self.dim, alpha: 1.0) diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index e62157c939..257d60b6d0 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -1469,7 +1469,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { } let bounds = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: buttonSize.height + insets.bottom)) - let containerTransition: ContainedViewLayoutTransition + var containerTransition: ContainedViewLayoutTransition let containerFrame: CGRect if isButtonVisible { var height: CGFloat @@ -1520,6 +1520,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { } } + if self.containerNode.frame.size.width.isZero { + containerTransition = .immediate + } + containerTransition.updateFrame(node: self.containerNode, frame: containerFrame) containerTransition.updateFrame(node: self.backgroundNode, frame: containerBounds) self.backgroundNode.update(size: containerBounds.size, transition: transition) diff --git a/submodules/GalleryUI/Sources/GalleryPagerNode.swift b/submodules/GalleryUI/Sources/GalleryPagerNode.swift index 07af78c66f..fbb87ce7c9 100644 --- a/submodules/GalleryUI/Sources/GalleryPagerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryPagerNode.swift @@ -585,7 +585,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest let node = self.itemNodes[i] transition.updateFrame(node: node, frame: CGRect(origin: CGPoint(x: CGFloat(i) * self.scrollView.bounds.size.width + self.pageGap, y: 0.0), size: CGSize(width: self.scrollView.bounds.size.width - self.pageGap * 2.0, height: self.scrollView.bounds.size.height))) - let screenFrame = node.convert(node.bounds, to: self.supernode) + let screenFrame = node.view.convert(node.view.bounds, to: self.view.superview) node.screenFrameUpdated(screenFrame) } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 97c3a39a9d..f13bd2e941 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -2022,12 +2022,14 @@ public func wallpaperMediaPickerController( context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer, + animateAppearance: Bool, completion: @escaping (PHAsset) -> Void = { _ in }, openColors: @escaping () -> Void ) -> ViewController { let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: { return nil }) + controller.animateAppearance = animateAppearance //controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) controller.requestController = { [weak controller] _, present in let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 74405b65f1..0dcdee3f62 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -119,11 +119,8 @@ final class ThemeAccentColorController: ViewController { } else { self.navigationItem.titleView = self.segmentedTitleView } - if case .peer = resultMode { - self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)) - } else { - self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView()) - } + + self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)) } required init(coder aDecoder: NSCoder) { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 12d8f61d15..2044e541f8 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -313,6 +313,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate doneButtonType = .set } self.toolbarNode = WallpaperGalleryToolbarNode(theme: self.theme, strings: self.presentationData.strings, doneButtonType: doneButtonType) + self.toolbarNode.dark = true self.toolbarNode.setDoneIsSolid(true, transition: .immediate) self.maskNode = ASImageNode() @@ -1177,12 +1178,16 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let colorPanelHeight = max(standardInputHeight, layout.inputHeight ?? 0.0) - bottomInset + inputFieldPanelHeight var colorPanelOffset: CGFloat = 0.0 + var colorPanelY = layout.size.height - bottomInset - colorPanelHeight if self.state.colorPanelCollapsed { colorPanelOffset = colorPanelHeight + colorPanelY = layout.size.height } - let colorPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomInset - colorPanelHeight + colorPanelOffset), size: CGSize(width: layout.size.width, height: colorPanelHeight)) + let colorPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: colorPanelY), size: CGSize(width: layout.size.width, height: colorPanelHeight)) bottomInset += (colorPanelHeight - colorPanelOffset) + self.toolbarNode.setDoneIsSolid(!self.state.colorPanelCollapsed, transition: transition) + if bottomInset + navigationBarHeight > bounds.height { return } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift index 36a5493534..75ec7e4f8a 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift @@ -146,7 +146,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina private var previousContentOffset: GridNodeVisibleContentOffset? - fileprivate let mainButtonStatePromise = Promise(nil) + fileprivate var mainButtonState: AttachmentMainButtonState? var pushController: (ViewController) -> Void = { _ in } var dismissControllers: (() -> Void)? @@ -193,7 +193,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina self?.push(controller) } - self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true))) + self.mainButtonState = AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true) } required public init(coder aDecoder: NSCoder) { @@ -362,7 +362,7 @@ private final class ThemeColorsGridContext: AttachmentMediaPickerContext { } public var mainButtonState: Signal { - return self.controller?.mainButtonStatePromise.get() ?? .single(nil) + return .single(self.controller?.mainButtonState) } init(controller: ThemeColorsGridController) { diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index a05ca062e6..4e751c1845 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -960,8 +960,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode { var image = isBlurrable ? image : nil if let imageToScale = image { let actualSize = CGSize(width: imageToScale.size.width * imageToScale.scale, height: imageToScale.size.height * imageToScale.scale) - if actualSize.width > 1280.0 || actualSize.height > 1280.0 { - image = TGScaleImageToPixelSize(image, actualSize.fitted(CGSize(width: 1280.0, height: 1280.0))) + if actualSize.width > 960.0 || actualSize.height > 960.0 { + image = TGScaleImageToPixelSize(image, actualSize.fitted(CGSize(width: 960.0, height: 960.0))) } } strongSelf.blurredNode.image = image @@ -1092,11 +1092,15 @@ final class WallpaperGalleryItemNode: GalleryItemNode { } @objc func toggleBlur() { + guard !self.animatingBlur else { + return + } let value = !self.blurButtonNode.isSelected self.blurButtonNode.setSelected(value, animated: true) self.setBlurEnabled(value, animated: true) } + private var animatingBlur = false func setBlurEnabled(_ enabled: Bool, animated: Bool) { let blurRadius: CGFloat = 30.0 @@ -1114,19 +1118,24 @@ final class WallpaperGalleryItemNode: GalleryItemNode { } if animated { + self.animatingBlur = true self.blurredNode.blurView.blurRadius = 0.0 UIView.animate(withDuration: 0.3, delay: 0.0, options: UIView.AnimationOptions(rawValue: 7 << 16), animations: { self.blurredNode.blurView.blurRadius = blurRadius - }, completion: nil) + }, completion: { _ in + self.animatingBlur = false + }) } else { self.blurredNode.blurView.blurRadius = blurRadius } } else { if self.blurredNode.supernode != nil { if animated { + self.animatingBlur = true UIView.animate(withDuration: 0.3, delay: 0.0, options: UIView.AnimationOptions(rawValue: 7 << 16), animations: { self.blurredNode.blurView.blurRadius = 0.0 }, completion: { finished in + self.animatingBlur = false if finished { self.blurredNode.removeFromSupernode() } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index cd6de0c56d..50db88d5ef 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -18543,6 +18543,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } public func presentThemeSelection() { + guard self.themeScreen == nil else { + return + } let context = self.context let peerId = self.chatLocation.peerId @@ -18618,8 +18621,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G navigationController.setViewControllers(controllers, animated: true) } } - var openWallpaperPickerImpl: (() -> Void)? - let openWallpaperPicker = { [weak self] in + var openWallpaperPickerImpl: ((Bool) -> Void)? + let openWallpaperPicker = { [weak self] animateAppearance in guard let strongSelf = self else { return } @@ -18627,6 +18630,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: EnginePeer(peer), + animateAppearance: animateAppearance, completion: { [weak self] asset in guard let strongSelf = self else { return @@ -18636,7 +18640,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G controller.apply = { [weak self] wallpaper, options, editedImage, cropRect, brightness in if let strongSelf = self { uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, editedImage: editedImage, cropRect: cropRect, brightness: brightness, peerId: peerId, completion: { - dismissControllers() + Queue.mainQueue().after(0.3, { + dismissControllers() + }) }) } } @@ -18651,7 +18657,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.push(controller) } }, openGallery: { - openWallpaperPickerImpl?() + openWallpaperPickerImpl?(false) }) controller.navigationPresentation = .flatModal strongSelf.push(controller) @@ -18661,7 +18667,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.push(controller) } openWallpaperPickerImpl = openWallpaperPicker - openWallpaperPicker() + openWallpaperPicker(true) }, resetWallpaper: { [weak self] in guard let strongSelf = self, let peerId else { diff --git a/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift index 2423b08455..853caa832f 100644 --- a/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageWallpaperBubbleContentNode.swift @@ -286,14 +286,37 @@ class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode { let boundingSize = imageSize var imageSize = boundingSize let updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError> + var patternArguments: PatternWallpaperArguments? switch media.content { - case let .file(file, _, _, _, _, _): + case let .file(file, patternColors, rotation, intensity, _, _): var representations: [ImageRepresentationWithReference] = file.previewRepresentations.map({ ImageRepresentationWithReference(representation: $0, reference: AnyMediaReference.message(message: MessageReference(item.message), media: file).resourceReference($0.resource)) }) if file.mimeType == "image/svg+xml" || file.mimeType == "application/x-tgwallpattern" { representations.append(ImageRepresentationWithReference(representation: .init(dimensions: PixelDimensions(width: 1440, height: 2960), resource: file.resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false), reference: AnyMediaReference.message(message: MessageReference(item.message), media: file).resourceReference(file.resource))) + + var colors: [UIColor] = [] + var customPatternColor: UIColor? = nil + var bakePatternAlpha: CGFloat = 1.0 + if let intensity = intensity, intensity < 0 { + if patternColors.isEmpty { + colors.append(UIColor(rgb: 0xd6e2ee, alpha: 0.5)) + } else { + colors.append(contentsOf: patternColors.map(UIColor.init(rgb:))) + } + customPatternColor = UIColor(white: 0.0, alpha: 1.0 - CGFloat(abs(intensity))) + } else { + if patternColors.isEmpty { + colors.append(UIColor(rgb: 0xd6e2ee, alpha: 0.5)) + } else { + colors.append(contentsOf: patternColors.map(UIColor.init(rgb:))) + } + let isLight = UIColor.average(of: patternColors.map(UIColor.init(rgb:))).hsb.b > 0.3 + customPatternColor = isLight ? .black : .white + bakePatternAlpha = CGFloat(intensity ?? 50) / 100.0 + } + patternArguments = PatternWallpaperArguments(colors: colors, rotation: rotation, customPatternColor: customPatternColor, bakePatternAlpha: bakePatternAlpha) } if ["image/png", "image/svg+xml", "application/x-tgwallpattern"].contains(file.mimeType) { - updateImageSignal = patternWallpaperImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, representations: representations, mode: .screen) + updateImageSignal = patternWallpaperImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, representations: representations, mode: .thumbnail) |> mapToSignal { value -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in if let value { return .single(value) @@ -322,7 +345,7 @@ class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode { strongSelf.imageNode.setSignal(updateImageSignal, attemptSynchronously: synchronousLoads) - let arguments = TransformImageArguments(corners: ImageCorners(radius: boundingSize.width / 2.0), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets()) + let arguments = TransformImageArguments(corners: ImageCorners(radius: boundingSize.width / 2.0), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), custom: patternArguments) let apply = makeImageLayout(arguments) apply() diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index a095843d44..27f6840b40 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4763,8 +4763,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } if let user = peer as? TelegramUser { - if user.botInfo == nil && strongSelf.data?.encryptionKeyFingerprint == nil { - items.append(.action(ContextMenuActionItem(text: "Change Background", icon: { theme in + if user.botInfo == nil && strongSelf.data?.encryptionKeyFingerprint == nil && !user.isDeleted { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ChangeWallpaper, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.dismissWithoutContent)