Merge commit 'ca80657e161b28abde1b2eafa3528e04f5487ca6'

This commit is contained in:
Isaac 2024-01-18 14:39:58 +04:00
commit 941b3a0477
13 changed files with 271 additions and 84 deletions

View File

@ -10886,6 +10886,7 @@ Sorry for the inconvenience.";
"Call.StatusWeakSignal" = "Weak network signal";
"Conversation.ContactAddContact" = "ADD";
"Conversation.ContactAddContactLong" = "ADD CONTACT";
"Conversation.ContactMessage" = "MESSAGE";
"Chat.PlayOnceVideoMessageTooltip" = "This video message can only be played once.";

View File

@ -304,31 +304,35 @@ final class CameraOutput: NSObject {
self.currentMode = mode
self.lastSampleTimestamp = nil
let codecType: AVVideoCodecType
if case .roundVideo = mode {
codecType = .h264
} else {
if hasHEVCHardwareEncoder {
codecType = .hevc
} else {
codecType = .h264
}
}
guard var videoSettings = self.videoOutput.recommendedVideoSettings(forVideoCodecType: codecType, assetWriterOutputFileType: .mp4) else {
return .complete()
}
var dimensions: CGSize = CGSize(width: 1080, height: 1920)
if orientation == .landscapeLeft || orientation == .landscapeRight {
dimensions = CGSize(width: 1920, height: 1080)
}
var orientation = orientation
let dimensions: CGSize
let videoSettings: [String: Any]
if case .roundVideo = mode {
videoSettings[AVVideoWidthKey] = 400
videoSettings[AVVideoHeightKey] = 400
dimensions = CGSize(width: 400, height: 400)
dimensions = videoMessageDimensions.cgSize
orientation = .landscapeRight
let compressionProperties: [String: Any] = [
AVVideoAverageBitRateKey: 1000 * 1000,
AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel,
AVVideoH264EntropyModeKey: AVVideoH264EntropyModeCABAC
]
videoSettings = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoCompressionPropertiesKey: compressionProperties,
AVVideoWidthKey: Int(dimensions.width),
AVVideoHeightKey: Int(dimensions.height)
]
} else {
let codecType: AVVideoCodecType = hasHEVCHardwareEncoder ? .hevc : .h264
if orientation == .landscapeLeft || orientation == .landscapeRight {
dimensions = CGSize(width: 1920, height: 1080)
} else {
dimensions = CGSize(width: 1080, height: 1920)
}
guard let settings = self.videoOutput.recommendedVideoSettings(forVideoCodecType: codecType, assetWriterOutputFileType: .mp4) else {
return .complete()
}
videoSettings = settings
}
let audioSettings = self.audioOutput.recommendedAudioSettingsForAssetWriter(writingTo: .mp4) ?? [:]
@ -514,10 +518,10 @@ final class CameraOutput: NSObject {
let extensions = CMFormatDescriptionGetExtensions(formatDescription) as! [String: Any]
var updatedExtensions = extensions
updatedExtensions["CVBytesPerRow"] = 400 * 4
updatedExtensions["CVBytesPerRow"] = videoMessageDimensions.width * 4
var newFormatDescription: CMFormatDescription?
var status = CMVideoFormatDescriptionCreate(allocator: nil, codecType: mediaSubType, width: 400, height: 400, extensions: updatedExtensions as CFDictionary, formatDescriptionOut: &newFormatDescription)
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 {
return nil
}

View File

@ -5,6 +5,9 @@ import CoreMedia
import CoreVideo
import Metal
import Display
import TelegramCore
let videoMessageDimensions = PixelDimensions(width: 400, height: 400)
func allocateOutputBufferPool(with inputFormatDescription: CMFormatDescription, outputRetainedBufferCountHint: Int) -> (
outputBufferPool: CVPixelBufferPool?,
@ -114,8 +117,7 @@ class CameraRoundVideoFilter {
}
self.inputFormatDescription = formatDescription
let diameter: CGFloat = 400.0
let circleImage = generateImage(CGSize(width: diameter, height: diameter), opaque: false, scale: 1.0, rotatedContext: { size, context in
let circleImage = generateImage(videoMessageDimensions.cgSize, opaque: false, scale: 1.0, rotatedContext: { size, context in
let bounds = CGRect(origin: .zero, size: size)
context.clear(bounds)
context.setFillColor(UIColor.white.cgColor)
@ -158,7 +160,7 @@ class CameraRoundVideoFilter {
var sourceImage = CIImage(cvImageBuffer: pixelBuffer)
sourceImage = sourceImage.oriented(additional ? .leftMirrored : .right)
let scale = 400.0 / min(sourceImage.extent.width, sourceImage.extent.height)
let scale = CGFloat(videoMessageDimensions.width) / min(sourceImage.extent.width, sourceImage.extent.height)
resizeFilter.setValue(sourceImage, forKey: kCIInputImageKey)
resizeFilter.setValue(scale, forKey: kCIInputScaleKey)
@ -203,18 +205,14 @@ class CameraRoundVideoFilter {
guard let finalImage else {
return nil
}
if finalImage.extent.width != 400 {
print("wtf: \(finalImage)")
}
var pbuf: CVPixelBuffer?
CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, outputPixelBufferPool!, &pbuf)
guard let outputPixelBuffer = pbuf else {
return nil
}
self.ciContext.render(finalImage, to: outputPixelBuffer, bounds: CGRect(origin: .zero, size: CGSize(width: 400, height: 400)), colorSpace: outputColorSpace)
self.ciContext.render(finalImage, to: outputPixelBuffer, bounds: CGRect(origin: .zero, size: videoMessageDimensions.cgSize), colorSpace: outputColorSpace)
return outputPixelBuffer
}

View File

@ -47,6 +47,7 @@ public class ItemListDisclosureItem: ListViewItem, ItemListItem {
let title: String
let titleColor: ItemListDisclosureItemTitleColor
let titleFont: ItemListDisclosureItemTitleFont
let titleIcon: UIImage?
let enabled: Bool
let label: String
let labelStyle: ItemListDisclosureLabelStyle
@ -59,7 +60,7 @@ public class ItemListDisclosureItem: ListViewItem, ItemListItem {
public let tag: ItemListItemTag?
public let shimmeringIndex: Int?
public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, context: AccountContext? = nil, iconPeer: EnginePeer? = nil, title: String, enabled: Bool = true, titleColor: ItemListDisclosureItemTitleColor = .primary, titleFont: ItemListDisclosureItemTitleFont = .regular, label: String, labelStyle: ItemListDisclosureLabelStyle = .text, additionalDetailLabel: String? = nil, sectionId: ItemListSectionId, style: ItemListStyle, disclosureStyle: ItemListDisclosureStyle = .arrow, action: (() -> Void)?, clearHighlightAutomatically: Bool = true, tag: ItemListItemTag? = nil, shimmeringIndex: Int? = nil) {
public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, context: AccountContext? = nil, iconPeer: EnginePeer? = nil, title: String, enabled: Bool = true, titleColor: ItemListDisclosureItemTitleColor = .primary, titleFont: ItemListDisclosureItemTitleFont = .regular, titleIcon: UIImage? = nil, label: String, labelStyle: ItemListDisclosureLabelStyle = .text, additionalDetailLabel: String? = nil, sectionId: ItemListSectionId, style: ItemListStyle, disclosureStyle: ItemListDisclosureStyle = .arrow, action: (() -> Void)?, clearHighlightAutomatically: Bool = true, tag: ItemListItemTag? = nil, shimmeringIndex: Int? = nil) {
self.presentationData = presentationData
self.icon = icon
self.context = context
@ -67,6 +68,7 @@ public class ItemListDisclosureItem: ListViewItem, ItemListItem {
self.title = title
self.titleColor = titleColor
self.titleFont = titleFont
self.titleIcon = titleIcon
self.enabled = enabled
self.labelStyle = labelStyle
self.label = label
@ -138,6 +140,7 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
var avatarNode: AvatarNode?
let iconNode: ASImageNode
let titleNode: TextNode
let titleIconNode: ASImageNode
public let labelNode: TextNode
var additionalDetailLabelNode: TextNode?
let arrowNode: ASImageNode
@ -184,6 +187,10 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false
self.titleIconNode = ASImageNode()
self.titleIconNode.displayWithoutProcessing = true
self.titleIconNode.displaysAsynchronously = false
self.labelNode = TextNode()
self.labelNode.isUserInteractionEnabled = false
@ -626,6 +633,19 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.additionalDetailLabelNode = nil
additionalDetailLabelNode.removeFromSupernode()
}
if let titleIcon = item.titleIcon {
if strongSelf.titleIconNode.supernode == nil {
strongSelf.addSubnode(strongSelf.titleIconNode)
}
strongSelf.titleIconNode.image = titleIcon
strongSelf.titleIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 5.0, y: floor((layout.contentSize.height - titleIcon.size.height) / 2.0) - 1.0), size: titleIcon.size)
} else {
if strongSelf.titleIconNode.supernode != nil {
strongSelf.titleIconNode.removeFromSupernode()
}
}
if case .textWithIcon = item.labelStyle {
if let updatedLabelImage = updatedLabelImage {

View File

@ -97,7 +97,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
case forwardPrivacy(PresentationTheme, String, String)
case groupPrivacy(PresentationTheme, String, String)
case voiceMessagePrivacy(PresentationTheme, String, String, Bool)
case messagePrivacy(Bool)
case messagePrivacy(PresentationTheme, Bool, Bool)
case bioPrivacy(PresentationTheme, String, String)
case selectivePrivacyInfo(PresentationTheme, String)
case passcode(PresentationTheme, String, Bool, String)
@ -240,14 +240,14 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
} else {
return false
}
case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue, lhsLocked):
if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue, rhsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsLocked == rhsLocked {
case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue, lhsHasPremium):
if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue, rhsHasPremium) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsHasPremium == rhsHasPremium {
return true
} else {
return false
}
case let .messagePrivacy(value):
if case .messagePrivacy(value) = rhs {
case let .messagePrivacy(lhsTheme, lhsValue, lhsHasPremium):
if case let .messagePrivacy(rhsTheme, rhsValue, rhsHasPremium) = rhs, lhsTheme === rhsTheme, lhsValue == rhsValue, lhsHasPremium == rhsHasPremium {
return true
} else {
return false
@ -390,12 +390,12 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
arguments.openGroupsPrivacy()
})
case let .voiceMessagePrivacy(_, text, value, locked):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: locked ? .textWithIcon(UIImage(bundleImageName: "Chat/Input/Accessory Panels/TextLockIcon")!.precomposed()) : .text, sectionId: self.section, style: .blocks, action: {
case let .voiceMessagePrivacy(theme, text, value, hasPremium):
return ItemListDisclosureItem(presentationData: presentationData, title: text, titleIcon: hasPremium ? PresentationResourcesItemList.premiumIcon(theme) : nil, label: value, labelStyle: !hasPremium ? .textWithIcon(UIImage(bundleImageName: "Chat/Input/Accessory Panels/TextLockIcon")!.precomposed()) : .text, sectionId: self.section, style: .blocks, action: {
arguments.openVoiceMessagePrivacy()
})
case let .messagePrivacy(value):
return ItemListDisclosureItem(presentationData: presentationData, title: presentationData.strings.Settings_Privacy_Messages, label: !value ? presentationData.strings.Settings_Privacy_Messages_ValueEveryone : presentationData.strings.Settings_Privacy_Messages_ValueContactsAndPremium, sectionId: self.section, style: .blocks, action: {
case let .messagePrivacy(theme, value, hasPremium):
return ItemListDisclosureItem(presentationData: presentationData, title: presentationData.strings.Settings_Privacy_Messages, titleIcon: hasPremium ? PresentationResourcesItemList.premiumIcon(theme) : nil, label: !value ? presentationData.strings.Settings_Privacy_Messages_ValueEveryone : presentationData.strings.Settings_Privacy_Messages_ValueContactsAndPremium, sectionId: self.section, style: .blocks, action: {
arguments.openMessagePrivacy()
})
case let .bioPrivacy(_, text, value):
@ -591,8 +591,8 @@ private func privacyAndSecurityControllerEntries(
entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceCalls)))
entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.groupInvitations)))
if !isPremiumDisabled {
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), !isPremium))
entries.append(.messagePrivacy(privacySettings.globalSettings.nonContactChatsRequirePremium))
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), isPremium))
entries.append(.messagePrivacy(presentationData.theme, privacySettings.globalSettings.nonContactChatsRequirePremium, isPremium))
}
} else {
entries.append(.phoneNumberPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_PhoneNumber, presentationData.strings.Channel_NotificationLoading))
@ -603,7 +603,7 @@ private func privacyAndSecurityControllerEntries(
entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, presentationData.strings.Channel_NotificationLoading))
entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, presentationData.strings.Channel_NotificationLoading))
if !isPremiumDisabled {
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading, !isPremium))
entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading, isPremium))
}
//entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp))

View File

@ -72,6 +72,7 @@ public enum PresentationResourceKey: Int32 {
case itemListCloudIcon
case itemListTopicArrowIcon
case itemListAddBoostsIcon
case itemListPremiumIcon
case statsReactionsIcon
case statsForwardsIcon

View File

@ -282,6 +282,30 @@ public struct PresentationResourcesItemList {
})
}
public static func premiumIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.itemListPremiumIcon.rawValue, { theme in
return generateImage(CGSize(width: 16.0, height: 16.0), contextGenerator: { size, context in
let bounds = CGRect(origin: .zero, size: size)
context.clear(bounds)
let image = UIImage(bundleImageName: "Item List/PremiumIcon")!
context.clip(to: bounds, mask: image.cgImage!)
let colorsArray: [CGColor] = [
UIColor(rgb: 0x6b93ff).cgColor,
UIColor(rgb: 0x6b93ff).cgColor,
UIColor(rgb: 0x8d77ff).cgColor,
UIColor(rgb: 0xb56eec).cgColor,
UIColor(rgb: 0xb56eec).cgColor
]
var locations: [CGFloat] = [0.0, 0.3, 0.5, 0.7, 1.0]
let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions())
})
})
}
public static func cornersImage(_ theme: PresentationTheme, top: Bool, bottom: Bool) -> UIImage? {
if !top && !bottom {
return nil

View File

@ -307,7 +307,18 @@ public class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
}
let (messageButtonWidth, messageContinueLayout) = makeMessageButtonLayout(constrainedSize.width, nil, false, item.presentationData.strings.Conversation_ContactMessage.uppercased(), mainColor, false, false)
let (addButtonWidth, addContinueLayout) = makeAddButtonLayout(constrainedSize.width, nil, false, !canMessage && !canAdd ? item.presentationData.strings.Conversation_ViewContactDetails.uppercased() : item.presentationData.strings.Conversation_ContactAddContact.uppercased(), mainColor, false, false)
let addTitle: String
if !canMessage && !canAdd {
addTitle = item.presentationData.strings.Conversation_ViewContactDetails
} else {
if canMessage {
addTitle = item.presentationData.strings.Conversation_ContactAddContact
} else {
addTitle = item.presentationData.strings.Conversation_ContactAddContactLong
}
}
let (addButtonWidth, addContinueLayout) = makeAddButtonLayout(constrainedSize.width, nil, false, addTitle.uppercased(), mainColor, false, false)
let maxButtonWidth = max(messageButtonWidth, addButtonWidth)
var maxContentWidth: CGFloat = avatarSize.width + 7.0
@ -327,7 +338,7 @@ public class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
let lineWidth: CGFloat = 3.0
var buttonCount = 1
if canMessage {
if canMessage && canAdd {
buttonCount += 1
}
var buttonWidth = floor((boundingWidth - layoutConstants.text.bubbleInsets.right * 2.0 - lineWidth))
@ -387,7 +398,7 @@ public class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
strongSelf.messageButtonNode.isHidden = !canMessage
let backgroundInsets = layoutConstants.text.bubbleInsets
let backgroundFrame = CGRect(origin: CGPoint(x: backgroundInsets.left, y: backgroundInsets.top + 5.0), size: CGSize(width: contentWidth - layoutConstants.text.bubbleInsets.right * 2.0, height: layoutSize.height - 34.0))
let backgroundFrame = CGRect(origin: CGPoint(x: backgroundInsets.left, y: backgroundInsets.top + 5.0), size: CGSize(width: boundingWidth - layoutConstants.text.bubbleInsets.right * 2.0, height: layoutSize.height - 34.0))
if let statusSizeAndApply = statusSizeAndApply {
strongSelf.dateAndStatusNode.frame = CGRect(origin: CGPoint(x: layoutConstants.text.bubbleInsets.left, y: backgroundFrame.maxY + 3.0), size: statusSizeAndApply.0)

View File

@ -532,7 +532,7 @@ public class VideoMessageCameraScreen: ViewController {
fileprivate var liveUploadInterface: LegacyLiveUploadInterface?
private var currentLiveUploadPath: String?
fileprivate var currentLiveUploadData: LegacyLiveUploadInterfaceResult?
fileprivate let backgroundView: UIVisualEffectView
fileprivate let containerView: UIView
fileprivate let componentHost: ComponentView<ViewControllerComponentContainer.Environment>
@ -689,16 +689,27 @@ public class VideoMessageCameraScreen: ViewController {
}
func withReadyCamera(isFirstTime: Bool = false, _ f: @escaping () -> Void) {
guard let controller = self.controller else {
return
}
if #available(iOS 13.0, *) {
let _ = ((self.cameraState.isDualCameraEnabled ? self.additionalPreviewView.isPreviewing : self.mainPreviewView.isPreviewing)
|> filter { $0 }
|> take(1)).startStandalone(next: { _ in
let _ = (combineLatest(queue: Queue.mainQueue(),
self.cameraState.isDualCameraEnabled ? self.additionalPreviewView.isPreviewing : self.mainPreviewView.isPreviewing,
controller.audioSessionReady.get()
)
|> filter { $0 && $1 }
|> take(1)).startStandalone(next: { _, _ in
f()
})
} else {
Queue.mainQueue().after(0.35) {
let _ = (combineLatest(queue: Queue.mainQueue(),
.single(true) |> delay(0.35, queue: Queue.mainQueue()),
controller.audioSessionReady.get()
)
|> filter { $0 && $1 }
|> take(1)).startStandalone(next: { _, _ in
f()
}
})
}
}
@ -1241,6 +1252,7 @@ public class VideoMessageCameraScreen: ViewController {
fileprivate let completion: (EnqueueMessage?, Bool?, Int32?) -> Void
private var audioSessionDisposable: Disposable?
fileprivate let audioSessionReady = ValuePromise<Bool>(false)
private let hapticFeedback = HapticFeedback()
@ -1484,11 +1496,13 @@ public class VideoMessageCameraScreen: ViewController {
finalDuration = duration
}
let dimensions = PixelDimensions(width: 400, height: 400)
var thumbnailImage = video.thumbnail
if startTime > 0.0 {
let composition = composition(with: results)
let imageGenerator = AVAssetImageGenerator(asset: composition)
imageGenerator.maximumSize = CGSize(width: 400, height: 400)
imageGenerator.maximumSize = dimensions.cgSize
imageGenerator.appliesPreferredTrackTransform = true
if let cgImage = try? imageGenerator.copyCGImage(at: CMTime(seconds: startTime, preferredTimescale: composition.duration.timescale), actualTime: nil) {
@ -1496,7 +1510,7 @@ public class VideoMessageCameraScreen: ViewController {
}
}
let values = MediaEditorValues(peerId: self.context.account.peerId, originalDimensions: PixelDimensions(width: 400, height: 400), cropOffset: .zero, cropRect: CGRect(origin: .zero, size: CGSize(width: 400.0, height: 400.0)), cropScale: 1.0, cropRotation: 0.0, cropMirroring: false, cropOrientation: nil, gradientColors: nil, videoTrimRange: self.node.previewState?.trimRange, videoIsMuted: false, videoIsFullHd: false, videoIsMirrored: false, videoVolume: nil, additionalVideoPath: nil, additionalVideoIsDual: false, additionalVideoPosition: nil, additionalVideoScale: nil, additionalVideoRotation: nil, additionalVideoPositionChanges: [], additionalVideoTrimRange: nil, additionalVideoOffset: nil, additionalVideoVolume: nil, nightTheme: false, drawing: nil, entities: [], toolValues: [:], audioTrack: nil, audioTrackTrimRange: nil, audioTrackOffset: nil, audioTrackVolume: nil, audioTrackSamples: nil, qualityPreset: .videoMessage)
let values = MediaEditorValues(peerId: self.context.account.peerId, originalDimensions: dimensions, cropOffset: .zero, cropRect: CGRect(origin: .zero, size: dimensions.cgSize), cropScale: 1.0, cropRotation: 0.0, cropMirroring: false, cropOrientation: nil, gradientColors: nil, videoTrimRange: self.node.previewState?.trimRange, videoIsMuted: false, videoIsFullHd: false, videoIsMirrored: false, videoVolume: nil, additionalVideoPath: nil, additionalVideoIsDual: false, additionalVideoPosition: nil, additionalVideoScale: nil, additionalVideoRotation: nil, additionalVideoPositionChanges: [], additionalVideoTrimRange: nil, additionalVideoOffset: nil, additionalVideoVolume: nil, nightTheme: false, drawing: nil, entities: [], toolValues: [:], audioTrack: nil, audioTrackTrimRange: nil, audioTrackOffset: nil, audioTrackVolume: nil, audioTrackSamples: nil, qualityPreset: .videoMessage)
var resourceAdjustments: VideoMediaResourceAdjustments? = nil
if let valuesData = try? JSONEncoder().encode(values) {
@ -1614,10 +1628,13 @@ public class VideoMessageCameraScreen: ViewController {
}
private func requestAudioSession() {
self.audioSessionDisposable = self.context.sharedContext.mediaManager.audioSession.push(audioSessionType: .recordWithOthers, activate: { _ in
self.audioSessionDisposable = self.context.sharedContext.mediaManager.audioSession.push(audioSessionType: .recordWithOthers, activate: { [weak self] _ in
if #available(iOS 13.0, *) {
try? AVAudioSession.sharedInstance().setAllowHapticsAndSystemSoundsDuringRecording(true)
}
if let self {
self.audioSessionReady.set(true)
}
}, deactivate: { _ in
return .single(Void())
})

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "premiumstar_16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,97 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.494995 cm
0.000000 0.000000 0.000000 scn
7.573102 2.542415 m
3.972436 0.336632 l
3.598035 0.107271 3.108589 0.224851 2.879229 0.599252 c
2.767209 0.782110 2.733811 1.002467 2.786615 1.210307 c
3.343997 3.404178 l
3.545203 4.196128 4.087134 4.858135 4.823744 5.211795 c
8.751891 7.097767 l
8.935022 7.185692 9.012203 7.405426 8.924278 7.588558 c
8.853073 7.736866 8.692046 7.819856 8.529942 7.791792 c
4.157411 7.034797 l
3.268577 6.880917 2.357086 7.126360 1.665707 7.705756 c
0.284388 8.863339 l
-0.052136 9.145357 -0.096324 9.646784 0.185694 9.983309 c
0.322857 10.146982 0.520100 10.248593 0.732998 10.265255 c
4.953338 10.595538 l
5.251494 10.618872 5.511330 10.807558 5.625789 11.083856 c
7.253917 15.014055 l
7.421958 15.419697 7.887019 15.612309 8.292661 15.444268 c
8.487435 15.363581 8.642185 15.208831 8.722873 15.014055 c
10.351001 11.083856 l
10.465460 10.807558 10.725295 10.618872 11.023451 10.595538 c
15.266980 10.263440 l
15.704712 10.229183 16.031794 9.846561 15.997537 9.408829 c
15.981057 9.198256 15.881458 9.002894 15.720723 8.865864 c
12.484364 6.106792 l
12.256535 5.912563 12.157140 5.606812 12.227205 5.315742 c
13.222160 1.182478 l
13.324918 0.755602 13.062167 0.326249 12.635291 0.223492 c
12.430174 0.174116 12.213841 0.208297 12.033939 0.318506 c
8.403688 2.542415 l
8.148836 2.698538 7.827954 2.698538 7.573102 2.542415 c
h
f*
n
Q
endstream
endobj
3 0 obj
1440
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 16.000000 16.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001530 00000 n
0000001553 00000 n
0000001726 00000 n
0000001800 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1859
%%EOF

View File

@ -350,11 +350,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
}
}
}
if isFirstTime, !self.viewOnceButton.isHidden {
self.maybePresentViewOnceTooltip()
}
let panelHeight = defaultHeight(metrics: metrics)
transition.updateFrame(node: self.deleteButton, frame: CGRect(origin: CGPoint(x: leftInset + 2.0 - UIScreenPixel, y: 1), size: CGSize(width: 40.0, height: 40)))
@ -488,6 +484,10 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
}
}
if isFirstTime, !self.viewOnceButton.isHidden {
self.maybePresentViewOnceTooltip()
}
return panelHeight
}

View File

@ -126,6 +126,29 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
}
if !pathComponents.isEmpty && !pathComponents[0].isEmpty {
let peerName: String = pathComponents[0]
if pathComponents[0].hasPrefix("+") || pathComponents[0].hasPrefix("%20") {
let component = pathComponents[0].replacingOccurrences(of: "%20", with: "+")
if component.rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789+").inverted) == nil {
var attach: String?
var startAttach: String?
if let queryItems = components.queryItems {
for queryItem in queryItems {
if let value = queryItem.value {
if queryItem.name == "attach" {
attach = value
} else if queryItem.name == "startattach" {
startAttach = value
}
}
}
}
return .phone(component.replacingOccurrences(of: "+", with: ""), attach, startAttach)
} else {
return .join(String(component.dropFirst()))
}
}
if pathComponents.count == 1 {
if let queryItems = components.queryItems {
if peerName == "socks" || peerName == "proxy" {
@ -288,27 +311,6 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
}
} else if pathComponents[0].hasPrefix(phonebookUsernamePathPrefix), let idValue = Int64(String(pathComponents[0][pathComponents[0].index(pathComponents[0].startIndex, offsetBy: phonebookUsernamePathPrefix.count)...])) {
return .peerId(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(idValue)))
} else if pathComponents[0].hasPrefix("+") || pathComponents[0].hasPrefix("%20") {
let component = pathComponents[0].replacingOccurrences(of: "%20", with: "+")
if component.rangeOfCharacter(from: CharacterSet(charactersIn: "0123456789+").inverted) == nil {
var attach: String?
var startAttach: String?
if let queryItems = components.queryItems {
for queryItem in queryItems {
if let value = queryItem.value {
if queryItem.name == "attach" {
attach = value
} else if queryItem.name == "startattach" {
startAttach = value
}
}
}
}
return .phone(component.replacingOccurrences(of: "+", with: ""), attach, startAttach)
} else {
return .join(String(component.dropFirst()))
}
} else if pathComponents[0].hasPrefix("$") || pathComponents[0].hasPrefix("%24") {
var component = pathComponents[0].replacingOccurrences(of: "%24", with: "$")
if component.hasPrefix("$") {