diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index c6062f9f63..18b04c5803 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -387,7 +387,13 @@ public struct AttachmentMainButtonState { case center } + public enum Font: Equatable { + case regular + case bold + } + public let text: String? + public let font: Font public let background: Background public let textColor: UIColor public let isVisible: Bool @@ -396,6 +402,7 @@ public struct AttachmentMainButtonState { public init( text: String?, + font: Font, background: Background, textColor: UIColor, isVisible: Bool, @@ -403,6 +410,7 @@ public struct AttachmentMainButtonState { isEnabled: Bool ) { self.text = text + self.font = font self.background = background self.textColor = textColor self.isVisible = isVisible @@ -411,7 +419,7 @@ public struct AttachmentMainButtonState { } static var initial: AttachmentMainButtonState { - return AttachmentMainButtonState(text: nil, background: .color(.clear), textColor: .clear, isVisible: false, progress: .none, isEnabled: false) + return AttachmentMainButtonState(text: nil, font: .bold, background: .color(.clear), textColor: .clear, isVisible: false, progress: .none, isEnabled: false) } } @@ -643,7 +651,14 @@ private final class MainButtonNode: HighlightTrackingButtonNode { self.setupShimmering() if let text = state.text { - self.textNode.attributedText = NSAttributedString(string: text, font: Font.semibold(17.0), textColor: state.textColor) + let font: UIFont + switch state.font { + case .regular: + font = Font.regular(17.0) + case .bold: + font = Font.semibold(17.0) + } + self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: state.textColor) let textSize = self.textNode.updateLayout(size) self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize) @@ -1267,7 +1282,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { func updateMainButtonState(_ mainButtonState: AttachmentMainButtonState?) { var currentButtonState = self.mainButtonState if mainButtonState == nil { - currentButtonState = AttachmentMainButtonState(text: currentButtonState.text, background: currentButtonState.background, textColor: currentButtonState.textColor, isVisible: false, progress: .none, isEnabled: currentButtonState.isEnabled) + currentButtonState = AttachmentMainButtonState(text: currentButtonState.text, font: currentButtonState.font, background: currentButtonState.background, textColor: currentButtonState.textColor, isVisible: false, progress: .none, isEnabled: currentButtonState.isEnabled) } self.mainButtonState = mainButtonState ?? currentButtonState } @@ -1417,6 +1432,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { self.scrollNode.isUserInteractionEnabled = !isSelecting let isButtonVisible = self.mainButtonState.isVisible + let isNarrowButton = isButtonVisible && self.mainButtonState.font == .regular var insets = layout.insets(options: []) if let inputHeight = layout.inputHeight, inputHeight > 0.0 && (isSelecting || isButtonVisible) { @@ -1457,7 +1473,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { if isButtonVisible { var height: CGFloat if layout.intrinsicInsets.bottom > 0.0 && (layout.inputHeight ?? 0.0).isZero { - height = bounds.height + 9.0 + height = bounds.height if case .regular = layout.metrics.widthClass { if self.isStandalone { height -= 3.0 @@ -1466,7 +1482,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { } } } else { - height = bounds.height + 9.0 + 8.0 + height = bounds.height + 8.0 + } + if !isNarrowButton { + height += 9.0 } containerFrame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: height)) } else if isSelecting { @@ -1532,11 +1551,13 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { let sideInset: CGFloat = 16.0 let buttonSize = CGSize(width: layout.size.width - (sideInset + layout.safeInsets.left) * 2.0, height: 50.0) + let buttonTopInset: CGFloat = isNarrowButton ? 2.0 : 8.0 + if !self.dismissed { self.mainButtonNode.updateLayout(size: buttonSize, state: self.mainButtonState, transition: transition) } if !self.animatingTransition { - transition.updateFrame(node: self.mainButtonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + sideInset, y: isButtonVisible || self.fromMenu ? 8.0 : containerFrame.height), size: buttonSize)) + transition.updateFrame(node: self.mainButtonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + sideInset, y: isButtonVisible || self.fromMenu ? buttonTopInset : containerFrame.height), size: buttonSize)) } return containerFrame.height diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 7da26bf271..c06f852960 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -1238,7 +1238,24 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { private var isDismissing = false - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer?, threadTitle: String?, chatLocation: ChatLocation?, bannedSendPhotos: (Int32, Bool)?, bannedSendVideos: (Int32, Bool)?, subject: Subject, editingContext: TGMediaEditingContext? = nil, selectionContext: TGMediaSelectionContext? = nil, saveEditedPhotos: Bool = false) { + fileprivate let mainButtonState: AttachmentMainButtonState? + private let mainButtonAction: (() -> Void)? + + public init( + context: AccountContext, + updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, + peer: EnginePeer?, + threadTitle: String?, + chatLocation: ChatLocation?, + bannedSendPhotos: (Int32, Bool)?, + bannedSendVideos: (Int32, Bool)?, + subject: Subject, + editingContext: TGMediaEditingContext? = nil, + selectionContext: TGMediaSelectionContext? = nil, + saveEditedPhotos: Bool = false, + mainButtonState: AttachmentMainButtonState? = nil, + mainButtonAction: (() -> Void)? = nil + ) { self.context = context let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } @@ -1251,6 +1268,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { self.bannedSendVideos = bannedSendVideos self.subject = subject self.saveEditedPhotos = saveEditedPhotos + self.mainButtonState = mainButtonState + self.mainButtonAction = mainButtonAction let selectionContext = selectionContext ?? TGMediaSelectionContext() @@ -1627,6 +1646,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } } + func mainButtonPressed() { + self.mainButtonAction?() + } + func dismissAllTooltips() { self.undoOverlayController?.dismissWithCommitAction() } @@ -1811,21 +1834,17 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } public var mediaPickerContext: AttachmentMediaPickerContext? { - if let interaction = self.interaction { - return MediaPickerContext(interaction: interaction) - } else { - return nil - } + return MediaPickerContext(controller: self) } } final class MediaPickerContext: AttachmentMediaPickerContext { - private weak var interaction: MediaPickerInteraction? + private weak var controller: MediaPickerScreen? var selectionCount: Signal { return Signal { [weak self] subscriber in - let disposable = self?.interaction?.selectionState?.selectionChangedSignal().start(next: { [weak self] value in - subscriber.putNext(Int(self?.interaction?.selectionState?.count() ?? 0)) + let disposable = self?.controller?.interaction?.selectionState?.selectionChangedSignal().start(next: { [weak self] value in + subscriber.putNext(Int(self?.controller?.interaction?.selectionState?.count() ?? 0)) }, error: { _ in }, completed: { }) return ActionDisposable { disposable?.dispose() @@ -1835,7 +1854,7 @@ final class MediaPickerContext: AttachmentMediaPickerContext { var caption: Signal { return Signal { [weak self] subscriber in - let disposable = self?.interaction?.editingState.forcedCaption().start(next: { caption in + let disposable = self?.controller?.interaction?.editingState.forcedCaption().start(next: { caption in if let caption = caption as? NSAttributedString { subscriber.putNext(caption) } else { @@ -1853,27 +1872,27 @@ final class MediaPickerContext: AttachmentMediaPickerContext { } public var mainButtonState: Signal { - return .single(nil) + return .single(self.controller?.mainButtonState) } - init(interaction: MediaPickerInteraction) { - self.interaction = interaction + init(controller: MediaPickerScreen) { + self.controller = controller } func setCaption(_ caption: NSAttributedString) { - self.interaction?.editingState.setForcedCaption(caption, skipUpdate: true) + self.controller?.interaction?.editingState.setForcedCaption(caption, skipUpdate: true) } func send(mode: AttachmentMediaPickerSendMode, attachmentMode: AttachmentMediaPickerAttachmentMode) { - self.interaction?.sendSelected(nil, mode == .silently, mode == .whenOnline ? scheduleWhenOnlineTimestamp : nil, true, {}) + self.controller?.interaction?.sendSelected(nil, mode == .silently, mode == .whenOnline ? scheduleWhenOnlineTimestamp : nil, true, {}) } func schedule() { - self.interaction?.schedule() + self.controller?.interaction?.schedule() } func mainButtonAction() { - + self.controller?.mainButtonPressed() } } @@ -1987,12 +2006,22 @@ public class MediaPickerGridSelectionGesture : UIPanGestureRecognizer { } } -public func standaloneMediaPickerController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, subject: MediaPickerScreen.Subject, completion: @escaping (PHAsset) -> Void = { _ in }) -> ViewController { +public func wallpaperMediaPickerController( + context: AccountContext, + updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, + peer: EnginePeer, + canDelete: Bool, + completion: @escaping (PHAsset) -> Void = { _ in } +) -> ViewController { let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: { return nil }) - controller.requestController = { _, present in - let mediaPickerController = MediaPickerScreen(context: context, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: subject) + controller.requestController = { [weak controller] _, present in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let mediaPickerController = MediaPickerScreen(context: context, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: canDelete ? AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_ResetWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.destructiveActionTextColor, isVisible: true, progress: .none, isEnabled: true) : nil, mainButtonAction: canDelete ? { + let _ = context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: nil).start() + controller?.dismiss(animated: true) + } : nil) mediaPickerController.customSelection = completion present(mediaPickerController, mediaPickerController.mediaPickerContext) } diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index adf80c4f64..bfc61df365 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -645,7 +645,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { price = nil } let buttonText = presentationData.strings.Premium_Gift_GiftSubscription(price ?? "—").string - self.buttonStatePromise.set(.single(AttachmentMainButtonState(text: buttonText, background: .premium, textColor: .white, isVisible: true, progress: self.inProgress ? .center : .none, isEnabled: true))) + self.buttonStatePromise.set(.single(AttachmentMainButtonState(text: buttonText, font: .bold, background: .premium, textColor: .white, isVisible: true, progress: self.inProgress ? .center : .none, isEnabled: true))) } func buy() { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift index 243de44ec9..a4b30a3610 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeColorsGridController.swift @@ -150,7 +150,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina var pushController: (ViewController) -> Void = { _ in } - public init(context: AccountContext, mode: Mode = .default) { + public init(context: AccountContext, mode: Mode = .default, canDelete: Bool = false) { self.context = context self.mode = mode self.presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -190,6 +190,10 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina self.pushController = { [weak self] controller in self?.push(controller) } + + if canDelete { + self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_ResetWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.destructiveActionTextColor, isVisible: true, progress: .none, isEnabled: true))) + } } required public init(coder aDecoder: NSCoder) { @@ -317,7 +321,12 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina } @objc fileprivate func mainButtonPressed() { + guard case let .peer(peer) = self.mode else { + return + } + let _ = self.context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: nil).start() + self.dismiss(animated: true) } public var requestAttachmentMenuExpansion: () -> Void = {} @@ -370,12 +379,12 @@ private final class ThemeColorsGridContext: AttachmentMediaPickerContext { } -public func standaloneColorPickerController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer, push: @escaping (ViewController) -> Void) -> ViewController { +public func standaloneColorPickerController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: EnginePeer, canDelete: Bool, push: @escaping (ViewController) -> Void) -> ViewController { let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: { return nil }) controller.requestController = { _, present in - let colorPickerController = ThemeColorsGridController(context: context, mode: .peer(peer)) + let colorPickerController = ThemeColorsGridController(context: context, mode: .peer(peer), canDelete: canDelete) colorPickerController.pushController = { controller in push(controller) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 68f9c899af..bbd85374e4 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -18520,21 +18520,31 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - let controller = standaloneMediaPickerController(context: strongSelf.context, subject: .assets(nil, .wallpaper), completion: { asset in - guard let strongSelf = self else { - return - } - let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false)) - controller.navigationPresentation = .modal - controller.apply = { [weak self] wallpaper, options, cropRect in - if let strongSelf = self { - uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, peerId: peerId, completion: { - dismissControllers() - }) + var canDelete = false + if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData { + canDelete = cachedUserData.wallpaper != nil + } + let controller = wallpaperMediaPickerController( + context: strongSelf.context, + updatedPresentationData: strongSelf.updatedPresentationData, + peer: EnginePeer(peer), + canDelete: canDelete, + completion: { asset in + guard let strongSelf = self else { + return } + let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false)) + controller.navigationPresentation = .modal + controller.apply = { [weak self] wallpaper, options, cropRect in + if let strongSelf = self { + uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, peerId: peerId, completion: { + dismissControllers() + }) + } + } + strongSelf.push(controller) } - strongSelf.push(controller) - }) + ) controller.navigationPresentation = .flatModal strongSelf.push(controller) }, @@ -18546,7 +18556,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.themeScreen = nil themeController.dimTapped() } - let controller = standaloneColorPickerController(context: strongSelf.context, peer: EnginePeer(peer), push: { [weak self] controller in + + var canDelete = false + if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData { + canDelete = cachedUserData.wallpaper != nil + } + let controller = standaloneColorPickerController(context: strongSelf.context, peer: EnginePeer(peer), canDelete: canDelete, push: { [weak self] controller in if let strongSelf = self { strongSelf.push(controller) } diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index af5b0191e1..e1b7eb7816 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -675,7 +675,7 @@ public final class WebAppController: ViewController, AttachmentContainable { let isLoading = json["is_progress_visible"] as? Bool let isEnabled = json["is_active"] as? Bool - let state = AttachmentMainButtonState(text: text, background: .color(backgroundColor), textColor: textColor, isVisible: isVisible, progress: (isLoading ?? false) ? .side : .none, isEnabled: isEnabled ?? true) + let state = AttachmentMainButtonState(text: text, font: .bold, background: .color(backgroundColor), textColor: textColor, isVisible: isVisible, progress: (isLoading ?? false) ? .side : .none, isEnabled: isEnabled ?? true) self.mainButtonState = state } }