diff --git a/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CameraPlaceholder.jpg b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CameraPlaceholder.jpg new file mode 100644 index 0000000000..d7d326fa0e Binary files /dev/null and b/submodules/LegacyComponents/Resources/LegacyComponentsResources.bundle/CameraPlaceholder.jpg differ diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index 7e9deb2fc0..5258fe8e96 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -1102,7 +1102,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus __strong TGCameraController *strongSelf = weakSelf; if (strongSelf == nil) return; - + TGDispatchOnMainThread(^ { strongSelf->_shutterIsBusy = false; @@ -1120,6 +1120,10 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus strongSelf->_camera.disabled = false; } }); + + [[SQueue concurrentDefaultQueue] dispatch:^{ + [TGCameraController generateStartImageWithImage:result]; + }]; }]; } else if (cameraMode == PGCameraModeVideo || cameraMode == PGCameraModeSquareVideo || cameraMode == PGCameraModeSquareSwing) @@ -2246,6 +2250,15 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus _interfaceView.previewViewFrame = toFrame; } ++ (void)generateStartImageWithImage:(UIImage *)frameImage { + CGFloat minSize = MIN(frameImage.size.width, frameImage.size.height); + UIImage *image = TGPhotoEditorCrop(frameImage, nil, UIImageOrientationUp, 0.0f, CGRectMake((frameImage.size.width - minSize) / 2.0f, (frameImage.size.height - minSize) / 2.0f, minSize, minSize), false, CGSizeMake(240.0f, 240.0f), frameImage.size, true); + UIImage *startImage = TGSecretBlurredAttachmentImage(image, image.size, NULL, false, 0); + TGDispatchOnMainThread(^{ + [TGCameraController saveStartImage:startImage]; + }); +} + - (void)beginTransitionOutWithVelocity:(CGFloat)velocity { _dismissing = true; @@ -2269,13 +2282,9 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus __weak TGCameraController *weakSelf = self; [_camera captureNextFrameCompletion:^(UIImage *frameImage) { - CGFloat minSize = MIN(frameImage.size.width, frameImage.size.height); - CGFloat maxSize = MAX(frameImage.size.width, frameImage.size.height); - - UIImage *image = TGPhotoEditorCrop(frameImage, nil, UIImageOrientationUp, 0.0f, CGRectMake((maxSize - minSize) / 2.0f, 0.0f, minSize, minSize), false, CGSizeMake(240.0f, 240.0f), frameImage.size, true); - - UIImage *startImage = TGSecretBlurredAttachmentImage(image, image.size, NULL, false, 0); - [TGCameraController saveStartImage:startImage]; + [[SQueue concurrentDefaultQueue] dispatch:^{ + [TGCameraController generateStartImageWithImage:frameImage]; + }]; }]; if (_standalone) { @@ -3156,7 +3165,7 @@ static UIImage *startImage = nil; + (UIImage *)startImage { if (startImage == nil) - startImage = TGComponentsImageNamed (@"VideoMessagePlaceholder.jpg"); + startImage = TGComponentsImageNamed (@"CameraPlaceholder.jpg"); return startImage; } diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift index 396dfa7ffc..f40dead068 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -184,16 +184,16 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi } switch playbackBaseRate { case .x0_5: - self.rateButton.setContent(.image(optionsRateImage(rate: "0.5x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "0.5X", color: self.theme.rootController.navigationBar.accentTextColor))) case .x1: - self.rateButton.setContent(.image(optionsRateImage(rate: "1x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.controlColor))) self.rateButton.accessibilityLabel = self.strings.VoiceOver_Media_PlaybackRate self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRateNormal self.rateButton.accessibilityHint = self.strings.VoiceOver_Media_PlaybackRateChange case .x1_5: - self.rateButton.setContent(.image(optionsRateImage(rate: "1.5x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "1.5X", color: self.theme.rootController.navigationBar.accentTextColor))) case .x2: - self.rateButton.setContent(.image(optionsRateImage(rate: "2x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.accentTextColor))) self.rateButton.accessibilityLabel = self.strings.VoiceOver_Media_PlaybackRate self.rateButton.accessibilityValue = self.strings.VoiceOver_Media_PlaybackRateFast self.rateButton.accessibilityHint = self.strings.VoiceOver_Media_PlaybackRateChange @@ -372,13 +372,13 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi if let playbackBaseRate = self.playbackBaseRate { switch playbackBaseRate { case .x0_5: - self.rateButton.setContent(.image(optionsRateImage(rate: "0.5x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "0.5X", color: self.theme.rootController.navigationBar.accentTextColor))) case .x1: - self.rateButton.setContent(.image(optionsRateImage(rate: "1x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.controlColor))) case .x1_5: - self.rateButton.setContent(.image(optionsRateImage(rate: "1.5x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "1.5X", color: self.theme.rootController.navigationBar.accentTextColor))) case .x2: - self.rateButton.setContent(.image(optionsRateImage(rate: "2x", isLarge: false, color: self.theme.rootController.navigationBar.controlColor))) + self.rateButton.setContent(.image(optionsRateImage(rate: "2X", color: self.theme.rootController.navigationBar.accentTextColor))) default: break } @@ -486,7 +486,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0)) transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 44.0 - rightInset, y: 0.0), size: CGSize(width: 44.0, height: minHeight))) let rateButtonSize = CGSize(width: 30.0, height: minHeight) - transition.updateFrame(node: self.rateButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 20.0 - closeButtonSize.width - rateButtonSize.width - rightInset, y: -4.0), size: rateButtonSize)) + transition.updateFrame(node: self.rateButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 33.0 - closeButtonSize.width - rateButtonSize.width - rightInset, y: -4.0), size: rateButtonSize)) transition.updateFrame(node: self.playPauseIconNode, frame: CGRect(origin: CGPoint(x: 6.0, y: 4.0 + UIScreenPixel), size: CGSize(width: 28.0, height: 28.0))) transition.updateFrame(node: self.actionButton, frame: CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: 40.0, height: 37.0))) transition.updateFrame(node: self.scrubbingNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 37.0 - 2.0), size: CGSize(width: size.width, height: 2.0))) @@ -501,7 +501,18 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi } @objc public func rateButtonPressed() { - self.rateButton.contextAction?(self.rateButton.containerNode, nil) + let nextRate: AudioPlaybackRate + if let rate = self.playbackBaseRate { + switch rate { + case .x1: + nextRate = .x2 + default: + nextRate = .x1 + } + } else { + nextRate = .x2 + } + self.setRate?(nextRate) } private func speedList(strings: PresentationStrings) -> [(String, String, AudioPlaybackRate)] { @@ -542,7 +553,6 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi let items: Signal<[ContextMenuItem], NoError> = self.contextMenuSpeedItems() let contextController = ContextController(account: self.context.account, presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, source: .reference(HeaderContextReferenceContentSource(controller: controller, sourceNode: self.rateButton.referenceNode)), items: items, reactionItems: [], gesture: gesture) self.presentInGlobalOverlay?(contextController) -// controller.presentInGlobalOverlay(contextController) } @objc public func actionButtonPressed() { @@ -606,38 +616,42 @@ private final class PlayPauseIconNode: ManagedAnimationNode { } } -private func optionsRateImage(rate: String, isLarge: Bool, color: UIColor = .white) -> UIImage? { - return generateImage(isLarge ? CGSize(width: 30.0, height: 30.0) : CGSize(width: 24.0, height: 24.0), rotatedContext: { size, context in +private func optionsRateImage(rate: String, color: UIColor = .white) -> UIImage? { + return generateImage(CGSize(width: 30.0, height: 16.0), rotatedContext: { size, context in UIGraphicsPushContext(context) context.clear(CGRect(origin: CGPoint(), size: size)) - if let image = generateTintedImage(image: UIImage(bundleImageName: isLarge ? "Chat/Context Menu/Playspeed30" : "Chat/Context Menu/Playspeed24"), color: color) { - image.draw(at: CGPoint(x: 0.0, y: 0.0)) - } + let lineWidth = 1.0 + UIScreenPixel + context.setLineWidth(lineWidth) + context.setStrokeColor(color.cgColor) + - let string = NSMutableAttributedString(string: rate, font: Font.with(size: 11.0, design: .round, weight: .semibold), textColor: color) + let string = NSMutableAttributedString(string: rate, font: Font.with(size: 11.0, design: .round, weight: .bold), textColor: color) var offset = CGPoint(x: 1.0, y: 0.0) + var width: CGFloat if rate.count >= 3 { - if rate == "0.5x" { + if rate == "0.5X" { string.addAttribute(.kern, value: -0.8 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string)) offset.x += -0.5 } else { string.addAttribute(.kern, value: -0.5 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string)) offset.x += -0.3 } + width = 29.0 } else { + string.addAttribute(.kern, value: -0.5 as NSNumber, range: NSRange(string.string.startIndex ..< string.string.endIndex, in: string.string)) + width = 19.0 offset.x += -0.3 } - - if !isLarge { - offset.x *= 0.5 - offset.y *= 0.5 - } - + + let path = UIBezierPath(roundedRect: CGRect(x: floorToScreenPixels((size.width - width) / 2.0), y: 0.0, width: width, height: 16.0).insetBy(dx: lineWidth / 2.0, dy: lineWidth / 2.0), byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 2.0, height: 2.0)) + context.addPath(path.cgPath) + context.strokePath() + let boundingRect = string.boundingRect(with: size, options: [], context: nil) - string.draw(at: CGPoint(x: offset.x + floor((size.width - boundingRect.width) / 2.0), y: offset.y + floor((size.height - boundingRect.height) / 2.0))) + string.draw(at: CGPoint(x: offset.x + floor((size.width - boundingRect.width) / 2.0), y: offset.y + UIScreenPixel + floor((size.height - boundingRect.height) / 2.0))) UIGraphicsPopContext() })