mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-31 15:37:01 +00:00
Merge commit '8467d6b3871756e7b63cc5cc912b29503a21dd3d'
This commit is contained in:
commit
a675cf1e65
227
submodules/CameraUI/Sources/CameraZoomNode.swift
Normal file
227
submodules/CameraUI/Sources/CameraZoomNode.swift
Normal file
@ -0,0 +1,227 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
|
||||
private final class ZoomWheelNodeDrawingState: NSObject {
|
||||
let transition: CGFloat
|
||||
let reverse: Bool
|
||||
|
||||
init(transition: CGFloat, reverse: Bool) {
|
||||
self.transition = transition
|
||||
self.reverse = reverse
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
final class ZoomWheelNode: ASDisplayNode {
|
||||
class State: Equatable {
|
||||
let active: Bool
|
||||
|
||||
init(active: Bool) {
|
||||
self.active = active
|
||||
}
|
||||
|
||||
static func ==(lhs: State, rhs: State) -> Bool {
|
||||
if lhs.active != rhs.active {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private class TransitionContext {
|
||||
let startTime: Double
|
||||
let duration: Double
|
||||
let previousState: State
|
||||
|
||||
init(startTime: Double, duration: Double, previousState: State) {
|
||||
self.startTime = startTime
|
||||
self.duration = duration
|
||||
self.previousState = previousState
|
||||
}
|
||||
}
|
||||
|
||||
private var animator: ConstantDisplayLinkAnimator?
|
||||
|
||||
private var hasState = false
|
||||
private var state: State = State(active: false)
|
||||
private var transitionContext: TransitionContext?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
self.isOpaque = false
|
||||
}
|
||||
|
||||
func update(state: State, animated: Bool) {
|
||||
var animated = animated
|
||||
if !self.hasState {
|
||||
self.hasState = true
|
||||
animated = false
|
||||
}
|
||||
|
||||
if self.state != state {
|
||||
let previousState = self.state
|
||||
self.state = state
|
||||
|
||||
if animated {
|
||||
self.transitionContext = TransitionContext(startTime: CACurrentMediaTime(), duration: 0.18, previousState: previousState)
|
||||
}
|
||||
|
||||
self.updateAnimations()
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateAnimations() {
|
||||
var animate = false
|
||||
let timestamp = CACurrentMediaTime()
|
||||
|
||||
if let transitionContext = self.transitionContext {
|
||||
if transitionContext.startTime + transitionContext.duration < timestamp {
|
||||
self.transitionContext = nil
|
||||
} else {
|
||||
animate = true
|
||||
}
|
||||
}
|
||||
|
||||
if animate {
|
||||
let animator: ConstantDisplayLinkAnimator
|
||||
if let current = self.animator {
|
||||
animator = current
|
||||
} else {
|
||||
animator = ConstantDisplayLinkAnimator(update: { [weak self] in
|
||||
self?.updateAnimations()
|
||||
})
|
||||
self.animator = animator
|
||||
}
|
||||
animator.isPaused = false
|
||||
} else {
|
||||
self.animator?.isPaused = true
|
||||
}
|
||||
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
|
||||
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||
var transitionFraction: CGFloat = self.state.active ? 1.0 : 0.0
|
||||
|
||||
var reverse = false
|
||||
if let transitionContext = self.transitionContext {
|
||||
let timestamp = CACurrentMediaTime()
|
||||
var t = CGFloat((timestamp - transitionContext.startTime) / transitionContext.duration)
|
||||
t = min(1.0, max(0.0, t))
|
||||
|
||||
if transitionContext.previousState.active != self.state.active {
|
||||
transitionFraction = self.state.active ? t : 1.0 - t
|
||||
|
||||
reverse = transitionContext.previousState.active
|
||||
}
|
||||
}
|
||||
|
||||
return ZoomWheelNodeDrawingState(transition: transitionFraction, reverse: reverse)
|
||||
}
|
||||
|
||||
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
if !isRasterizing {
|
||||
context.setBlendMode(.copy)
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.fill(bounds)
|
||||
}
|
||||
|
||||
guard let parameters = parameters as? ZoomWheelNodeDrawingState else {
|
||||
return
|
||||
}
|
||||
|
||||
let color = UIColor(rgb: 0xffffff)
|
||||
context.setFillColor(color.cgColor)
|
||||
|
||||
let clearLineWidth: CGFloat = 4.0
|
||||
let lineWidth: CGFloat = 1.0 + UIScreenPixel
|
||||
|
||||
context.scaleBy(x: 2.5, y: 2.5)
|
||||
|
||||
context.translateBy(x: 4.0, y: 3.0)
|
||||
let _ = try? drawSvgPath(context, path: "M14,8.335 C14.36727,8.335 14.665,8.632731 14.665,9 C14.665,11.903515 12.48064,14.296846 9.665603,14.626311 L9.665,16 C9.665,16.367269 9.367269,16.665 9,16.665 C8.666119,16.665 8.389708,16.418942 8.34221,16.098269 L8.335,16 L8.3354,14.626428 C5.519879,14.297415 3.335,11.90386 3.335,9 C3.335,8.632731 3.632731,8.335 4,8.335 C4.367269,8.335 4.665,8.632731 4.665,9 C4.665,11.394154 6.605846,13.335 9,13.335 C11.39415,13.335 13.335,11.394154 13.335,9 C13.335,8.632731 13.63273,8.335 14,8.335 Z ")
|
||||
|
||||
let _ = try? drawSvgPath(context, path: "M9,2.5 C10.38071,2.5 11.5,3.61929 11.5,5 L11.5,9 C11.5,10.380712 10.38071,11.5 9,11.5 C7.619288,11.5 6.5,10.380712 6.5,9 L6.5,5 C6.5,3.61929 7.619288,2.5 9,2.5 Z ")
|
||||
|
||||
context.translateBy(x: -4.0, y: -3.0)
|
||||
|
||||
if parameters.transition > 0.0 {
|
||||
let startPoint: CGPoint
|
||||
let endPoint: CGPoint
|
||||
|
||||
let origin = CGPoint(x: 9.0, y: 10.0 - UIScreenPixel)
|
||||
let length: CGFloat = 17.0
|
||||
|
||||
if parameters.reverse {
|
||||
startPoint = CGPoint(x: origin.x + length * (1.0 - parameters.transition), y: origin.y + length * (1.0 - parameters.transition))
|
||||
endPoint = CGPoint(x: origin.x + length, y: origin.y + length)
|
||||
} else {
|
||||
startPoint = origin
|
||||
endPoint = CGPoint(x: origin.x + length * parameters.transition, y: origin.y + length * parameters.transition)
|
||||
}
|
||||
|
||||
context.setBlendMode(.clear)
|
||||
context.setLineWidth(clearLineWidth)
|
||||
|
||||
context.move(to: startPoint)
|
||||
context.addLine(to: endPoint)
|
||||
context.strokePath()
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
context.setStrokeColor(color.cgColor)
|
||||
context.setLineWidth(lineWidth)
|
||||
context.setLineCap(.round)
|
||||
context.setLineJoin(.round)
|
||||
|
||||
context.move(to: startPoint)
|
||||
context.addLine(to: endPoint)
|
||||
context.strokePath()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ButtonNode: HighlightTrackingButtonNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let textNode: ImmediateTextNode
|
||||
|
||||
init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.textNode = ImmediateTextNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
self.highligthedChanged = { [weak self] highlight in
|
||||
if let strongSelf = self {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func update() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
final class CameraZoomNode: ASDisplayNode {
|
||||
private let wheelNode: ZoomWheelNode
|
||||
|
||||
private let backgroundNode: ASDisplayNode
|
||||
|
||||
override init() {
|
||||
self.wheelNode = ZoomWheelNode()
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.wheelNode)
|
||||
}
|
||||
}
|
@ -178,7 +178,6 @@ private final class VoiceChatVolumeContextItemNode: ASDisplayNode, ContextMenuCu
|
||||
let delta = translation / self.bounds.width * 2.0
|
||||
self.value = max(0.0, min(2.0, self.value + delta))
|
||||
self.valueChanged(self.value, true)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -4569,13 +4569,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
var inputTextMaxLength: Int32 = 4096
|
||||
var webpageUrl: String?
|
||||
for media in message.media {
|
||||
if media is TelegramMediaImage || media is TelegramMediaFile {
|
||||
inputTextMaxLength = strongSelf.context.currentLimitsConfiguration.with { $0 }.maxMediaCaptionLength
|
||||
break
|
||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
|
||||
webpageUrl = content.url
|
||||
}
|
||||
}
|
||||
return $0.withUpdatedEditMessage(ChatEditMessageState(messageId: messageId, inputState: ChatTextInputState(inputText: chatInputStateStringWithAppliedEntities(message.text, entities: entities)), disableUrlPreview: nil, inputTextMaxLength: inputTextMaxLength))
|
||||
let inputText = chatInputStateStringWithAppliedEntities(message.text, entities: entities)
|
||||
var disableUrlPreview: String?
|
||||
if let detectedWebpageUrl = detectUrl(inputText), webpageUrl == nil {
|
||||
disableUrlPreview = detectedWebpageUrl
|
||||
}
|
||||
return $0.withUpdatedEditMessage(ChatEditMessageState(messageId: messageId, inputState: ChatTextInputState(inputText: inputText), disableUrlPreview: disableUrlPreview, inputTextMaxLength: inputTextMaxLength))
|
||||
}
|
||||
|
||||
updated = updatedChatEditInterfaceMessageState(state: updated, message: message)
|
||||
|
@ -417,19 +417,11 @@ func searchQuerySuggestionResultStateForChatInterfacePresentationState(_ chatPre
|
||||
|
||||
private let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType([.link]).rawValue)
|
||||
|
||||
func urlPreviewStateForInputText(_ inputText: NSAttributedString?, context: AccountContext, currentQuery: String?) -> (String?, Signal<(TelegramMediaWebpage?) -> TelegramMediaWebpage?, NoError>)? {
|
||||
guard let text = inputText else {
|
||||
if currentQuery != nil {
|
||||
return (nil, .single({ _ in return nil }))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if let dataDetector = dataDetector {
|
||||
func detectUrl(_ inputText: NSAttributedString?) -> String? {
|
||||
var detectedUrl: String?
|
||||
if let text = inputText, let dataDetector = dataDetector {
|
||||
let utf16 = text.string.utf16
|
||||
|
||||
var detectedUrl: String?
|
||||
|
||||
let nsRange = NSRange(location: 0, length: utf16.count)
|
||||
let matches = dataDetector.matches(in: text.string, options: [], range: nsRange)
|
||||
if let match = matches.first {
|
||||
@ -444,7 +436,20 @@ func urlPreviewStateForInputText(_ inputText: NSAttributedString?, context: Acco
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
return detectedUrl
|
||||
}
|
||||
|
||||
func urlPreviewStateForInputText(_ inputText: NSAttributedString?, context: AccountContext, currentQuery: String?) -> (String?, Signal<(TelegramMediaWebpage?) -> TelegramMediaWebpage?, NoError>)? {
|
||||
guard let _ = inputText else {
|
||||
if currentQuery != nil {
|
||||
return (nil, .single({ _ in return nil }))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if let _ = dataDetector {
|
||||
let detectedUrl = detectUrl(inputText)
|
||||
if detectedUrl != currentQuery {
|
||||
if let detectedUrl = detectedUrl {
|
||||
return (detectedUrl, webpagePreview(account: context.account, url: detectedUrl) |> map { value in
|
||||
|
Loading…
x
Reference in New Issue
Block a user