mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Various fixes
This commit is contained in:
parent
8a7daf3662
commit
7ab4685940
10 changed files with 140 additions and 64 deletions
|
|
@ -146,7 +146,7 @@ private final class CameraContext {
|
|||
transform = CGAffineTransformTranslate(transform, 0.0, -size.height)
|
||||
ciImage = ciImage.transformed(by: transform)
|
||||
}
|
||||
ciImage = ciImage.clampedToExtent().applyingGaussianBlur(sigma: Camera.isDualCameraSupported(forRoundVideo: true) ? 100.0 : 40.0).cropped(to: CGRect(origin: .zero, size: size))
|
||||
ciImage = ciImage.clampedToExtent().applyingGaussianBlur(sigma: Camera.isDualCameraSupported(forRoundVideo: true) ? 60.0 : 40.0).cropped(to: CGRect(origin: .zero, size: size))
|
||||
if let cgImage = self.ciContext.createCGImage(ciImage, from: ciImage.extent) {
|
||||
let uiImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: .right)
|
||||
if front {
|
||||
|
|
@ -189,6 +189,7 @@ private final class CameraContext {
|
|||
|
||||
deinit {
|
||||
Logger.shared.log("CameraContext", "deinit")
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
private var isSessionRunning = false
|
||||
|
|
@ -202,7 +203,7 @@ private final class CameraContext {
|
|||
}
|
||||
|
||||
func stopCapture(invalidate: Bool = false) {
|
||||
Logger.shared.log("CameraContext", "startCapture(invalidate: \(invalidate))")
|
||||
Logger.shared.log("CameraContext", "stopCapture(invalidate: \(invalidate))")
|
||||
if invalidate {
|
||||
self.mainDeviceContext?.device.resetZoom()
|
||||
|
||||
|
|
@ -212,6 +213,7 @@ private final class CameraContext {
|
|||
}
|
||||
|
||||
self.session.session.stopRunning()
|
||||
self.isSessionRunning = false
|
||||
}
|
||||
|
||||
func focus(at point: CGPoint, autoFocus: Bool) {
|
||||
|
|
@ -228,7 +230,7 @@ private final class CameraContext {
|
|||
}
|
||||
|
||||
func setFps(_ fps: Float64) {
|
||||
self.mainDeviceContext?.device.fps = fps
|
||||
self.mainDeviceContext?.device.setFps(fps)
|
||||
}
|
||||
|
||||
private var modeChange: Camera.ModeChange = .none {
|
||||
|
|
@ -1170,6 +1172,7 @@ public struct CameraRecordingData {
|
|||
}
|
||||
|
||||
public enum CameraRecordingError {
|
||||
case videoRecorderInitializationError
|
||||
case audioInitializationError
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,10 +141,12 @@ final class CameraDevice {
|
|||
Logger.shared.log("Camera", "No format selected")
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
Logger.shared.log("Camera", "Available formats:")
|
||||
for format in device.formats {
|
||||
Logger.shared.log("Camera", format.description)
|
||||
}
|
||||
#endif
|
||||
|
||||
if let targetFPS = device.actualFPS(maxFramerate) {
|
||||
device.activeVideoMinFrameDuration = targetFPS.duration
|
||||
|
|
@ -180,18 +182,16 @@ final class CameraDevice {
|
|||
self.setFocusPoint(CGPoint(x: 0.5, y: 0.5), focusMode: .continuousAutoFocus, exposureMode: .continuousAutoExposure, monitorSubjectAreaChange: false)
|
||||
}
|
||||
|
||||
var fps: Double = defaultFPS {
|
||||
didSet {
|
||||
guard let device = self.videoDevice, let targetFPS = device.actualFPS(Double(self.fps)) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.fps = targetFPS.fps
|
||||
|
||||
self.transaction(device) { device in
|
||||
device.activeVideoMinFrameDuration = targetFPS.duration
|
||||
device.activeVideoMaxFrameDuration = targetFPS.duration
|
||||
}
|
||||
private(set) var fps: Double = defaultFPS
|
||||
|
||||
func setFps(_ fps: Double) {
|
||||
guard let device = self.videoDevice, let targetFPS = device.actualFPS(Double(self.fps)) else {
|
||||
return
|
||||
}
|
||||
self.fps = targetFPS.fps
|
||||
self.transaction(device) { device in
|
||||
device.activeVideoMinFrameDuration = targetFPS.duration
|
||||
device.activeVideoMaxFrameDuration = targetFPS.duration
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ public struct CameraCode: Equatable {
|
|||
}
|
||||
|
||||
final class CameraOutput: NSObject {
|
||||
private struct RoundVideoFormatDescriptionCacheEntry {
|
||||
let sourceFormatDescription: CMFormatDescription
|
||||
let outputFormatDescription: CMFormatDescription
|
||||
}
|
||||
|
||||
let exclusive: Bool
|
||||
let ciContext: CIContext
|
||||
let colorSpace: CGColorSpace
|
||||
|
|
@ -111,13 +116,14 @@ final class CameraOutput: NSObject {
|
|||
|
||||
private var roundVideoFilter: CameraRoundLegacyVideoFilter?
|
||||
private let semaphore = DispatchSemaphore(value: 1)
|
||||
private var roundVideoFormatDescriptionCache: [RoundVideoFormatDescriptionCacheEntry] = []
|
||||
|
||||
private let videoQueue = DispatchQueue(label: "", qos: .userInitiated)
|
||||
private let audioQueue = DispatchQueue(label: "")
|
||||
|
||||
private let metadataQueue = DispatchQueue(label: "")
|
||||
|
||||
private var photoCaptureRequests: [Int64: PhotoCaptureContext] = [:]
|
||||
private var photoCaptureRequests = Atomic<[Int64: PhotoCaptureContext]>(value: [:])
|
||||
private var videoRecorder: VideoRecorder?
|
||||
|
||||
private var captureOrientation: AVCaptureVideoOrientation = .portrait
|
||||
|
|
@ -268,8 +274,8 @@ final class CameraOutput: NSObject {
|
|||
return EmptyDisposable
|
||||
}
|
||||
subscriber.putNext(self.photoOutput.isFlashScene)
|
||||
let observer = self.photoOutput.observe(\.isFlashScene, options: [.new], changeHandler: { device, _ in
|
||||
subscriber.putNext(self.photoOutput.isFlashScene)
|
||||
let observer = self.photoOutput.observe(\.isFlashScene, options: [.new], changeHandler: { output, _ in
|
||||
subscriber.putNext(output.isFlashScene)
|
||||
})
|
||||
return ActionDisposable {
|
||||
observer.invalidate()
|
||||
|
|
@ -316,12 +322,20 @@ final class CameraOutput: NSObject {
|
|||
#else
|
||||
let uniqueId = settings.uniqueID
|
||||
let photoCapture = PhotoCaptureContext(ciContext: self.ciContext, settings: settings, orientation: orientation, mirror: mirror)
|
||||
self.photoCaptureRequests[uniqueId] = photoCapture
|
||||
let _ = self.photoCaptureRequests.modify { dict in
|
||||
var dict = dict
|
||||
dict[uniqueId] = photoCapture
|
||||
return dict
|
||||
}
|
||||
self.photoOutput.capturePhoto(with: settings, delegate: photoCapture)
|
||||
|
||||
return photoCapture.signal
|
||||
|> afterDisposed { [weak self] in
|
||||
self?.photoCaptureRequests.removeValue(forKey: uniqueId)
|
||||
let _ = self?.photoCaptureRequests.modify { dict in
|
||||
var dict = dict
|
||||
dict.removeValue(forKey: uniqueId)
|
||||
return dict
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -419,18 +433,21 @@ final class CameraOutput: NSObject {
|
|||
}
|
||||
}
|
||||
)
|
||||
guard let videoRecorder else {
|
||||
return .fail(.videoRecorderInitializationError)
|
||||
}
|
||||
|
||||
videoRecorder?.start()
|
||||
videoRecorder.start()
|
||||
self.videoRecorder = videoRecorder
|
||||
|
||||
if case .dualCamera = mode, let position {
|
||||
videoRecorder?.markPositionChange(position: position, time: .zero)
|
||||
videoRecorder.markPositionChange(position: position, time: .zero)
|
||||
} else if case .roundVideo = mode {
|
||||
additionalOutput?.masterOutput = self
|
||||
}
|
||||
|
||||
return Signal { subscriber in
|
||||
let timer = SwiftSignalKit.Timer(timeout: 0.033, repeat: true, completion: { [weak videoRecorder] in
|
||||
let timer = SwiftSignalKit.Timer(timeout: 0.1, repeat: true, completion: { [weak videoRecorder] in
|
||||
let recordingData = CameraRecordingData(duration: videoRecorder?.duration ?? 0.0, filePath: outputFilePath)
|
||||
subscriber.putNext(recordingData)
|
||||
}, queue: Queue.mainQueue())
|
||||
|
|
@ -456,13 +473,54 @@ final class CameraOutput: NSObject {
|
|||
}
|
||||
|
||||
var transitionImage: UIImage? {
|
||||
return self.videoRecorder?.transitionImage
|
||||
var result: UIImage?
|
||||
self.videoQueue.sync {
|
||||
result = self.videoRecorder?.transitionImage
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private weak var masterOutput: CameraOutput?
|
||||
|
||||
private var lastSampleTimestamp: CMTime?
|
||||
|
||||
private func roundVideoFormatDescription(for sourceFormatDescription: CMFormatDescription) -> CMFormatDescription? {
|
||||
if let entry = self.roundVideoFormatDescriptionCache.first(where: { CFEqual($0.sourceFormatDescription, sourceFormatDescription) }) {
|
||||
return entry.outputFormatDescription
|
||||
}
|
||||
|
||||
guard let extensions = CMFormatDescriptionGetExtensions(sourceFormatDescription) as? [String: Any] else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let mediaSubType = CMFormatDescriptionGetMediaSubType(sourceFormatDescription)
|
||||
var updatedExtensions = extensions
|
||||
updatedExtensions["CVBytesPerRow"] = videoMessageDimensions.width * 4
|
||||
|
||||
var outputFormatDescription: CMFormatDescription?
|
||||
let status = CMVideoFormatDescriptionCreate(
|
||||
allocator: nil,
|
||||
codecType: mediaSubType,
|
||||
width: videoMessageDimensions.width,
|
||||
height: videoMessageDimensions.height,
|
||||
extensions: updatedExtensions as CFDictionary,
|
||||
formatDescriptionOut: &outputFormatDescription
|
||||
)
|
||||
guard status == noErr, let outputFormatDescription else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.roundVideoFormatDescriptionCache.append(RoundVideoFormatDescriptionCacheEntry(
|
||||
sourceFormatDescription: sourceFormatDescription,
|
||||
outputFormatDescription: outputFormatDescription
|
||||
))
|
||||
if self.roundVideoFormatDescriptionCache.count > 4 {
|
||||
self.roundVideoFormatDescriptionCache.removeFirst(self.roundVideoFormatDescriptionCache.count - 4)
|
||||
}
|
||||
|
||||
return outputFormatDescription
|
||||
}
|
||||
|
||||
private var needsCrossfadeTransition = false
|
||||
private var crossfadeTransitionStart: Double = 0.0
|
||||
|
||||
|
|
@ -564,17 +622,11 @@ final class CameraOutput: NSObject {
|
|||
return nil
|
||||
}
|
||||
self.semaphore.wait()
|
||||
|
||||
let mediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription)
|
||||
let extensions = CMFormatDescriptionGetExtensions(formatDescription) as! [String: Any]
|
||||
|
||||
var updatedExtensions = extensions
|
||||
updatedExtensions["CVBytesPerRow"] = videoMessageDimensions.width * 4
|
||||
|
||||
var newFormatDescription: CMFormatDescription?
|
||||
var status = CMVideoFormatDescriptionCreate(allocator: nil, codecType: mediaSubType, width: videoMessageDimensions.width, height: videoMessageDimensions.height, extensions: updatedExtensions as CFDictionary, formatDescriptionOut: &newFormatDescription)
|
||||
guard status == noErr, let newFormatDescription else {
|
||||
defer {
|
||||
self.semaphore.signal()
|
||||
}
|
||||
|
||||
guard let newFormatDescription = self.roundVideoFormatDescription(for: formatDescription) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -585,12 +637,11 @@ final class CameraOutput: NSObject {
|
|||
filter = CameraRoundLegacyVideoFilter(ciContext: self.ciContext, colorSpace: self.colorSpace, simple: self.exclusive)
|
||||
self.roundVideoFilter = filter
|
||||
}
|
||||
if !filter.isPrepared {
|
||||
if !filter.isPrepared || filter.inputFormatDescription.map({ !CFEqual($0, newFormatDescription) }) ?? true {
|
||||
filter.prepare(with: newFormatDescription, outputRetainedBufferCountHint: 4)
|
||||
}
|
||||
|
||||
guard let newPixelBuffer = filter.render(pixelBuffer: videoPixelBuffer, additional: additional, captureOrientation: self.captureOrientation, transitionFactor: transitionFactor) else {
|
||||
self.semaphore.signal()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +654,7 @@ final class CameraOutput: NSObject {
|
|||
}
|
||||
|
||||
var newSampleBuffer: CMSampleBuffer?
|
||||
status = CMSampleBufferCreateForImageBuffer(
|
||||
let status = CMSampleBufferCreateForImageBuffer(
|
||||
allocator: kCFAllocatorDefault,
|
||||
imageBuffer: newPixelBuffer,
|
||||
dataReady: true,
|
||||
|
|
@ -615,10 +666,8 @@ final class CameraOutput: NSObject {
|
|||
)
|
||||
|
||||
if status == noErr, let newSampleBuffer {
|
||||
self.semaphore.signal()
|
||||
return newSampleBuffer
|
||||
}
|
||||
self.semaphore.signal()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -640,18 +689,18 @@ extension CameraOutput: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureA
|
|||
guard CMSampleBufferDataIsReady(sampleBuffer) else {
|
||||
return
|
||||
}
|
||||
|
||||
if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
|
||||
self.processSampleBuffer?(sampleBuffer, videoPixelBuffer, connection)
|
||||
} else if sampleBuffer.type == kCMMediaType_Audio {
|
||||
self.processAudioBuffer?(sampleBuffer)
|
||||
}
|
||||
|
||||
|
||||
if let masterOutput = self.masterOutput {
|
||||
masterOutput.processVideoRecording(sampleBuffer, fromAdditionalOutput: true)
|
||||
} else {
|
||||
self.processVideoRecording(sampleBuffer, fromAdditionalOutput: false)
|
||||
}
|
||||
|
||||
if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
|
||||
self.processSampleBuffer?(sampleBuffer, videoPixelBuffer, connection)
|
||||
} else if sampleBuffer.type == kCMMediaType_Audio {
|
||||
self.processAudioBuffer?(sampleBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ final class PhotoCaptureContext: NSObject, AVCapturePhotoCaptureDelegate {
|
|||
} else {
|
||||
guard let photoPixelBuffer = photo.pixelBuffer else {
|
||||
print("Error occurred while capturing photo: Missing pixel buffer (\(String(describing: error)))")
|
||||
self.pipe.putNext(.failed)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,9 +204,7 @@ private final class VideoRecorderImpl {
|
|||
let maxDate = Date(timeIntervalSinceNow: 0.05)
|
||||
RunLoop.current.run(until: maxDate)
|
||||
}
|
||||
}
|
||||
|
||||
if let videoInput = self.videoInput {
|
||||
let time = CACurrentMediaTime()
|
||||
// if let previousPresentationTime = self.previousPresentationTime, let previousAppendTime = self.previousAppendTime {
|
||||
// print("appending \(presentationTime.seconds) (\(presentationTime.seconds - previousPresentationTime) ) on \(time) (\(time - previousAppendTime)")
|
||||
|
|
@ -366,7 +364,7 @@ private final class VideoRecorderImpl {
|
|||
|
||||
private func maybeFinish() {
|
||||
dispatchPrecondition(condition: .onQueue(self.queue))
|
||||
guard self.hasAllVideoBuffers && self.hasAllVideoBuffers && !self.stopped else {
|
||||
guard self.hasAllVideoBuffers && (!self.configuration.hasAudio || self.hasAllAudioBuffers) && !self.stopped else {
|
||||
return
|
||||
}
|
||||
let _ = self._stopped.modify { _ in return true }
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@
|
|||
|
||||
- (void)createDismissViewIfNeeded
|
||||
{
|
||||
if (_dismissView != nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIView *parentView = [self _parentView];
|
||||
|
||||
_dismissView = [[UIView alloc] initWithFrame:parentView.bounds];
|
||||
|
|
@ -231,6 +235,12 @@
|
|||
- (void)finishEditing {
|
||||
if ([self.inputPanel dismissInput]) {
|
||||
_editing = false;
|
||||
|
||||
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
_dismissView.alpha = 0.0f;
|
||||
} completion:^(BOOL finished) {
|
||||
|
||||
}];
|
||||
|
||||
if (self.finishedWithCaption != nil)
|
||||
self.finishedWithCaption([_inputPanel caption]);
|
||||
|
|
|
|||
|
|
@ -260,7 +260,11 @@ private func proxySettingsControllerEntries(theme: PresentationTheme, strings: P
|
|||
entries.append(.serversHeader(theme, strings.SocksProxySetup_SavedProxies))
|
||||
entries.append(.addServer(theme, strings.SocksProxySetup_AddProxy, state.editing))
|
||||
var index = 0
|
||||
var existingServers = Set<ProxyServerSettings>()
|
||||
for server in proxySettings.servers {
|
||||
if !existingServers.insert(server).inserted {
|
||||
continue
|
||||
}
|
||||
let status: ProxyServerStatus = statuses[server] ?? .checking
|
||||
let displayStatus: DisplayProxyServerStatus
|
||||
if proxySettings.enabled && server == proxySettings.activeServer {
|
||||
|
|
@ -301,7 +305,7 @@ private func proxySettingsControllerEntries(theme: PresentationTheme, strings: P
|
|||
entries.append(.server(index, theme, strings, server, server == proxySettings.activeServer, displayStatus, ProxySettingsServerItemEditing(editable: true, editing: state.editing, revealed: state.revealedServer == server), proxySettings.enabled))
|
||||
index += 1
|
||||
}
|
||||
if !proxySettings.servers.isEmpty {
|
||||
if !existingServers.isEmpty {
|
||||
entries.append(.shareProxyList(theme, strings.SocksProxySetup_ShareProxyList))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -347,8 +347,11 @@ func proxyServerSettingsController(sharedContext: SharedAccountContext, context:
|
|||
}
|
||||
}
|
||||
} else {
|
||||
settings.servers.append(proxyServerSettings)
|
||||
if settings.servers.count == 1 {
|
||||
let wasEmpty = settings.servers.isEmpty
|
||||
if !settings.servers.contains(proxyServerSettings) {
|
||||
settings.servers.append(proxyServerSettings)
|
||||
}
|
||||
if wasEmpty && settings.servers.count == 1 {
|
||||
settings.activeServer = proxyServerSettings
|
||||
}
|
||||
}
|
||||
|
|
@ -388,4 +391,3 @@ func proxyServerSettingsController(sharedContext: SharedAccountContext, context:
|
|||
|
||||
return controller
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ final class CameraVideoSource: VideoSource {
|
|||
let index = self.onUpdatedListeners.add(f)
|
||||
|
||||
return ActionDisposable { [weak self] in
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -252,7 +252,7 @@ final class LiveStreamMediaSource {
|
|||
let index = self.onVideoUpdatedListeners.add(f)
|
||||
|
||||
return ActionDisposable { [weak self] in
|
||||
DispatchQueue.main.async {
|
||||
Queue.mainQueue().async {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3427,6 +3427,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||
}
|
||||
}
|
||||
if let mediaDraftState = interfaceState.interfaceState.mediaDraftState, case .audio = mediaDraftState.contentType {
|
||||
viewOnceIsVisible = true
|
||||
recordMoreIsVisible = true
|
||||
}
|
||||
|
||||
|
|
@ -3438,13 +3439,29 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||
transition.updateSublayerTransformOffset(layer: self.clippingNode.layer, offset: CGPoint(x: 0.0, y: clippingDelta))*/
|
||||
|
||||
let viewOnceSize = self.viewOnceButton.update(theme: interfaceState.theme)
|
||||
let viewOnceButtonFrame = CGRect(origin: CGPoint(x: width - rightInset - 50.0 - UIScreenPixel, y: -152.0), size: viewOnceSize)
|
||||
|
||||
var viewOnceButtonY: CGFloat = -105.0
|
||||
if isRecording {
|
||||
if accessoryPanel == nil {
|
||||
viewOnceButtonY -= 49.0
|
||||
}
|
||||
}
|
||||
|
||||
let viewOnceButtonFrame = CGRect(origin: CGPoint(x: width - rightInset - 50.0 - UIScreenPixel, y: viewOnceButtonY), size: viewOnceSize)
|
||||
self.viewOnceButton.bounds = CGRect(origin: .zero, size: viewOnceButtonFrame.size)
|
||||
transition.updatePosition(node: self.viewOnceButton, position: viewOnceButtonFrame.center)
|
||||
|
||||
if self.viewOnceButton.alpha.isZero && viewOnceIsVisible {
|
||||
self.viewOnceButton.update(isSelected: self.viewOnce, animated: false)
|
||||
}
|
||||
|
||||
transition.updateAlpha(node: self.viewOnceButton, alpha: viewOnceIsVisible ? 1.0 : 0.0)
|
||||
transition.updateTransformScale(node: self.viewOnceButton, scale: viewOnceIsVisible ? 1.0 : 0.01)
|
||||
if let user = interfaceState.renderedPeer?.peer as? TelegramUser, user.id != interfaceState.accountPeerId && user.botInfo == nil && interfaceState.sendPaidMessageStars == nil {
|
||||
self.viewOnceButton.isHidden = false
|
||||
} else {
|
||||
self.viewOnceButton.isHidden = true
|
||||
}
|
||||
|
||||
let recordMoreSize = self.recordMoreButton.update(theme: interfaceState.theme)
|
||||
let recordMoreButtonFrame = CGRect(origin: CGPoint(x: width - rightInset - 50.0 - UIScreenPixel, y: -52.0), size: recordMoreSize)
|
||||
|
|
@ -3455,14 +3472,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||
self.recordMoreButton.update(isSelected: false, animated: false)
|
||||
}
|
||||
|
||||
transition.updateAlpha(node: self.viewOnceButton, alpha: viewOnceIsVisible ? 1.0 : 0.0)
|
||||
transition.updateTransformScale(node: self.viewOnceButton, scale: viewOnceIsVisible ? 1.0 : 0.01)
|
||||
if let user = interfaceState.renderedPeer?.peer as? TelegramUser, user.id != interfaceState.accountPeerId && user.botInfo == nil && interfaceState.sendPaidMessageStars == nil {
|
||||
self.viewOnceButton.isHidden = false
|
||||
} else {
|
||||
self.viewOnceButton.isHidden = true
|
||||
}
|
||||
|
||||
transition.updateAlpha(node: self.recordMoreButton, alpha: recordMoreIsVisible ? 1.0 : 0.0)
|
||||
transition.updateTransformScale(node: self.recordMoreButton, scale: recordMoreIsVisible ? 1.0 : 0.01)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue