diff --git a/submodules/Components/SheetComponent/Sources/SheetComponent.swift b/submodules/Components/SheetComponent/Sources/SheetComponent.swift index e4bb4bc549..e0d1b597f9 100644 --- a/submodules/Components/SheetComponent/Sources/SheetComponent.swift +++ b/submodules/Components/SheetComponent/Sources/SheetComponent.swift @@ -9,12 +9,14 @@ public final class SheetComponentEnvironment: Equatable { public let isDisplaying: Bool public let isCentered: Bool public let hasInputHeight: Bool + public let regularMetricsSize: CGSize? public let dismiss: (Bool) -> Void - public init(isDisplaying: Bool, isCentered: Bool, hasInputHeight: Bool, dismiss: @escaping (Bool) -> Void) { + public init(isDisplaying: Bool, isCentered: Bool, hasInputHeight: Bool, regularMetricsSize: CGSize?, dismiss: @escaping (Bool) -> Void) { self.isDisplaying = isDisplaying self.isCentered = isCentered self.hasInputHeight = hasInputHeight + self.regularMetricsSize = regularMetricsSize self.dismiss = dismiss } @@ -28,6 +30,9 @@ public final class SheetComponentEnvironment: Equatable { if lhs.hasInputHeight != rhs.hasInputHeight { return false } + if lhs.regularMetricsSize != rhs.regularMetricsSize { + return false + } return true } } @@ -49,7 +54,11 @@ public final class SheetComponent: Component { public let backgroundColor: BackgroundColor public let animateOut: ActionSlot> - public init(content: AnyComponent, backgroundColor: BackgroundColor, animateOut: ActionSlot>) { + public init( + content: AnyComponent, + backgroundColor: BackgroundColor, + animateOut: ActionSlot> + ) { self.content = content self.backgroundColor = backgroundColor self.animateOut = animateOut @@ -65,7 +74,6 @@ public final class SheetComponent: Component { if lhs.animateOut != rhs.animateOut { return false } - return true } @@ -265,12 +273,15 @@ public final class SheetComponent: Component { transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil) - let containerSize: CGSize + var containerSize: CGSize if sheetEnvironment.isCentered { let verticalInset: CGFloat = 44.0 let maxSide = max(availableSize.width, availableSize.height) let minSide = min(availableSize.width, availableSize.height) containerSize = CGSize(width: min(availableSize.width - 20.0, floor(maxSide / 2.0)), height: min(availableSize.height, minSide) - verticalInset * 2.0) + if let regularMetricsSize = sheetEnvironment.regularMetricsSize { + containerSize = regularMetricsSize + } } else { containerSize = CGSize(width: availableSize.width, height: .greatestFiniteMagnitude) } diff --git a/submodules/DrawingUI/Sources/ColorPickerScreen.swift b/submodules/DrawingUI/Sources/ColorPickerScreen.swift index 0314c8ac07..e22687835a 100644 --- a/submodules/DrawingUI/Sources/ColorPickerScreen.swift +++ b/submodules/DrawingUI/Sources/ColorPickerScreen.swift @@ -40,13 +40,15 @@ private struct ColorSelectionImage: Equatable { let topRightRadius: CGFloat let bottomLeftRadius: CGFloat let bottomRightRadius: CGFloat + let isLight: Bool - init(size: CGSize, topLeftRadius: CGFloat, topRightRadius: CGFloat, bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat) { + init(size: CGSize, topLeftRadius: CGFloat, topRightRadius: CGFloat, bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat, isLight: Bool) { self.size = size self.topLeftRadius = topLeftRadius self.topRightRadius = topRightRadius self.bottomLeftRadius = bottomLeftRadius self.bottomRightRadius = bottomRightRadius + self.isLight = isLight } public static func ==(lhs: ColorSelectionImage, rhs: ColorSelectionImage) -> Bool { @@ -65,18 +67,21 @@ private struct ColorSelectionImage: Equatable { if lhs.bottomRightRadius != rhs.bottomRightRadius { return false } + if lhs.isLight != rhs.isLight { + return false + } return true } mutating func getImage() -> UIImage { if self._image == nil { - self._image = generateColorSelectionImage(size: self.size, topLeftRadius: self.topLeftRadius, topRightRadius: self.topRightRadius, bottomLeftRadius: self.bottomLeftRadius, bottomRightRadius: self.bottomRightRadius) + self._image = generateColorSelectionImage(size: self.size, topLeftRadius: self.topLeftRadius, topRightRadius: self.topRightRadius, bottomLeftRadius: self.bottomLeftRadius, bottomRightRadius: self.bottomRightRadius, isLight: self.isLight) } return self._image! } } -private func generateColorSelectionImage(size: CGSize, topLeftRadius: CGFloat, topRightRadius: CGFloat, bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat) -> UIImage? { +private func generateColorSelectionImage(size: CGSize, topLeftRadius: CGFloat, topRightRadius: CGFloat, bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat, isLight: Bool) -> UIImage? { let margin: CGFloat = 10.0 let realSize = size @@ -88,7 +93,7 @@ private func generateColorSelectionImage(size: CGSize, topLeftRadius: CGFloat, t context.setShadow(offset: CGSize(), blur: 9.0, color: UIColor(rgb: 0x000000, alpha: 0.15).cgColor) context.setLineWidth(3.0 - UIScreenPixel) - context.setStrokeColor(UIColor(rgb: 0x1a1a1c).cgColor) + context.setStrokeColor(UIColor(rgb: isLight ? 0xffffff : 0x1a1a1c).cgColor) context.strokePath() }) return image @@ -686,7 +691,10 @@ final class ColorGridComponent: Component { } else if selectedColorIndex == palleteColors.count - 1 { bottomRightRadius = largeCornerRadius } - var selectionKnobImage = ColorSelectionImage(size: CGSize(width: squareSize, height: squareSize), topLeftRadius: topLeftRadius, topRightRadius: topRightRadius, bottomLeftRadius: bottomLeftRadius, bottomRightRadius: bottomRightRadius) + + let isLight = (selectedColor?.toUIColor().lightness ?? 1.0) < 0.5 ? true : false + + var selectionKnobImage = ColorSelectionImage(size: CGSize(width: squareSize, height: squareSize), topLeftRadius: topLeftRadius, topRightRadius: topRightRadius, bottomLeftRadius: bottomLeftRadius, bottomRightRadius: bottomRightRadius, isLight: isLight) if selectionKnobImage != self.selectionKnobImage { self.selectionKnob.image = selectionKnobImage.getImage() self.selectionKnobImage = selectionKnobImage @@ -2425,6 +2433,7 @@ private final class ColorPickerSheetComponent: CombinedComponent { isDisplaying: environment.value.isVisible, isCentered: environment.metrics.widthClass == .regular, hasInputHeight: !environment.inputHeight.isZero, + regularMetricsSize: CGSize(width: 430.0, height: 900.0), dismiss: { animated in if animated { animateOut.invoke(Action { _ in diff --git a/submodules/DrawingUI/Sources/DrawingMetalView.swift b/submodules/DrawingUI/Sources/DrawingMetalView.swift index cbbe56ea13..e386379f03 100644 --- a/submodules/DrawingUI/Sources/DrawingMetalView.swift +++ b/submodules/DrawingUI/Sources/DrawingMetalView.swift @@ -52,6 +52,7 @@ final class DrawingMetalView: MTKView { self.isPaused = true self.preferredFramesPerSecond = 60 self.presentsWithTransaction = true + self.clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0) self.setup() } @@ -179,9 +180,23 @@ final class DrawingMetalView: MTKView { commandBuffer?.commit() commandBuffer?.waitUntilScheduled() self.currentDrawable?.present() -// if let drawable = self.currentDrawable { -// commandBuffer?.present(drawable) -// } + } + + func reset() { + let renderPassDescriptor = MTLRenderPassDescriptor() + let attachment = renderPassDescriptor.colorAttachments[0] + attachment?.clearColor = clearColor + attachment?.texture = self.currentDrawable?.texture + attachment?.loadAction = .clear + attachment?.storeAction = .store + + let commandBuffer = self.commandQueue.makeCommandBuffer() + let commandEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor) + + commandEncoder?.endEncoding() + commandBuffer?.commit() + commandBuffer?.waitUntilScheduled() + self.currentDrawable?.present() } func clear() { @@ -191,6 +206,7 @@ final class DrawingMetalView: MTKView { drawable.updateBuffer(with: self.size) drawable.clear() + self.reset() } enum BrushType { diff --git a/submodules/DrawingUI/Sources/DrawingScreen.swift b/submodules/DrawingUI/Sources/DrawingScreen.swift index 6b7b433c51..f8a41d66f0 100644 --- a/submodules/DrawingUI/Sources/DrawingScreen.swift +++ b/submodules/DrawingUI/Sources/DrawingScreen.swift @@ -482,6 +482,9 @@ private final class DrawingScreenComponent: CombinedComponent { let updateEntitiesPlayback: ActionSlot let previewBrushSize: ActionSlot let dismissEyedropper: ActionSlot + let requestPresentColorPicker: ActionSlot + let toggleWithEraser: ActionSlot + let toggleWithPreviousTool: ActionSlot let apply: ActionSlot let dismiss: ActionSlot @@ -506,6 +509,9 @@ private final class DrawingScreenComponent: CombinedComponent { updateEntitiesPlayback: ActionSlot, previewBrushSize: ActionSlot, dismissEyedropper: ActionSlot, + requestPresentColorPicker: ActionSlot, + toggleWithEraser: ActionSlot, + toggleWithPreviousTool: ActionSlot, apply: ActionSlot, dismiss: ActionSlot, presentColorPicker: @escaping (DrawingColor) -> Void, @@ -528,6 +534,9 @@ private final class DrawingScreenComponent: CombinedComponent { self.updateEntitiesPlayback = updateEntitiesPlayback self.previewBrushSize = previewBrushSize self.dismissEyedropper = dismissEyedropper + self.requestPresentColorPicker = requestPresentColorPicker + self.toggleWithEraser = toggleWithEraser + self.toggleWithPreviousTool = toggleWithPreviousTool self.apply = apply self.dismiss = dismiss self.presentColorPicker = presentColorPicker @@ -599,6 +608,8 @@ private final class DrawingScreenComponent: CombinedComponent { private let deselectEntity: ActionSlot private let updateEntitiesPlayback: ActionSlot private let dismissEyedropper: ActionSlot + private let toggleWithEraser: ActionSlot + private let toggleWithPreviousTool: ActionSlot private let present: (ViewController) -> Void var currentMode: Mode @@ -610,14 +621,16 @@ private final class DrawingScreenComponent: CombinedComponent { var lastSize: CGFloat = 0.5 private let stickerPickerInputData = Promise() - - init(context: AccountContext, updateToolState: ActionSlot, insertEntity: ActionSlot, deselectEntity: ActionSlot, updateEntitiesPlayback: ActionSlot, dismissEyedropper: ActionSlot, present: @escaping (ViewController) -> Void) { + + init(context: AccountContext, updateToolState: ActionSlot, insertEntity: ActionSlot, deselectEntity: ActionSlot, updateEntitiesPlayback: ActionSlot, dismissEyedropper: ActionSlot, toggleWithEraser: ActionSlot, toggleWithPreviousTool: ActionSlot, present: @escaping (ViewController) -> Void) { self.context = context self.updateToolState = updateToolState self.insertEntity = insertEntity self.deselectEntity = deselectEntity self.updateEntitiesPlayback = updateEntitiesPlayback self.dismissEyedropper = dismissEyedropper + self.toggleWithEraser = toggleWithEraser + self.toggleWithPreviousTool = toggleWithPreviousTool self.present = present self.currentMode = .drawing @@ -679,10 +692,26 @@ private final class DrawingScreenComponent: CombinedComponent { stickerPickerInputData.set(signal) }) - + super.init() self.loadToolState() + + self.toggleWithEraser.connect { [weak self] _ in + if let strongSelf = self { + if strongSelf.drawingState.selectedTool == .eraser { + strongSelf.updateSelectedTool(strongSelf.nextToEraserTool) + } else { + strongSelf.updateSelectedTool(.eraser) + } + } + } + + self.toggleWithPreviousTool.connect { [weak self] _ in + if let strongSelf = self { + strongSelf.updateSelectedTool(strongSelf.previousTool) + } + } } func loadToolState() { @@ -726,12 +755,25 @@ private final class DrawingScreenComponent: CombinedComponent { self.updated(transition: animated ? .easeInOut(duration: 0.2) : .immediate) } + var previousTool: DrawingToolState.Key = .eraser + var nextToEraserTool: DrawingToolState.Key = .pen + func updateSelectedTool(_ tool: DrawingToolState.Key, update: Bool = true) { if self.selectedEntity != nil { self.skipSelectedEntityUpdate = true self.updateCurrentMode(.drawing, update: false) self.skipSelectedEntityUpdate = false } + + if tool != self.drawingState.selectedTool { + if self.drawingState.selectedTool == .eraser { + self.nextToEraserTool = tool + } else if tool == .eraser { + self.nextToEraserTool = self.drawingState.selectedTool + } + self.previousTool = self.drawingState.selectedTool + } + self.drawingState = self.drawingState.withUpdatedSelectedTool(tool) self.currentColor = self.drawingState.currentToolState.color ?? self.currentColor self.updateToolState.invoke(self.drawingState.currentToolState) @@ -893,7 +935,7 @@ private final class DrawingScreenComponent: CombinedComponent { } func makeState() -> State { - return State(context: self.context, updateToolState: self.updateToolState, insertEntity: self.insertEntity, deselectEntity: self.deselectEntity, updateEntitiesPlayback: self.updateEntitiesPlayback, dismissEyedropper: self.dismissEyedropper, present: self.present) + return State(context: self.context, updateToolState: self.updateToolState, insertEntity: self.insertEntity, deselectEntity: self.deselectEntity, updateEntitiesPlayback: self.updateEntitiesPlayback, dismissEyedropper: self.dismissEyedropper, toggleWithEraser: self.toggleWithEraser, toggleWithPreviousTool: self.toggleWithPreviousTool, present: self.present) } static var body: Body { @@ -953,11 +995,20 @@ private final class DrawingScreenComponent: CombinedComponent { let controller = environment.controller let strings = environment.strings - + let previewBrushSize = component.previewBrushSize let performAction = component.performAction let dismissEyedropper = component.dismissEyedropper + let apply = component.apply + let dismiss = component.dismiss + + let presentColorPicker = component.presentColorPicker + let presentFastColorPicker = component.presentFastColorPicker + let updateFastColorPickerPan = component.updateFastColorPickerPan + let dismissFastColorPicker = component.dismissFastColorPicker + let presentFontPicker = component.presentFontPicker + component.updateState.connect { [weak state] updatedState in state?.updateDrawingState(updatedState) } @@ -975,19 +1026,24 @@ private final class DrawingScreenComponent: CombinedComponent { component.updateSelectedEntity.connect { [weak state] entity in state?.updateSelectedEntity(entity) } - - let apply = component.apply - let dismiss = component.dismiss - - let presentColorPicker = component.presentColorPicker - let presentFastColorPicker = component.presentFastColorPicker - let updateFastColorPickerPan = component.updateFastColorPickerPan - let dismissFastColorPicker = component.dismissFastColorPicker - let presentFontPicker = component.presentFontPicker + component.requestPresentColorPicker.connect { [weak state] _ in + if let state = state { + presentColorPicker(state.currentColor) + } + } let topInset = environment.safeInsets.top + 31.0 let bottomInset: CGFloat = environment.inputHeight > 0.0 ? environment.inputHeight : 145.0 + var leftEdge: CGFloat = environment.safeInsets.left + var rightEdge: CGFloat = context.availableSize.width - environment.safeInsets.right + var availableWidth = context.availableSize.width + if case .regular = environment.metrics.widthClass { + availableWidth = 430.0 + leftEdge = floorToScreenPixels((context.availableSize.width - availableWidth) / 2.0) + rightEdge = floorToScreenPixels((context.availableSize.width - availableWidth) / 2.0) + availableWidth + } + let topGradient = topGradient.update( component: BlurredGradientComponent( position: .top, @@ -1070,7 +1126,7 @@ private final class DrawingScreenComponent: CombinedComponent { }, toggleKeyboard: nil ), - availableSize: CGSize(width: context.availableSize.width - 84.0, height: 44.0), + availableSize: CGSize(width: availableWidth - 84.0, height: 44.0), transition: context.transition ) context.add(textSettings @@ -1091,8 +1147,8 @@ private final class DrawingScreenComponent: CombinedComponent { } - let rightButtonPosition = context.availableSize.width - environment.safeInsets.right - 24.0 - var offsetX: CGFloat = environment.safeInsets.left + 24.0 + let rightButtonPosition = rightEdge - 24.0 + var offsetX: CGFloat = leftEdge + 24.0 let delta: CGFloat = (rightButtonPosition - offsetX) / 7.0 let applySwatchColor: (DrawingColor) -> Void = { [weak state] color in @@ -1351,7 +1407,7 @@ private final class DrawingScreenComponent: CombinedComponent { previewBrushSize.invoke(nil) } ), - availableSize: CGSize(width: context.availableSize.width - environment.safeInsets.left - environment.safeInsets.right, height: 120.0), + availableSize: CGSize(width: availableWidth - environment.safeInsets.left - environment.safeInsets.right, height: 120.0), transition: context.transition ) context.add(tools @@ -1684,7 +1740,7 @@ private final class DrawingScreenComponent: CombinedComponent { transition: context.transition ) context.add(colorButton - .position(CGPoint(x: environment.safeInsets.left + colorButton.size.width / 2.0 + 2.0, y: context.availableSize.height - environment.safeInsets.bottom - colorButton.size.height / 2.0 - 89.0)) + .position(CGPoint(x: leftEdge + colorButton.size.width / 2.0 + 2.0, y: context.availableSize.height - environment.safeInsets.bottom - colorButton.size.height / 2.0 - 89.0)) .appear(.default(scale: true)) .disappear(.default(scale: true)) ) @@ -1732,7 +1788,7 @@ private final class DrawingScreenComponent: CombinedComponent { transition: .immediate ) context.add(addButton - .position(CGPoint(x: context.availableSize.width - environment.safeInsets.right - addButton.size.width / 2.0 - 2.0, y: context.availableSize.height - environment.safeInsets.bottom - addButton.size.height / 2.0 - 89.0)) + .position(CGPoint(x: rightEdge - addButton.size.width / 2.0 - 2.0, y: context.availableSize.height - environment.safeInsets.bottom - addButton.size.height / 2.0 - 89.0)) .appear(.default(scale: true)) .disappear(.default(scale: true)) ) @@ -1821,7 +1877,7 @@ private final class DrawingScreenComponent: CombinedComponent { previewBrushSize.invoke(nil) } ), - availableSize: CGSize(width: context.availableSize.width - 57.0 - modeRightInset, height: context.availableSize.height), + availableSize: CGSize(width: availableWidth - 57.0 - modeRightInset, height: context.availableSize.height), transition: context.transition ) context.add(modeAndSize @@ -1880,6 +1936,11 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { private let updateEntitiesPlayback: ActionSlot private let previewBrushSize: ActionSlot private let dismissEyedropper: ActionSlot + + private let requestPresentColorPicker: ActionSlot + private let toggleWithEraser: ActionSlot + private let toggleWithPreviousTool: ActionSlot + private let apply: ActionSlot private let dismiss: ActionSlot @@ -1912,6 +1973,25 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { strongSelf.updateState.invoke(state) } } + self._drawingView?.requestedColorPicker = { [weak self] in + if let strongSelf = self { + if let _ = strongSelf.colorPickerScreen { + strongSelf.dismissColorPicker() + } else { + strongSelf.requestPresentColorPicker.invoke(Void()) + } + } + } + self._drawingView?.requestedEraserToggle = { [weak self] in + if let strongSelf = self { + strongSelf.toggleWithEraser.invoke(Void()) + } + } + self._drawingView?.requestedToolsToggle = { [weak self] in + if let strongSelf = self { + strongSelf.toggleWithPreviousTool.invoke(Void()) + } + } self.performAction.connect { [weak self] action in if let strongSelf = self { if action == .clear { @@ -2121,6 +2201,9 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { self.updateEntitiesPlayback = ActionSlot() self.previewBrushSize = ActionSlot() self.dismissEyedropper = ActionSlot() + self.requestPresentColorPicker = ActionSlot() + self.toggleWithEraser = ActionSlot() + self.toggleWithPreviousTool = ActionSlot() self.apply = ActionSlot() self.dismiss = ActionSlot() @@ -2234,6 +2317,7 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { } } + private weak var colorPickerScreen: ColorPickerScreen? func presentColorPicker(initialColor: DrawingColor, dismissed: @escaping () -> Void = {}) { self.dismissCurrentEyedropper() self.dismissFontPicker() @@ -2250,6 +2334,14 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { dismissed() }) controller.present(colorController, in: .window(.root)) + self.colorPickerScreen = colorController + } + + func dismissColorPicker() { + if let colorPickerScreen = self.colorPickerScreen { + self.colorPickerScreen = nil + colorPickerScreen.dismiss() + } } private var fastColorPickerView: ColorSpectrumPickerView? @@ -2525,6 +2617,9 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { updateEntitiesPlayback: self.updateEntitiesPlayback, previewBrushSize: self.previewBrushSize, dismissEyedropper: self.dismissEyedropper, + requestPresentColorPicker: self.requestPresentColorPicker, + toggleWithEraser: self.toggleWithEraser, + toggleWithPreviousTool: self.toggleWithPreviousTool, apply: self.apply, dismiss: self.dismiss, presentColorPicker: { [weak self] initialColor in @@ -2881,10 +2976,10 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController { (self.displayNode as! Node).containerLayoutUpdated(layout: layout, orientation: orientation, transition: Transition(transition)) } - public func adapterContainerLayoutUpdatedSize(_ size: CGSize, intrinsicInsets: UIEdgeInsets, safeInsets: UIEdgeInsets, statusBarHeight: CGFloat, inputHeight: CGFloat, orientation: UIInterfaceOrientation, animated: Bool) { + public func adapterContainerLayoutUpdatedSize(_ size: CGSize, intrinsicInsets: UIEdgeInsets, safeInsets: UIEdgeInsets, statusBarHeight: CGFloat, inputHeight: CGFloat, orientation: UIInterfaceOrientation, isRegular: Bool, animated: Bool) { let layout = ContainerViewLayout( size: size, - metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), + metrics: LayoutMetrics(widthClass: isRegular ? .regular : .compact, heightClass: isRegular ? .regular : .compact), deviceMetrics: DeviceMetrics(screenSize: size, scale: UIScreen.main.scale, statusBarHeight: statusBarHeight, onScreenNavigationHeight: nil), intrinsicInsets: intrinsicInsets, safeInsets: safeInsets, diff --git a/submodules/DrawingUI/Sources/DrawingTextEntity.swift b/submodules/DrawingUI/Sources/DrawingTextEntity.swift index ab104ca149..baaddd7c01 100644 --- a/submodules/DrawingUI/Sources/DrawingTextEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingTextEntity.swift @@ -616,7 +616,7 @@ final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate { case .semi: self.textView.textColor = color self.textView.strokeColor = nil - self.textView.frameColor = UIColor(rgb: 0xffffff, alpha: 0.75) + self.textView.frameColor = color.lightness > 0.7 ? UIColor(rgb: 0x000000, alpha: 0.75) : UIColor(rgb: 0xffffff, alpha: 0.75) case .stroke: self.textView.textColor = color.lightness > 0.99 ? UIColor.black : UIColor.white self.textView.strokeColor = color diff --git a/submodules/DrawingUI/Sources/DrawingView.swift b/submodules/DrawingUI/Sources/DrawingView.swift index 203b90aebb..69f0f6893d 100644 --- a/submodules/DrawingUI/Sources/DrawingView.swift +++ b/submodules/DrawingUI/Sources/DrawingView.swift @@ -35,7 +35,7 @@ private enum DrawingOperation { case removeEntity(DrawingEntity) } -public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDrawingView { +public final class DrawingView: UIView, UIGestureRecognizerDelegate, UIPencilInteractionDelegate, TGPhotoDrawingView { public var zoomOut: () -> Void = {} struct NavigationState { @@ -71,6 +71,10 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw var shouldBegin: (CGPoint) -> Bool = { _ in return true } var getFullImage: () -> UIImage? = { return nil } + var requestedColorPicker: () -> Void = {} + var requestedEraserToggle: () -> Void = {} + var requestedToolsToggle: () -> Void = {} + private var undoStack: [DrawingOperation] = [] private var redoStack: [DrawingOperation] = [] fileprivate var uncommitedElement: DrawingElement? @@ -81,9 +85,7 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw private var currentDrawingViewContainer: UIImageView private var currentDrawingRenderView: DrawingRenderView? private var currentDrawingLayer: DrawingRenderLayer? - - private var pannedSelectionView: UIView - + private var metalView: DrawingMetalView? private let brushSizePreviewLayer: SimpleShapeLayer @@ -131,6 +133,8 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw private var previousPointTimestamp: Double? + private let pencilInteraction: UIInteraction? + init(size: CGSize) { self.imageSize = size self.screenSize = size @@ -149,12 +153,6 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw self.currentDrawingViewContainer.backgroundColor = .clear self.currentDrawingViewContainer.isUserInteractionEnabled = false - self.pannedSelectionView = UIView() - self.pannedSelectionView.frame = CGRect(origin: .zero, size: size) - self.pannedSelectionView.contentScaleFactor = 1.0 - self.pannedSelectionView.backgroundColor = .clear - self.pannedSelectionView.isUserInteractionEnabled = false - self.brushSizePreviewLayer = SimpleShapeLayer() self.brushSizePreviewLayer.bounds = CGRect(origin: .zero, size: CGSize(width: 100.0, height: 100.0)) self.brushSizePreviewLayer.strokeColor = UIColor(rgb: 0x919191).cgColor @@ -166,12 +164,24 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw self.brushSizePreviewLayer.shadowOffset = CGSize(width: 0.0, height: 3.0) self.brushSizePreviewLayer.shadowRadius = 20.0 + if #available(iOS 12.1, *) { + let pencilInteraction = UIPencilInteraction() + self.pencilInteraction = pencilInteraction + } else { + self.pencilInteraction = nil + } + super.init(frame: CGRect(origin: .zero, size: size)) Queue.mainQueue().async { self.loadTemplates() } + if #available(iOS 12.1, *), let pencilInteraction = self.pencilInteraction as? UIPencilInteraction { + pencilInteraction.delegate = self + self.addInteraction(pencilInteraction) + } + self.backgroundColor = .clear self.contentScaleFactor = 1.0 self.isExclusiveTouch = true @@ -415,6 +425,20 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } + + @available(iOS 12.1, *) + public func pencilInteractionDidTap(_ interaction: UIPencilInteraction) { + switch UIPencilInteraction.preferredTapAction { + case .switchEraser: + self.requestedEraserToggle() + case .showColorPalette: + self.requestedColorPicker() + case .switchPrevious: + self.requestedToolsToggle() + default: + break + } + } private var longPressTimer: SwiftSignalKit.Timer? private var fillCircleLayer: CALayer? diff --git a/submodules/DrawingUI/Sources/StickerPickerScreen.swift b/submodules/DrawingUI/Sources/StickerPickerScreen.swift index f9b97ef85f..74cee9670c 100644 --- a/submodules/DrawingUI/Sources/StickerPickerScreen.swift +++ b/submodules/DrawingUI/Sources/StickerPickerScreen.swift @@ -659,6 +659,7 @@ class StickerPickerScreen: ViewController { let isLandscape = layout.orientation == .landscape let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset let topInset: CGFloat + var bottomInset = layout.intrinsicInsets.bottom if let (panInitialTopInset, panOffset, _) = self.panGestureArguments { if effectiveExpanded { topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset)) @@ -672,7 +673,7 @@ class StickerPickerScreen: ViewController { let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / self.defaultTopInset) self.controller?.updateModalStyleOverlayTransitionFactor(modalProgress, transition: transition.containedViewLayoutTransition) - + let clipFrame: CGRect let contentFrame: CGRect if layout.metrics.widthClass == .compact { @@ -719,9 +720,11 @@ class StickerPickerScreen: ViewController { let maxSide = max(layout.size.width, layout.size.height) let minSide = min(layout.size.width, layout.size.height) - let containerSize = CGSize(width: min(layout.size.width - 20.0, floor(maxSide / 2.0)), height: min(layout.size.height, minSide) - verticalInset * 2.0) + let containerSize = CGSize(width: floorToScreenPixels(min(layout.size.width - 20.0, floor(maxSide / 2.0)) * 0.66), height: floorToScreenPixels((min(layout.size.height, minSide) - verticalInset * 2.0) * 0.66)) clipFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - containerSize.width) / 2.0), y: floor((layout.size.height - containerSize.height) / 2.0)), size: containerSize) contentFrame = clipFrame + + bottomInset = 0.0 } transition.setFrame(view: self.containerView, frame: clipFrame) @@ -741,7 +744,7 @@ class StickerPickerScreen: ViewController { theme: self.theme, strings: self.presentationData.strings, deviceMetrics: layout.deviceMetrics, - bottomInset: layout.intrinsicInsets.bottom, + bottomInset: bottomInset, content: content, backgroundColor: self.theme.list.itemBlocksBackgroundColor, separatorColor: self.theme.list.blocksBackgroundColor diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoPaintStickersContext.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoPaintStickersContext.h index 0f2952b6ca..17e3dbad06 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoPaintStickersContext.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoPaintStickersContext.h @@ -88,6 +88,7 @@ statusBarHeight:(CGFloat)statusBarHeight inputHeight:(CGFloat)inputHeight orientation:(UIInterfaceOrientation)orientation + isRegular:(bool)isRegular animated:(BOOL)animated; @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoDrawingController.m b/submodules/LegacyComponents/Sources/TGPhotoDrawingController.m index 6fc399a37c..7cc71c0a59 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoDrawingController.m +++ b/submodules/LegacyComponents/Sources/TGPhotoDrawingController.m @@ -796,6 +796,7 @@ const CGSize TGPhotoPaintingMaxSize = { 1920.0f, 1920.0f }; statusBarHeight:[_context statusBarFrame].size.height inputHeight:_keyboardHeight orientation:self.effectiveOrientation + isRegular:[UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad animated:animated]; } diff --git a/submodules/PaymentMethodUI/Sources/AddPaymentMethodSheetScreen.swift b/submodules/PaymentMethodUI/Sources/AddPaymentMethodSheetScreen.swift index 27c1013e2d..60e40d690f 100644 --- a/submodules/PaymentMethodUI/Sources/AddPaymentMethodSheetScreen.swift +++ b/submodules/PaymentMethodUI/Sources/AddPaymentMethodSheetScreen.swift @@ -205,6 +205,7 @@ private final class AddPaymentMethodSheetComponent: CombinedComponent { isDisplaying: environment.value.isVisible, isCentered: false, hasInputHeight: !environment.inputHeight.isZero, + regularMetricsSize: nil, dismiss: { animated in if animated { animateOut.invoke(Action { _ in diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index c1b2de1310..b7aa9b6186 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -1126,6 +1126,7 @@ private final class DemoSheetComponent: CombinedComponent { isDisplaying: environment.value.isVisible, isCentered: environment.metrics.widthClass == .regular, hasInputHeight: !environment.inputHeight.isZero, + regularMetricsSize: nil, dismiss: { animated in if animated { animateOut.invoke(Action { _ in diff --git a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift index 5654bdd90b..5e9910a260 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift @@ -1012,6 +1012,7 @@ private final class LimitSheetComponent: CombinedComponent { isDisplaying: environment.value.isVisible, isCentered: environment.metrics.widthClass == .regular, hasInputHeight: !environment.inputHeight.isZero, + regularMetricsSize: nil, dismiss: { animated in if animated { animateOut.invoke(Action { _ in