Merge commit 'c98abdd0251e0a5ec1f8494e6f3c876b78dd18b2'

This commit is contained in:
Ali 2022-12-25 19:57:46 +04:00
commit d826bd06c0
12 changed files with 212 additions and 49 deletions

View File

@ -9,12 +9,14 @@ public final class SheetComponentEnvironment: Equatable {
public let isDisplaying: Bool public let isDisplaying: Bool
public let isCentered: Bool public let isCentered: Bool
public let hasInputHeight: Bool public let hasInputHeight: Bool
public let regularMetricsSize: CGSize?
public let dismiss: (Bool) -> Void 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.isDisplaying = isDisplaying
self.isCentered = isCentered self.isCentered = isCentered
self.hasInputHeight = hasInputHeight self.hasInputHeight = hasInputHeight
self.regularMetricsSize = regularMetricsSize
self.dismiss = dismiss self.dismiss = dismiss
} }
@ -28,6 +30,9 @@ public final class SheetComponentEnvironment: Equatable {
if lhs.hasInputHeight != rhs.hasInputHeight { if lhs.hasInputHeight != rhs.hasInputHeight {
return false return false
} }
if lhs.regularMetricsSize != rhs.regularMetricsSize {
return false
}
return true return true
} }
} }
@ -49,7 +54,11 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
public let backgroundColor: BackgroundColor public let backgroundColor: BackgroundColor
public let animateOut: ActionSlot<Action<()>> public let animateOut: ActionSlot<Action<()>>
public init(content: AnyComponent<ChildEnvironmentType>, backgroundColor: BackgroundColor, animateOut: ActionSlot<Action<()>>) { public init(
content: AnyComponent<ChildEnvironmentType>,
backgroundColor: BackgroundColor,
animateOut: ActionSlot<Action<()>>
) {
self.content = content self.content = content
self.backgroundColor = backgroundColor self.backgroundColor = backgroundColor
self.animateOut = animateOut self.animateOut = animateOut
@ -65,7 +74,6 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
if lhs.animateOut != rhs.animateOut { if lhs.animateOut != rhs.animateOut {
return false return false
} }
return true return true
} }
@ -265,12 +273,15 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil) transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil)
let containerSize: CGSize var containerSize: CGSize
if sheetEnvironment.isCentered { if sheetEnvironment.isCentered {
let verticalInset: CGFloat = 44.0 let verticalInset: CGFloat = 44.0
let maxSide = max(availableSize.width, availableSize.height) let maxSide = max(availableSize.width, availableSize.height)
let minSide = min(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) 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 { } else {
containerSize = CGSize(width: availableSize.width, height: .greatestFiniteMagnitude) containerSize = CGSize(width: availableSize.width, height: .greatestFiniteMagnitude)
} }

View File

@ -40,13 +40,15 @@ private struct ColorSelectionImage: Equatable {
let topRightRadius: CGFloat let topRightRadius: CGFloat
let bottomLeftRadius: CGFloat let bottomLeftRadius: CGFloat
let bottomRightRadius: 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.size = size
self.topLeftRadius = topLeftRadius self.topLeftRadius = topLeftRadius
self.topRightRadius = topRightRadius self.topRightRadius = topRightRadius
self.bottomLeftRadius = bottomLeftRadius self.bottomLeftRadius = bottomLeftRadius
self.bottomRightRadius = bottomRightRadius self.bottomRightRadius = bottomRightRadius
self.isLight = isLight
} }
public static func ==(lhs: ColorSelectionImage, rhs: ColorSelectionImage) -> Bool { public static func ==(lhs: ColorSelectionImage, rhs: ColorSelectionImage) -> Bool {
@ -65,18 +67,21 @@ private struct ColorSelectionImage: Equatable {
if lhs.bottomRightRadius != rhs.bottomRightRadius { if lhs.bottomRightRadius != rhs.bottomRightRadius {
return false return false
} }
if lhs.isLight != rhs.isLight {
return false
}
return true return true
} }
mutating func getImage() -> UIImage { mutating func getImage() -> UIImage {
if self._image == nil { 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! 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 margin: CGFloat = 10.0
let realSize = size 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.setShadow(offset: CGSize(), blur: 9.0, color: UIColor(rgb: 0x000000, alpha: 0.15).cgColor)
context.setLineWidth(3.0 - UIScreenPixel) context.setLineWidth(3.0 - UIScreenPixel)
context.setStrokeColor(UIColor(rgb: 0x1a1a1c).cgColor) context.setStrokeColor(UIColor(rgb: isLight ? 0xffffff : 0x1a1a1c).cgColor)
context.strokePath() context.strokePath()
}) })
return image return image
@ -686,7 +691,10 @@ final class ColorGridComponent: Component {
} else if selectedColorIndex == palleteColors.count - 1 { } else if selectedColorIndex == palleteColors.count - 1 {
bottomRightRadius = largeCornerRadius 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 { if selectionKnobImage != self.selectionKnobImage {
self.selectionKnob.image = selectionKnobImage.getImage() self.selectionKnob.image = selectionKnobImage.getImage()
self.selectionKnobImage = selectionKnobImage self.selectionKnobImage = selectionKnobImage
@ -2425,6 +2433,7 @@ private final class ColorPickerSheetComponent: CombinedComponent {
isDisplaying: environment.value.isVisible, isDisplaying: environment.value.isVisible,
isCentered: environment.metrics.widthClass == .regular, isCentered: environment.metrics.widthClass == .regular,
hasInputHeight: !environment.inputHeight.isZero, hasInputHeight: !environment.inputHeight.isZero,
regularMetricsSize: CGSize(width: 430.0, height: 900.0),
dismiss: { animated in dismiss: { animated in
if animated { if animated {
animateOut.invoke(Action { _ in animateOut.invoke(Action { _ in

View File

@ -52,6 +52,7 @@ final class DrawingMetalView: MTKView {
self.isPaused = true self.isPaused = true
self.preferredFramesPerSecond = 60 self.preferredFramesPerSecond = 60
self.presentsWithTransaction = true self.presentsWithTransaction = true
self.clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0)
self.setup() self.setup()
} }
@ -179,9 +180,23 @@ final class DrawingMetalView: MTKView {
commandBuffer?.commit() commandBuffer?.commit()
commandBuffer?.waitUntilScheduled() commandBuffer?.waitUntilScheduled()
self.currentDrawable?.present() 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() { func clear() {
@ -191,6 +206,7 @@ final class DrawingMetalView: MTKView {
drawable.updateBuffer(with: self.size) drawable.updateBuffer(with: self.size)
drawable.clear() drawable.clear()
self.reset()
} }
enum BrushType { enum BrushType {

View File

@ -482,6 +482,9 @@ private final class DrawingScreenComponent: CombinedComponent {
let updateEntitiesPlayback: ActionSlot<Bool> let updateEntitiesPlayback: ActionSlot<Bool>
let previewBrushSize: ActionSlot<CGFloat?> let previewBrushSize: ActionSlot<CGFloat?>
let dismissEyedropper: ActionSlot<Void> let dismissEyedropper: ActionSlot<Void>
let requestPresentColorPicker: ActionSlot<Void>
let toggleWithEraser: ActionSlot<Void>
let toggleWithPreviousTool: ActionSlot<Void>
let apply: ActionSlot<Void> let apply: ActionSlot<Void>
let dismiss: ActionSlot<Void> let dismiss: ActionSlot<Void>
@ -506,6 +509,9 @@ private final class DrawingScreenComponent: CombinedComponent {
updateEntitiesPlayback: ActionSlot<Bool>, updateEntitiesPlayback: ActionSlot<Bool>,
previewBrushSize: ActionSlot<CGFloat?>, previewBrushSize: ActionSlot<CGFloat?>,
dismissEyedropper: ActionSlot<Void>, dismissEyedropper: ActionSlot<Void>,
requestPresentColorPicker: ActionSlot<Void>,
toggleWithEraser: ActionSlot<Void>,
toggleWithPreviousTool: ActionSlot<Void>,
apply: ActionSlot<Void>, apply: ActionSlot<Void>,
dismiss: ActionSlot<Void>, dismiss: ActionSlot<Void>,
presentColorPicker: @escaping (DrawingColor) -> Void, presentColorPicker: @escaping (DrawingColor) -> Void,
@ -528,6 +534,9 @@ private final class DrawingScreenComponent: CombinedComponent {
self.updateEntitiesPlayback = updateEntitiesPlayback self.updateEntitiesPlayback = updateEntitiesPlayback
self.previewBrushSize = previewBrushSize self.previewBrushSize = previewBrushSize
self.dismissEyedropper = dismissEyedropper self.dismissEyedropper = dismissEyedropper
self.requestPresentColorPicker = requestPresentColorPicker
self.toggleWithEraser = toggleWithEraser
self.toggleWithPreviousTool = toggleWithPreviousTool
self.apply = apply self.apply = apply
self.dismiss = dismiss self.dismiss = dismiss
self.presentColorPicker = presentColorPicker self.presentColorPicker = presentColorPicker
@ -599,6 +608,8 @@ private final class DrawingScreenComponent: CombinedComponent {
private let deselectEntity: ActionSlot<Void> private let deselectEntity: ActionSlot<Void>
private let updateEntitiesPlayback: ActionSlot<Bool> private let updateEntitiesPlayback: ActionSlot<Bool>
private let dismissEyedropper: ActionSlot<Void> private let dismissEyedropper: ActionSlot<Void>
private let toggleWithEraser: ActionSlot<Void>
private let toggleWithPreviousTool: ActionSlot<Void>
private let present: (ViewController) -> Void private let present: (ViewController) -> Void
var currentMode: Mode var currentMode: Mode
@ -610,14 +621,16 @@ private final class DrawingScreenComponent: CombinedComponent {
var lastSize: CGFloat = 0.5 var lastSize: CGFloat = 0.5
private let stickerPickerInputData = Promise<StickerPickerInputData>() private let stickerPickerInputData = Promise<StickerPickerInputData>()
init(context: AccountContext, updateToolState: ActionSlot<DrawingToolState>, insertEntity: ActionSlot<DrawingEntity>, deselectEntity: ActionSlot<Void>, updateEntitiesPlayback: ActionSlot<Bool>, dismissEyedropper: ActionSlot<Void>, present: @escaping (ViewController) -> Void) { init(context: AccountContext, updateToolState: ActionSlot<DrawingToolState>, insertEntity: ActionSlot<DrawingEntity>, deselectEntity: ActionSlot<Void>, updateEntitiesPlayback: ActionSlot<Bool>, dismissEyedropper: ActionSlot<Void>, toggleWithEraser: ActionSlot<Void>, toggleWithPreviousTool: ActionSlot<Void>, present: @escaping (ViewController) -> Void) {
self.context = context self.context = context
self.updateToolState = updateToolState self.updateToolState = updateToolState
self.insertEntity = insertEntity self.insertEntity = insertEntity
self.deselectEntity = deselectEntity self.deselectEntity = deselectEntity
self.updateEntitiesPlayback = updateEntitiesPlayback self.updateEntitiesPlayback = updateEntitiesPlayback
self.dismissEyedropper = dismissEyedropper self.dismissEyedropper = dismissEyedropper
self.toggleWithEraser = toggleWithEraser
self.toggleWithPreviousTool = toggleWithPreviousTool
self.present = present self.present = present
self.currentMode = .drawing self.currentMode = .drawing
@ -679,10 +692,26 @@ private final class DrawingScreenComponent: CombinedComponent {
stickerPickerInputData.set(signal) stickerPickerInputData.set(signal)
}) })
super.init() super.init()
self.loadToolState() 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() { func loadToolState() {
@ -726,12 +755,25 @@ private final class DrawingScreenComponent: CombinedComponent {
self.updated(transition: animated ? .easeInOut(duration: 0.2) : .immediate) 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) { func updateSelectedTool(_ tool: DrawingToolState.Key, update: Bool = true) {
if self.selectedEntity != nil { if self.selectedEntity != nil {
self.skipSelectedEntityUpdate = true self.skipSelectedEntityUpdate = true
self.updateCurrentMode(.drawing, update: false) self.updateCurrentMode(.drawing, update: false)
self.skipSelectedEntityUpdate = 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.drawingState = self.drawingState.withUpdatedSelectedTool(tool)
self.currentColor = self.drawingState.currentToolState.color ?? self.currentColor self.currentColor = self.drawingState.currentToolState.color ?? self.currentColor
self.updateToolState.invoke(self.drawingState.currentToolState) self.updateToolState.invoke(self.drawingState.currentToolState)
@ -893,7 +935,7 @@ private final class DrawingScreenComponent: CombinedComponent {
} }
func makeState() -> State { 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 { static var body: Body {
@ -953,11 +995,20 @@ private final class DrawingScreenComponent: CombinedComponent {
let controller = environment.controller let controller = environment.controller
let strings = environment.strings let strings = environment.strings
let previewBrushSize = component.previewBrushSize let previewBrushSize = component.previewBrushSize
let performAction = component.performAction let performAction = component.performAction
let dismissEyedropper = component.dismissEyedropper 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 component.updateState.connect { [weak state] updatedState in
state?.updateDrawingState(updatedState) state?.updateDrawingState(updatedState)
} }
@ -975,19 +1026,24 @@ private final class DrawingScreenComponent: CombinedComponent {
component.updateSelectedEntity.connect { [weak state] entity in component.updateSelectedEntity.connect { [weak state] entity in
state?.updateSelectedEntity(entity) state?.updateSelectedEntity(entity)
} }
component.requestPresentColorPicker.connect { [weak state] _ in
let apply = component.apply if let state = state {
let dismiss = component.dismiss presentColorPicker(state.currentColor)
}
let presentColorPicker = component.presentColorPicker }
let presentFastColorPicker = component.presentFastColorPicker
let updateFastColorPickerPan = component.updateFastColorPickerPan
let dismissFastColorPicker = component.dismissFastColorPicker
let presentFontPicker = component.presentFontPicker
let topInset = environment.safeInsets.top + 31.0 let topInset = environment.safeInsets.top + 31.0
let bottomInset: CGFloat = environment.inputHeight > 0.0 ? environment.inputHeight : 145.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( let topGradient = topGradient.update(
component: BlurredGradientComponent( component: BlurredGradientComponent(
position: .top, position: .top,
@ -1070,7 +1126,7 @@ private final class DrawingScreenComponent: CombinedComponent {
}, },
toggleKeyboard: nil 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 transition: context.transition
) )
context.add(textSettings context.add(textSettings
@ -1091,8 +1147,8 @@ private final class DrawingScreenComponent: CombinedComponent {
} }
let rightButtonPosition = context.availableSize.width - environment.safeInsets.right - 24.0 let rightButtonPosition = rightEdge - 24.0
var offsetX: CGFloat = environment.safeInsets.left + 24.0 var offsetX: CGFloat = leftEdge + 24.0
let delta: CGFloat = (rightButtonPosition - offsetX) / 7.0 let delta: CGFloat = (rightButtonPosition - offsetX) / 7.0
let applySwatchColor: (DrawingColor) -> Void = { [weak state] color in let applySwatchColor: (DrawingColor) -> Void = { [weak state] color in
@ -1351,7 +1407,7 @@ private final class DrawingScreenComponent: CombinedComponent {
previewBrushSize.invoke(nil) 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 transition: context.transition
) )
context.add(tools context.add(tools
@ -1684,7 +1740,7 @@ private final class DrawingScreenComponent: CombinedComponent {
transition: context.transition transition: context.transition
) )
context.add(colorButton 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)) .appear(.default(scale: true))
.disappear(.default(scale: true)) .disappear(.default(scale: true))
) )
@ -1732,7 +1788,7 @@ private final class DrawingScreenComponent: CombinedComponent {
transition: .immediate transition: .immediate
) )
context.add(addButton 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)) .appear(.default(scale: true))
.disappear(.default(scale: true)) .disappear(.default(scale: true))
) )
@ -1821,7 +1877,7 @@ private final class DrawingScreenComponent: CombinedComponent {
previewBrushSize.invoke(nil) 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 transition: context.transition
) )
context.add(modeAndSize context.add(modeAndSize
@ -1880,6 +1936,11 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
private let updateEntitiesPlayback: ActionSlot<Bool> private let updateEntitiesPlayback: ActionSlot<Bool>
private let previewBrushSize: ActionSlot<CGFloat?> private let previewBrushSize: ActionSlot<CGFloat?>
private let dismissEyedropper: ActionSlot<Void> private let dismissEyedropper: ActionSlot<Void>
private let requestPresentColorPicker: ActionSlot<Void>
private let toggleWithEraser: ActionSlot<Void>
private let toggleWithPreviousTool: ActionSlot<Void>
private let apply: ActionSlot<Void> private let apply: ActionSlot<Void>
private let dismiss: ActionSlot<Void> private let dismiss: ActionSlot<Void>
@ -1912,6 +1973,25 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
strongSelf.updateState.invoke(state) 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 self.performAction.connect { [weak self] action in
if let strongSelf = self { if let strongSelf = self {
if action == .clear { if action == .clear {
@ -2121,6 +2201,9 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
self.updateEntitiesPlayback = ActionSlot<Bool>() self.updateEntitiesPlayback = ActionSlot<Bool>()
self.previewBrushSize = ActionSlot<CGFloat?>() self.previewBrushSize = ActionSlot<CGFloat?>()
self.dismissEyedropper = ActionSlot<Void>() self.dismissEyedropper = ActionSlot<Void>()
self.requestPresentColorPicker = ActionSlot<Void>()
self.toggleWithEraser = ActionSlot<Void>()
self.toggleWithPreviousTool = ActionSlot<Void>()
self.apply = ActionSlot<Void>() self.apply = ActionSlot<Void>()
self.dismiss = ActionSlot<Void>() self.dismiss = ActionSlot<Void>()
@ -2234,6 +2317,7 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
} }
} }
private weak var colorPickerScreen: ColorPickerScreen?
func presentColorPicker(initialColor: DrawingColor, dismissed: @escaping () -> Void = {}) { func presentColorPicker(initialColor: DrawingColor, dismissed: @escaping () -> Void = {}) {
self.dismissCurrentEyedropper() self.dismissCurrentEyedropper()
self.dismissFontPicker() self.dismissFontPicker()
@ -2250,6 +2334,14 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
dismissed() dismissed()
}) })
controller.present(colorController, in: .window(.root)) 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? private var fastColorPickerView: ColorSpectrumPickerView?
@ -2525,6 +2617,9 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
updateEntitiesPlayback: self.updateEntitiesPlayback, updateEntitiesPlayback: self.updateEntitiesPlayback,
previewBrushSize: self.previewBrushSize, previewBrushSize: self.previewBrushSize,
dismissEyedropper: self.dismissEyedropper, dismissEyedropper: self.dismissEyedropper,
requestPresentColorPicker: self.requestPresentColorPicker,
toggleWithEraser: self.toggleWithEraser,
toggleWithPreviousTool: self.toggleWithPreviousTool,
apply: self.apply, apply: self.apply,
dismiss: self.dismiss, dismiss: self.dismiss,
presentColorPicker: { [weak self] initialColor in 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)) (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( let layout = ContainerViewLayout(
size: size, 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), deviceMetrics: DeviceMetrics(screenSize: size, scale: UIScreen.main.scale, statusBarHeight: statusBarHeight, onScreenNavigationHeight: nil),
intrinsicInsets: intrinsicInsets, intrinsicInsets: intrinsicInsets,
safeInsets: safeInsets, safeInsets: safeInsets,

View File

@ -616,7 +616,7 @@ final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate {
case .semi: case .semi:
self.textView.textColor = color self.textView.textColor = color
self.textView.strokeColor = nil 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: case .stroke:
self.textView.textColor = color.lightness > 0.99 ? UIColor.black : UIColor.white self.textView.textColor = color.lightness > 0.99 ? UIColor.black : UIColor.white
self.textView.strokeColor = color self.textView.strokeColor = color

View File

@ -35,7 +35,7 @@ private enum DrawingOperation {
case removeEntity(DrawingEntity) case removeEntity(DrawingEntity)
} }
public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDrawingView { public final class DrawingView: UIView, UIGestureRecognizerDelegate, UIPencilInteractionDelegate, TGPhotoDrawingView {
public var zoomOut: () -> Void = {} public var zoomOut: () -> Void = {}
struct NavigationState { struct NavigationState {
@ -71,6 +71,10 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw
var shouldBegin: (CGPoint) -> Bool = { _ in return true } var shouldBegin: (CGPoint) -> Bool = { _ in return true }
var getFullImage: () -> UIImage? = { return nil } var getFullImage: () -> UIImage? = { return nil }
var requestedColorPicker: () -> Void = {}
var requestedEraserToggle: () -> Void = {}
var requestedToolsToggle: () -> Void = {}
private var undoStack: [DrawingOperation] = [] private var undoStack: [DrawingOperation] = []
private var redoStack: [DrawingOperation] = [] private var redoStack: [DrawingOperation] = []
fileprivate var uncommitedElement: DrawingElement? fileprivate var uncommitedElement: DrawingElement?
@ -81,9 +85,7 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw
private var currentDrawingViewContainer: UIImageView private var currentDrawingViewContainer: UIImageView
private var currentDrawingRenderView: DrawingRenderView? private var currentDrawingRenderView: DrawingRenderView?
private var currentDrawingLayer: DrawingRenderLayer? private var currentDrawingLayer: DrawingRenderLayer?
private var pannedSelectionView: UIView
private var metalView: DrawingMetalView? private var metalView: DrawingMetalView?
private let brushSizePreviewLayer: SimpleShapeLayer private let brushSizePreviewLayer: SimpleShapeLayer
@ -131,6 +133,8 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw
private var previousPointTimestamp: Double? private var previousPointTimestamp: Double?
private let pencilInteraction: UIInteraction?
init(size: CGSize) { init(size: CGSize) {
self.imageSize = size self.imageSize = size
self.screenSize = size self.screenSize = size
@ -149,12 +153,6 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw
self.currentDrawingViewContainer.backgroundColor = .clear self.currentDrawingViewContainer.backgroundColor = .clear
self.currentDrawingViewContainer.isUserInteractionEnabled = false 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 = SimpleShapeLayer()
self.brushSizePreviewLayer.bounds = CGRect(origin: .zero, size: CGSize(width: 100.0, height: 100.0)) self.brushSizePreviewLayer.bounds = CGRect(origin: .zero, size: CGSize(width: 100.0, height: 100.0))
self.brushSizePreviewLayer.strokeColor = UIColor(rgb: 0x919191).cgColor 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.shadowOffset = CGSize(width: 0.0, height: 3.0)
self.brushSizePreviewLayer.shadowRadius = 20.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)) super.init(frame: CGRect(origin: .zero, size: size))
Queue.mainQueue().async { Queue.mainQueue().async {
self.loadTemplates() self.loadTemplates()
} }
if #available(iOS 12.1, *), let pencilInteraction = self.pencilInteraction as? UIPencilInteraction {
pencilInteraction.delegate = self
self.addInteraction(pencilInteraction)
}
self.backgroundColor = .clear self.backgroundColor = .clear
self.contentScaleFactor = 1.0 self.contentScaleFactor = 1.0
self.isExclusiveTouch = true self.isExclusiveTouch = true
@ -415,6 +425,20 @@ public final class DrawingView: UIView, UIGestureRecognizerDelegate, TGPhotoDraw
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true 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 longPressTimer: SwiftSignalKit.Timer?
private var fillCircleLayer: CALayer? private var fillCircleLayer: CALayer?

View File

@ -659,6 +659,7 @@ class StickerPickerScreen: ViewController {
let isLandscape = layout.orientation == .landscape let isLandscape = layout.orientation == .landscape
let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset let edgeTopInset = isLandscape ? 0.0 : self.defaultTopInset
let topInset: CGFloat let topInset: CGFloat
var bottomInset = layout.intrinsicInsets.bottom
if let (panInitialTopInset, panOffset, _) = self.panGestureArguments { if let (panInitialTopInset, panOffset, _) = self.panGestureArguments {
if effectiveExpanded { if effectiveExpanded {
topInset = min(edgeTopInset, panInitialTopInset + max(0.0, panOffset)) 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) let modalProgress = isLandscape ? 0.0 : (1.0 - topInset / self.defaultTopInset)
self.controller?.updateModalStyleOverlayTransitionFactor(modalProgress, transition: transition.containedViewLayoutTransition) self.controller?.updateModalStyleOverlayTransitionFactor(modalProgress, transition: transition.containedViewLayoutTransition)
let clipFrame: CGRect let clipFrame: CGRect
let contentFrame: CGRect let contentFrame: CGRect
if layout.metrics.widthClass == .compact { if layout.metrics.widthClass == .compact {
@ -719,9 +720,11 @@ class StickerPickerScreen: ViewController {
let maxSide = max(layout.size.width, layout.size.height) let maxSide = max(layout.size.width, layout.size.height)
let minSide = min(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) 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 contentFrame = clipFrame
bottomInset = 0.0
} }
transition.setFrame(view: self.containerView, frame: clipFrame) transition.setFrame(view: self.containerView, frame: clipFrame)
@ -741,7 +744,7 @@ class StickerPickerScreen: ViewController {
theme: self.theme, theme: self.theme,
strings: self.presentationData.strings, strings: self.presentationData.strings,
deviceMetrics: layout.deviceMetrics, deviceMetrics: layout.deviceMetrics,
bottomInset: layout.intrinsicInsets.bottom, bottomInset: bottomInset,
content: content, content: content,
backgroundColor: self.theme.list.itemBlocksBackgroundColor, backgroundColor: self.theme.list.itemBlocksBackgroundColor,
separatorColor: self.theme.list.blocksBackgroundColor separatorColor: self.theme.list.blocksBackgroundColor

View File

@ -88,6 +88,7 @@
statusBarHeight:(CGFloat)statusBarHeight statusBarHeight:(CGFloat)statusBarHeight
inputHeight:(CGFloat)inputHeight inputHeight:(CGFloat)inputHeight
orientation:(UIInterfaceOrientation)orientation orientation:(UIInterfaceOrientation)orientation
isRegular:(bool)isRegular
animated:(BOOL)animated; animated:(BOOL)animated;
@end @end

View File

@ -796,6 +796,7 @@ const CGSize TGPhotoPaintingMaxSize = { 1920.0f, 1920.0f };
statusBarHeight:[_context statusBarFrame].size.height statusBarHeight:[_context statusBarFrame].size.height
inputHeight:_keyboardHeight inputHeight:_keyboardHeight
orientation:self.effectiveOrientation orientation:self.effectiveOrientation
isRegular:[UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad
animated:animated]; animated:animated];
} }

View File

@ -205,6 +205,7 @@ private final class AddPaymentMethodSheetComponent: CombinedComponent {
isDisplaying: environment.value.isVisible, isDisplaying: environment.value.isVisible,
isCentered: false, isCentered: false,
hasInputHeight: !environment.inputHeight.isZero, hasInputHeight: !environment.inputHeight.isZero,
regularMetricsSize: nil,
dismiss: { animated in dismiss: { animated in
if animated { if animated {
animateOut.invoke(Action { _ in animateOut.invoke(Action { _ in

View File

@ -1126,6 +1126,7 @@ private final class DemoSheetComponent: CombinedComponent {
isDisplaying: environment.value.isVisible, isDisplaying: environment.value.isVisible,
isCentered: environment.metrics.widthClass == .regular, isCentered: environment.metrics.widthClass == .regular,
hasInputHeight: !environment.inputHeight.isZero, hasInputHeight: !environment.inputHeight.isZero,
regularMetricsSize: nil,
dismiss: { animated in dismiss: { animated in
if animated { if animated {
animateOut.invoke(Action { _ in animateOut.invoke(Action { _ in

View File

@ -1012,6 +1012,7 @@ private final class LimitSheetComponent: CombinedComponent {
isDisplaying: environment.value.isVisible, isDisplaying: environment.value.isVisible,
isCentered: environment.metrics.widthClass == .regular, isCentered: environment.metrics.widthClass == .regular,
hasInputHeight: !environment.inputHeight.isZero, hasInputHeight: !environment.inputHeight.isZero,
regularMetricsSize: nil,
dismiss: { animated in dismiss: { animated in
if animated { if animated {
animateOut.invoke(Action { _ in animateOut.invoke(Action { _ in