mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Merge commit 'd16e1d9513c49f225fd6aa529e0f160b0bb237d0' into videochats
This commit is contained in:
commit
69aaf87071
@ -114,7 +114,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
||||
|
||||
self.rootPath = rootPath
|
||||
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "siri", launchSpecificId: arc4random64())
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "siri", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
||||
|
||||
let logsPath = rootPath + "/siri-logs"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||
@ -884,7 +884,7 @@ private final class WidgetIntentHandler {
|
||||
|
||||
self.rootPath = rootPath
|
||||
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "siri", launchSpecificId: arc4random64())
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "siri", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
||||
|
||||
let logsPath = rootPath + "/siri-logs"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
@ -92,7 +92,7 @@ private func getCommonTimeline(friends: [Friend]?, in context: TimelineProviderC
|
||||
|
||||
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
||||
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "widget", launchSpecificId: arc4random64())
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "widget", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
||||
|
||||
let logsPath = rootPath + "/widget-logs"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
@ -56,6 +56,7 @@ public enum AnimatedStickerPlaybackPosition {
|
||||
case start
|
||||
case end
|
||||
case timestamp(Double)
|
||||
case frameIndex(Int)
|
||||
}
|
||||
|
||||
public enum AnimatedStickerPlaybackMode {
|
||||
@ -94,6 +95,7 @@ public protocol AnimatedStickerFrameSource: class {
|
||||
|
||||
func takeFrame(draw: Bool) -> AnimatedStickerFrame?
|
||||
func skipToEnd()
|
||||
func skipToFrameIndex(_ index: Int)
|
||||
}
|
||||
|
||||
private final class AnimatedStickerFrameSourceWrapper {
|
||||
@ -271,6 +273,9 @@ public final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource
|
||||
|
||||
public func skipToEnd() {
|
||||
}
|
||||
|
||||
public func skipToFrameIndex(_ index: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
private func wrappedWrite(_ fd: Int32, _ data: UnsafeRawPointer, _ count: Int) -> Int {
|
||||
@ -656,6 +661,10 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource
|
||||
func skipToEnd() {
|
||||
self.currentFrame = self.frameCount - 1
|
||||
}
|
||||
|
||||
func skipToFrameIndex(_ index: Int) {
|
||||
self.currentFrame = index
|
||||
}
|
||||
}
|
||||
|
||||
public final class AnimatedStickerFrameQueue {
|
||||
@ -748,6 +757,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
|
||||
public var completed: (Bool) -> Void = { _ in }
|
||||
public var frameUpdated: (Int, Int) -> Void = { _, _ in }
|
||||
public private(set) var currentFrameIndex: Int = 0
|
||||
private var playFromIndex: Int?
|
||||
|
||||
private let timer = Atomic<SwiftSignalKit.Timer?>(value: nil)
|
||||
private let frameSource = Atomic<QueueLocalObject<AnimatedStickerFrameSourceWrapper>?>(value: nil)
|
||||
@ -842,7 +853,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
strongSelf.isSetUpForPlayback = false
|
||||
strongSelf.isPlaying = true
|
||||
}
|
||||
strongSelf.play()
|
||||
var fromIndex = strongSelf.playFromIndex
|
||||
strongSelf.playFromIndex = nil
|
||||
strongSelf.play(fromIndex: fromIndex)
|
||||
} else if strongSelf.canDisplayFirstFrame {
|
||||
strongSelf.play(firstFrame: true)
|
||||
}
|
||||
@ -911,7 +924,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
|
||||
private var isSetUpForPlayback = false
|
||||
|
||||
public func play(firstFrame: Bool = false) {
|
||||
public func play(firstFrame: Bool = false, fromIndex: Int? = nil) {
|
||||
switch self.playbackMode {
|
||||
case .once:
|
||||
self.isPlaying = true
|
||||
@ -949,6 +962,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
guard let frameSource = maybeFrameSource else {
|
||||
return
|
||||
}
|
||||
if let fromIndex = fromIndex {
|
||||
frameSource.skipToFrameIndex(fromIndex)
|
||||
}
|
||||
let frameQueue = QueueLocalObject<AnimatedStickerFrameQueue>(queue: queue, generate: {
|
||||
return AnimatedStickerFrameQueue(queue: queue, length: 1, source: frameSource)
|
||||
})
|
||||
@ -978,6 +994,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
})
|
||||
|
||||
strongSelf.frameUpdated(frame.index, frame.totalFrames)
|
||||
strongSelf.currentFrameIndex = frame.index
|
||||
|
||||
if frame.isLastFrame {
|
||||
var stopped = false
|
||||
@ -1016,6 +1033,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
self.isSetUpForPlayback = true
|
||||
let directData = self.directData
|
||||
let cachedData = self.cachedData
|
||||
if directData == nil && cachedData == nil {
|
||||
self.playFromIndex = fromIndex
|
||||
}
|
||||
let queue = self.queue
|
||||
let timerHolder = self.timer
|
||||
let frameSourceHolder = self.frameSource
|
||||
@ -1039,6 +1059,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
guard let frameSource = maybeFrameSource else {
|
||||
return
|
||||
}
|
||||
if let fromIndex = fromIndex {
|
||||
frameSource.skipToFrameIndex(fromIndex)
|
||||
}
|
||||
let frameQueue = QueueLocalObject<AnimatedStickerFrameQueue>(queue: queue, generate: {
|
||||
return AnimatedStickerFrameQueue(queue: queue, length: 1, source: frameSource)
|
||||
})
|
||||
@ -1068,6 +1091,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
})
|
||||
|
||||
strongSelf.frameUpdated(frame.index, frame.totalFrames)
|
||||
strongSelf.currentFrameIndex = frame.index
|
||||
|
||||
if frame.isLastFrame {
|
||||
var stopped = false
|
||||
@ -1163,6 +1187,21 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
|
||||
var delta = targetFrame - frameSource.frameIndex
|
||||
if delta < 0 {
|
||||
delta = frameSource.frameCount + delta
|
||||
}
|
||||
for i in 0 ..< delta {
|
||||
maybeFrame = frameQueue.syncWith { frameQueue in
|
||||
return frameQueue.take(draw: i == delta - 1)
|
||||
}
|
||||
}
|
||||
} else if case let .frameIndex(frameIndex) = position {
|
||||
let targetFrame = frameIndex
|
||||
if targetFrame == frameSource.frameIndex {
|
||||
return
|
||||
}
|
||||
|
||||
var delta = targetFrame - frameSource.frameIndex
|
||||
if delta < 0 {
|
||||
delta = frameSource.frameCount + delta
|
||||
|
||||
@ -1045,7 +1045,7 @@
|
||||
CGFloat baselineNudge = (lineHeight - fontLineHeight) * 0.6f;
|
||||
|
||||
CGRect rect = *lineFragmentRect;
|
||||
rect.size.height = lineHeight;
|
||||
rect.size.height = lineHeight + 2.0f;
|
||||
|
||||
CGRect usedRect = *lineFragmentUsedRect;
|
||||
usedRect.size.height = MAX(lineHeight, usedRect.size.height);
|
||||
|
||||
@ -155,6 +155,316 @@ private final class TipValueNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private final class FormatterImpl: NSObject, UITextFieldDelegate {
|
||||
private struct Representation {
|
||||
private let format: CurrencyFormat
|
||||
private var caretIndex: Int = 0
|
||||
private var wholePart: [Int] = []
|
||||
private var decimalPart: [Int] = []
|
||||
|
||||
init(string: String, format: CurrencyFormat) {
|
||||
self.format = format
|
||||
|
||||
var isDecimalPart = false
|
||||
for c in string {
|
||||
if c.isNumber {
|
||||
if let value = Int(String(c)) {
|
||||
if isDecimalPart {
|
||||
self.decimalPart.append(value)
|
||||
} else {
|
||||
self.wholePart.append(value)
|
||||
}
|
||||
}
|
||||
} else if String(c) == format.decimalSeparator {
|
||||
isDecimalPart = true
|
||||
}
|
||||
}
|
||||
|
||||
while self.wholePart.count > 1 {
|
||||
if self.wholePart[0] != 0 {
|
||||
break
|
||||
} else {
|
||||
self.wholePart.removeFirst()
|
||||
}
|
||||
}
|
||||
if self.wholePart.isEmpty {
|
||||
self.wholePart = [0]
|
||||
}
|
||||
|
||||
while self.decimalPart.count > 1 {
|
||||
if self.decimalPart[self.decimalPart.count - 1] != 0 {
|
||||
break
|
||||
} else {
|
||||
self.decimalPart.removeLast()
|
||||
}
|
||||
}
|
||||
while self.decimalPart.count < format.decimalDigits {
|
||||
self.decimalPart.append(0)
|
||||
}
|
||||
|
||||
self.caretIndex = self.wholePart.count
|
||||
}
|
||||
|
||||
var minCaretIndex: Int {
|
||||
for i in 0 ..< self.wholePart.count {
|
||||
if self.wholePart[i] != 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return self.wholePart.count
|
||||
}
|
||||
|
||||
mutating func moveCaret(offset: Int) {
|
||||
self.caretIndex = max(self.minCaretIndex, min(self.caretIndex + offset, self.wholePart.count + self.decimalPart.count))
|
||||
}
|
||||
|
||||
mutating func normalize() {
|
||||
while self.wholePart.count > 1 {
|
||||
if self.wholePart[0] != 0 {
|
||||
break
|
||||
} else {
|
||||
self.wholePart.removeFirst()
|
||||
self.moveCaret(offset: -1)
|
||||
}
|
||||
}
|
||||
if self.wholePart.isEmpty {
|
||||
self.wholePart = [0]
|
||||
}
|
||||
|
||||
while self.decimalPart.count < format.decimalDigits {
|
||||
self.decimalPart.append(0)
|
||||
}
|
||||
while self.decimalPart.count > format.decimalDigits {
|
||||
self.decimalPart.removeLast()
|
||||
}
|
||||
|
||||
self.caretIndex = max(self.minCaretIndex, min(self.caretIndex, self.wholePart.count + self.decimalPart.count))
|
||||
}
|
||||
|
||||
mutating func backspace() {
|
||||
if self.caretIndex > self.wholePart.count {
|
||||
let decimalIndex = self.caretIndex - self.wholePart.count
|
||||
if decimalIndex > 0 {
|
||||
self.decimalPart.remove(at: decimalIndex - 1)
|
||||
|
||||
self.moveCaret(offset: -1)
|
||||
self.normalize()
|
||||
}
|
||||
} else {
|
||||
if self.caretIndex > 0 {
|
||||
self.wholePart.remove(at: self.caretIndex - 1)
|
||||
|
||||
self.moveCaret(offset: -1)
|
||||
self.normalize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutating func insert(letter: String) {
|
||||
if letter == "." || letter == "," {
|
||||
if self.caretIndex == self.wholePart.count {
|
||||
return
|
||||
} else if self.caretIndex < self.wholePart.count {
|
||||
for i in (self.caretIndex ..< self.wholePart.count).reversed() {
|
||||
self.decimalPart.insert(self.wholePart[i], at: 0)
|
||||
self.wholePart.remove(at: i)
|
||||
}
|
||||
}
|
||||
|
||||
self.normalize()
|
||||
} else if letter.count == 1 && letter[letter.startIndex].isNumber {
|
||||
if let value = Int(letter) {
|
||||
if self.caretIndex <= self.wholePart.count {
|
||||
self.wholePart.insert(value, at: self.caretIndex)
|
||||
} else {
|
||||
let decimalIndex = self.caretIndex - self.wholePart.count
|
||||
self.decimalPart.insert(value, at: decimalIndex)
|
||||
}
|
||||
self.moveCaret(offset: 1)
|
||||
self.normalize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var string: String {
|
||||
var result = ""
|
||||
|
||||
for digit in self.wholePart {
|
||||
result.append("\(digit)")
|
||||
}
|
||||
result.append(self.format.decimalSeparator)
|
||||
for digit in self.decimalPart {
|
||||
result.append("\(digit)")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
var stringCaretIndex: Int {
|
||||
var logicalIndex = 0
|
||||
var resolvedIndex = 0
|
||||
|
||||
if logicalIndex == self.caretIndex {
|
||||
return resolvedIndex
|
||||
}
|
||||
|
||||
for _ in self.wholePart {
|
||||
logicalIndex += 1
|
||||
resolvedIndex += 1
|
||||
|
||||
if logicalIndex == self.caretIndex {
|
||||
return resolvedIndex
|
||||
}
|
||||
}
|
||||
|
||||
resolvedIndex += 1
|
||||
|
||||
for _ in self.decimalPart {
|
||||
logicalIndex += 1
|
||||
resolvedIndex += 1
|
||||
|
||||
if logicalIndex == self.caretIndex {
|
||||
return resolvedIndex
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedIndex
|
||||
}
|
||||
|
||||
var numericalValue: Int64 {
|
||||
var result: Int64 = 0
|
||||
|
||||
for digit in self.wholePart {
|
||||
result *= 10
|
||||
result += Int64(digit)
|
||||
}
|
||||
for digit in self.decimalPart {
|
||||
result *= 10
|
||||
result += Int64(digit)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private let format: CurrencyFormat
|
||||
private let currency: String
|
||||
private let maxNumericalValue: Int64
|
||||
private let updated: (Int64) -> Void
|
||||
private let focusUpdated: (Bool) -> Void
|
||||
|
||||
private var representation: Representation
|
||||
|
||||
private var previousResolvedCaretIndex: Int = 0
|
||||
private var ignoreTextSelection: Bool = false
|
||||
private var enableTextSelectionProcessing: Bool = false
|
||||
|
||||
init?(textField: UITextField, currency: String, maxNumericalValue: Int64, initialValue: String, updated: @escaping (Int64) -> Void, focusUpdated: @escaping (Bool) -> Void) {
|
||||
guard let format = CurrencyFormat(currency: currency) else {
|
||||
return nil
|
||||
}
|
||||
self.format = format
|
||||
self.currency = currency
|
||||
self.maxNumericalValue = maxNumericalValue
|
||||
self.updated = updated
|
||||
self.focusUpdated = focusUpdated
|
||||
|
||||
self.representation = Representation(string: initialValue, format: format)
|
||||
|
||||
super.init()
|
||||
|
||||
textField.text = self.representation.string
|
||||
self.previousResolvedCaretIndex = self.representation.stringCaretIndex
|
||||
}
|
||||
|
||||
func reset(textField: UITextField, initialValue: String) {
|
||||
self.representation = Representation(string: initialValue, format: self.format)
|
||||
self.resetFromRepresentation(textField: textField, notifyUpdated: false)
|
||||
}
|
||||
|
||||
private func resetFromRepresentation(textField: UITextField, notifyUpdated: Bool) {
|
||||
self.ignoreTextSelection = true
|
||||
|
||||
if self.representation.numericalValue > self.maxNumericalValue {
|
||||
self.representation = Representation(string: formatCurrencyAmountCustom(self.maxNumericalValue, currency: self.currency).0, format: self.format)
|
||||
}
|
||||
|
||||
textField.text = self.representation.string
|
||||
self.previousResolvedCaretIndex = self.representation.stringCaretIndex
|
||||
|
||||
if self.enableTextSelectionProcessing {
|
||||
let stringCaretIndex = self.representation.stringCaretIndex
|
||||
if let caretPosition = textField.position(from: textField.beginningOfDocument, offset: stringCaretIndex) {
|
||||
textField.selectedTextRange = textField.textRange(from: caretPosition, to: caretPosition)
|
||||
}
|
||||
}
|
||||
self.ignoreTextSelection = false
|
||||
|
||||
if notifyUpdated {
|
||||
self.updated(self.representation.numericalValue)
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
if string.count == 1 {
|
||||
self.representation.insert(letter: string)
|
||||
self.resetFromRepresentation(textField: textField, notifyUpdated: true)
|
||||
} else if string.count == 0 {
|
||||
self.representation.backspace()
|
||||
self.resetFromRepresentation(textField: textField, notifyUpdated: true)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@objc public func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
self.enableTextSelectionProcessing = true
|
||||
self.focusUpdated(true)
|
||||
|
||||
let stringCaretIndex = self.representation.stringCaretIndex
|
||||
self.previousResolvedCaretIndex = stringCaretIndex
|
||||
if let caretPosition = textField.position(from: textField.beginningOfDocument, offset: stringCaretIndex) {
|
||||
self.ignoreTextSelection = true
|
||||
textField.selectedTextRange = textField.textRange(from: caretPosition, to: caretPosition)
|
||||
DispatchQueue.main.async {
|
||||
textField.selectedTextRange = textField.textRange(from: caretPosition, to: caretPosition)
|
||||
self.ignoreTextSelection = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func textFieldDidChangeSelection(_ textField: UITextField) {
|
||||
if self.ignoreTextSelection {
|
||||
return
|
||||
}
|
||||
if !self.enableTextSelectionProcessing {
|
||||
return
|
||||
}
|
||||
|
||||
if let selectedTextRange = textField.selectedTextRange {
|
||||
let index = textField.offset(from: textField.beginningOfDocument, to: selectedTextRange.end)
|
||||
if self.previousResolvedCaretIndex != index {
|
||||
self.representation.moveCaret(offset: self.previousResolvedCaretIndex < index ? 1 : -1)
|
||||
|
||||
let stringCaretIndex = self.representation.stringCaretIndex
|
||||
self.previousResolvedCaretIndex = stringCaretIndex
|
||||
if let caretPosition = textField.position(from: textField.beginningOfDocument, offset: stringCaretIndex) {
|
||||
textField.selectedTextRange = textField.textRange(from: caretPosition, to: caretPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc public func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
self.enableTextSelectionProcessing = false
|
||||
self.focusUpdated(false)
|
||||
}
|
||||
}
|
||||
|
||||
class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
let titleNode: TextNode
|
||||
@ -167,8 +477,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
private var valueNodes: [TipValueNode] = []
|
||||
|
||||
private var item: BotCheckoutTipItem?
|
||||
|
||||
private var formatterDelegate: CurrencyUITextFieldDelegate?
|
||||
private var formatter: FormatterImpl?
|
||||
|
||||
init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
@ -178,6 +487,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
|
||||
self.labelNode = TextNode()
|
||||
self.labelNode.isUserInteractionEnabled = false
|
||||
self.labelNode.isHidden = true
|
||||
|
||||
self.tipMeasurementNode = ImmediateTextNode()
|
||||
self.tipCurrencyNode = ImmediateTextNode()
|
||||
@ -248,8 +558,25 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((labelsContentHeight - titleLayout.size.height) / 2.0)), size: titleLayout.size)
|
||||
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: params.width - leftInset - labelLayout.size.width, y: floor((labelsContentHeight - labelLayout.size.height) / 2.0)), size: labelLayout.size)
|
||||
|
||||
if strongSelf.formatterDelegate == nil {
|
||||
strongSelf.formatterDelegate = CurrencyUITextFieldDelegate(formatter: CurrencyFormatter(currency: item.currency, { formatter in
|
||||
if strongSelf.formatter == nil {
|
||||
strongSelf.formatter = FormatterImpl(textField: strongSelf.textNode.textField, currency: item.currency, maxNumericalValue: item.maxValue, initialValue: item.value, updated: { value in
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
if item.numericValue != value {
|
||||
item.updateValue(value)
|
||||
}
|
||||
}, focusUpdated: { value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if value {
|
||||
strongSelf.item?.updatedFocus(true)
|
||||
}
|
||||
})
|
||||
strongSelf.textNode.textField.delegate = strongSelf.formatter
|
||||
|
||||
/*strongSelf.formatterDelegate = CurrencyUITextFieldDelegate(formatter: CurrencyFormatter(currency: item.currency, { formatter in
|
||||
formatter.maxValue = currencyToFractionalAmount(value: item.maxValue, currency: item.currency) ?? 10000.0
|
||||
formatter.minValue = 0.0
|
||||
formatter.hasDecimals = true
|
||||
@ -263,20 +590,10 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
strongSelf.textFieldTextChanged(strongSelf.textNode.textField)
|
||||
}
|
||||
|
||||
strongSelf.textNode.textField.delegate = strongSelf.formatterDelegate*/
|
||||
|
||||
strongSelf.textNode.clipsToBounds = true
|
||||
strongSelf.textNode.textField.delegate = strongSelf.formatterDelegate
|
||||
|
||||
/*let toolbar: UIToolbar = UIToolbar()
|
||||
toolbar.tintColor = item.theme.rootController.navigationBar.accentTextColor
|
||||
toolbar.barTintColor = item.theme.rootController.navigationBar.backgroundColor
|
||||
toolbar.barStyle = .default
|
||||
toolbar.items = [
|
||||
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil),
|
||||
UIBarButtonItem(title: item.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.dismissKeyboard))
|
||||
]
|
||||
toolbar.sizeToFit()
|
||||
|
||||
strongSelf.textNode.textField.inputAccessoryView = toolbar*/
|
||||
//strongSelf.textNode.textField.delegate = strongSelf
|
||||
}
|
||||
|
||||
strongSelf.textNode.textField.typingAttributes = [NSAttributedString.Key.font: titleFont]
|
||||
@ -297,8 +614,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
//let currencySymbolOnTheLeft = true
|
||||
|
||||
if strongSelf.textNode.textField.text ?? "" != currencyText.0 {
|
||||
strongSelf.textNode.textField.text = currencyText.0
|
||||
strongSelf.labelNode.isHidden = !currencyText.0.isEmpty
|
||||
strongSelf.formatter?.reset(textField: strongSelf.textNode.textField, initialValue: currencyText.0)
|
||||
}
|
||||
|
||||
strongSelf.tipMeasurementNode.attributedText = NSAttributedString(string: currencyText.0, font: titleFont, textColor: textColor)
|
||||
@ -334,10 +650,14 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
}
|
||||
let (nodeMinWidth, nodeApply) = valueNode.update(theme: item.theme, text: variantText, isHighlighted: item.value == variantText, height: valueHeight)
|
||||
valueNode.action = {
|
||||
guard let strongSelf = self else {
|
||||
guard let strongSelf = self, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
strongSelf.item?.updateValue(variantValue)
|
||||
if item.numericValue == variantValue {
|
||||
item.updateValue(0)
|
||||
} else {
|
||||
item.updateValue(variantValue)
|
||||
}
|
||||
}
|
||||
totalMinWidth += nodeMinWidth
|
||||
variantLayouts.append((nodeMinWidth, nodeApply))
|
||||
@ -390,7 +710,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
|
||||
@objc private func textFieldTextChanged(_ textField: UITextField) {
|
||||
let text = textField.text ?? ""
|
||||
self.labelNode.isHidden = !text.isEmpty
|
||||
//self.labelNode.isHidden = !text.isEmpty
|
||||
|
||||
guard let item = self.item else {
|
||||
return
|
||||
@ -401,7 +721,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
var cleanText = ""
|
||||
/*var cleanText = ""
|
||||
for c in text {
|
||||
if c.isNumber {
|
||||
cleanText.append(c)
|
||||
@ -424,7 +744,7 @@ class BotCheckoutTipItemNode: ListViewItemNode, UITextFieldDelegate {
|
||||
}
|
||||
}
|
||||
item.updateValue(value)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
|
||||
@ -2766,7 +2766,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
private func prepareRandomGreetingSticker() {
|
||||
let context = self.context
|
||||
self.preloadedSticker.set(.single(nil)
|
||||
|> then(randomGreetingSticker(account: context.account)
|
||||
|> then(context.engine.stickers.randomGreetingSticker()
|
||||
|> map { item in
|
||||
return item?.file
|
||||
}))
|
||||
|
||||
@ -911,7 +911,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
(strongSelf.navigationController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .window(.root))
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in
|
||||
return .forward(source: id, grouping: .auto, attributes: [])
|
||||
return .forward(source: id, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|> deliverOnMainQueue).start(next: { [weak self] messageIds in
|
||||
if let strongSelf = self {
|
||||
|
||||
@ -881,7 +881,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
foundRemotePeers = (
|
||||
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, true))
|
||||
|> then(
|
||||
searchPeers(account: context.account, query: query)
|
||||
context.engine.peers.searchPeers(query: query)
|
||||
|> map { ($0.0, $0.1, false) }
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
|
||||
@ -825,7 +825,7 @@ public func createPollController(context: AccountContext, peer: Peer, isQuiz: Bo
|
||||
|
||||
dismissImpl?()
|
||||
|
||||
completion(.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaPoll(pollId: MediaId(namespace: Namespaces.Media.LocalPoll, id: arc4random64()), publicity: publicity, kind: kind, text: processPollText(state.text), options: options, correctAnswers: correctAnswers, results: TelegramMediaPollResults(voters: nil, totalVoters: nil, recentVoters: [], solution: resolvedSolution), isClosed: false, deadlineTimeout: deadlineTimeout)), replyToMessageId: nil, localGroupingKey: nil))
|
||||
completion(.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaPoll(pollId: MediaId(namespace: Namespaces.Media.LocalPoll, id: Int64.random(in: Int64.min ... Int64.max)), publicity: publicity, kind: kind, text: processPollText(state.text), options: options, correctAnswers: correctAnswers, results: TelegramMediaPollResults(voters: nil, totalVoters: nil, recentVoters: [], solution: resolvedSolution), isClosed: false, deadlineTimeout: deadlineTimeout)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
})
|
||||
|
||||
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
|
||||
@ -1095,7 +1095,7 @@ public final class ContactListNode: ASDisplayNode {
|
||||
if globalSearch {
|
||||
foundRemoteContacts = foundRemoteContacts
|
||||
|> then(
|
||||
searchPeers(account: context.account, query: query)
|
||||
context.engine.peers.searchPeers(query: query)
|
||||
|> map { ($0.0, $0.1) }
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
|
||||
@ -526,11 +526,10 @@ public class ContactsController: ViewController {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private func prepareRandomGreetingSticker() {
|
||||
let context = self.context
|
||||
self.preloadedSticker.set(.single(nil)
|
||||
|> then(randomGreetingSticker(account: context.account)
|
||||
|> then(context.engine.stickers.randomGreetingSticker()
|
||||
|> map { item in
|
||||
return item?.file
|
||||
}))
|
||||
|
||||
@ -269,7 +269,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
|
||||
if categories.contains(.global) {
|
||||
foundRemoteContacts = .single(previousFoundRemoteContacts.with({ $0 }))
|
||||
|> then(
|
||||
searchPeers(account: context.account, query: query)
|
||||
context.engine.peers.searchPeers(query: query)
|
||||
|> map { ($0.0, $0.1) }
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
|
||||
@ -918,7 +918,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
intermediateCompletion()
|
||||
})
|
||||
contentParentNode.updateAbsoluteRect?(self.contentContainerNode.frame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y + contentContainerOffset.y), self.bounds.size)
|
||||
contentParentNode.applyAbsoluteOffset?(-contentContainerOffset.y, transitionCurve, transitionDuration)
|
||||
contentParentNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: -contentContainerOffset.y), transitionCurve, transitionDuration)
|
||||
|
||||
if let reactionContextNode = self.reactionContextNode {
|
||||
reactionContextNode.animateOut(to: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size), animatingOutToReaction: self.reactionContextNodeIsAnimatingOut)
|
||||
|
||||
@ -69,8 +69,8 @@ private func loadCountryCodes() -> [Country] {
|
||||
private var countryCodes: [Country] = loadCountryCodes()
|
||||
private var countryCodesByPrefix: [String: (Country, Country.CountryCode)] = [:]
|
||||
|
||||
public func loadServerCountryCodes(accountManager: AccountManager, network: Network, completion: @escaping () -> Void) {
|
||||
let _ = (getCountriesList(accountManager: accountManager, network: network, langCode: nil)
|
||||
public func loadServerCountryCodes(accountManager: AccountManager, engine: TelegramEngineUnauthorized, completion: @escaping () -> Void) {
|
||||
let _ = (engine.localization.getCountriesList(accountManager: accountManager, langCode: nil)
|
||||
|> deliverOnMainQueue).start(next: { countries in
|
||||
countryCodes = countries
|
||||
|
||||
@ -93,6 +93,30 @@ public func loadServerCountryCodes(accountManager: AccountManager, network: Netw
|
||||
})
|
||||
}
|
||||
|
||||
public func loadServerCountryCodes(accountManager: AccountManager, engine: TelegramEngine, completion: @escaping () -> Void) {
|
||||
let _ = (engine.localization.getCountriesList(accountManager: accountManager, langCode: nil)
|
||||
|> deliverOnMainQueue).start(next: { countries in
|
||||
countryCodes = countries
|
||||
|
||||
var countriesByPrefix: [String: (Country, Country.CountryCode)] = [:]
|
||||
for country in countries {
|
||||
for code in country.countryCodes {
|
||||
if !code.prefixes.isEmpty {
|
||||
for prefix in code.prefixes {
|
||||
countriesByPrefix["\(code.code)\(prefix)"] = (country, code)
|
||||
}
|
||||
} else {
|
||||
countriesByPrefix[code.code] = (country, code)
|
||||
}
|
||||
}
|
||||
}
|
||||
countryCodesByPrefix = countriesByPrefix
|
||||
Queue.mainQueue().async {
|
||||
completion()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private final class AuthorizationSequenceCountrySelectionNavigationContentNode: NavigationBarContentNode {
|
||||
private let theme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
|
||||
@ -222,12 +222,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: logData.count, isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: logData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
}
|
||||
@ -302,12 +302,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: logData.count, isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: logData.count, attributes: [.FileName(fileName: "Log-iOS-Short.txt")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
}
|
||||
@ -374,12 +374,12 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let fileResource = LocalFileMediaResource(fileId: id, size: logData.count, isSecretRelated: false)
|
||||
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData)
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: logData.count, attributes: [.FileName(fileName: "Log-iOS-Full.txt")])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
|
||||
}
|
||||
@ -424,9 +424,9 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
strongController.dismiss()
|
||||
|
||||
let messages = logs.map { (name, path) -> EnqueueMessage in
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)])
|
||||
return .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
}
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
@ -455,9 +455,9 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
strongController.dismiss()
|
||||
|
||||
let messages = logs.map { (name, path) -> EnqueueMessage in
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)])
|
||||
return .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
}
|
||||
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: messages).start()
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ public final class ContextExtractedContentContainingNode: ASDisplayNode {
|
||||
public var willUpdateIsExtractedToContextPreview: ((Bool, ContainedViewLayoutTransition) -> Void)?
|
||||
public var isExtractedToContextPreviewUpdated: ((Bool) -> Void)?
|
||||
public var updateAbsoluteRect: ((CGRect, CGSize) -> Void)?
|
||||
public var applyAbsoluteOffset: ((CGFloat, ContainedViewLayoutTransitionCurve, Double) -> Void)?
|
||||
public var applyAbsoluteOffset: ((CGPoint, ContainedViewLayoutTransitionCurve, Double) -> Void)?
|
||||
public var applyAbsoluteOffsetSpring: ((CGFloat, Double, CGFloat) -> Void)?
|
||||
public var layoutUpdated: ((CGSize) -> Void)?
|
||||
public var updateDistractionFreeMode: ((Bool) -> Void)?
|
||||
|
||||
@ -1027,6 +1027,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
transition = .animated(duration: duration, curve: .spring)
|
||||
case let .Default(duration):
|
||||
transition = .animated(duration: max(updateSizeAndInsets.duration, duration ?? 0.3), curve: .easeInOut)
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
transition = .animated(duration: duration, curve: .custom(cp1x, cp1y, cp2x, cp2y))
|
||||
}
|
||||
}
|
||||
} else if let scrollToItem = scrollToItem {
|
||||
@ -1040,6 +1042,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
} else {
|
||||
transition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
|
||||
}
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
transition = .animated(duration: duration, curve: .custom(cp1x, cp1y, cp2x, cp2y))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2665,6 +2669,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
scrollToItemTransition = .animated(duration: duration, curve: .spring)
|
||||
case let .Default(duration):
|
||||
scrollToItemTransition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
scrollToItemTransition = .animated(duration: duration, curve: .custom(cp1x, cp1y, cp2x, cp2y))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2751,6 +2757,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
updateSizeAndInsetsTransition = .animated(duration: duration, curve: .spring)
|
||||
case let .Default(duration):
|
||||
updateSizeAndInsetsTransition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
updateSizeAndInsetsTransition = .animated(duration: duration, curve: .custom(cp1x, cp1y, cp2x, cp2y))
|
||||
}
|
||||
}
|
||||
|
||||
@ -2804,6 +2812,20 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
animationDuration = duration
|
||||
|
||||
springAnimation.isAdditive = true
|
||||
animation = springAnimation
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
headerNodesTransition = (.animated(duration: duration, curve: .custom(cp1x, cp1y, cp2x, cp2y)), false, -completeOffset)
|
||||
animationCurve = .custom(cp1x, cp1y, cp2x, cp2y)
|
||||
let springAnimation = CABasicAnimation(keyPath: "sublayerTransform")
|
||||
springAnimation.timingFunction = CAMediaTimingFunction(controlPoints: cp1x, cp1y, cp2x, cp2y)
|
||||
springAnimation.duration = duration * UIView.animationDurationFactor()
|
||||
springAnimation.fromValue = NSValue(caTransform3D: CATransform3DMakeTranslation(0.0, -completeOffset, 0.0))
|
||||
springAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity)
|
||||
springAnimation.isRemovedOnCompletion = true
|
||||
|
||||
animationDuration = duration
|
||||
|
||||
springAnimation.isAdditive = true
|
||||
animation = springAnimation
|
||||
case let .Default(duration):
|
||||
@ -2826,8 +2848,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
self.layer.add(animation, forKey: nil)
|
||||
for itemNode in self.itemNodes {
|
||||
itemNode.applyAbsoluteOffset(value: -completeOffset, animationCurve: animationCurve, duration: animationDuration)
|
||||
itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -completeOffset), animationCurve: animationCurve, duration: animationDuration)
|
||||
}
|
||||
//self.didScrollWithOffset?(-completeOffset, ContainedViewLayoutTransition.animated(duration: animationDuration, curve: animationCurve), nil)
|
||||
}
|
||||
} else {
|
||||
self.visibleSize = updateSizeAndInsets.size
|
||||
@ -2866,7 +2889,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
springAnimation.isAdditive = true
|
||||
self.layer.add(springAnimation, forKey: nil)
|
||||
for itemNode in self.itemNodes {
|
||||
itemNode.applyAbsoluteOffset(value: -completeOffset, animationCurve: .spring, duration: duration)
|
||||
itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -completeOffset), animationCurve: .spring, duration: duration)
|
||||
}
|
||||
} else {
|
||||
if let snapshotView = snapshotView {
|
||||
@ -2993,6 +3016,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
headerNodesTransition = (.animated(duration: duration, curve: .spring), headerNodesTransition.1, headerNodesTransition.2 - offsetOrZero)
|
||||
case let .Default(duration):
|
||||
headerNodesTransition = (.animated(duration: duration ?? 0.3, curve: .easeInOut), true, headerNodesTransition.2 - offsetOrZero)
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
headerNodesTransition = (.animated(duration: duration, curve: .custom(cp1x, cp1y, cp2x, cp2y)), headerNodesTransition.1, headerNodesTransition.2 - offsetOrZero)
|
||||
}
|
||||
for (_, headerNode) in self.itemHeaderNodes {
|
||||
previousItemHeaderNodes.append(headerNode)
|
||||
@ -3065,6 +3090,27 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
animation = springAnimation
|
||||
reverseAnimation = reverseSpringAnimation
|
||||
case let .Custom(duration, cp1x, cp1y, cp2x, cp2y):
|
||||
animationCurve = .custom(cp1x, cp1y, cp2x, cp2y)
|
||||
animationDuration = duration
|
||||
let basicAnimation = CABasicAnimation(keyPath: "sublayerTransform")
|
||||
basicAnimation.timingFunction = CAMediaTimingFunction(controlPoints: cp1x, cp1y, cp2x, cp2y)
|
||||
basicAnimation.duration = duration * UIView.animationDurationFactor()
|
||||
basicAnimation.fromValue = NSValue(caTransform3D: CATransform3DMakeTranslation(0.0, -offset, 0.0))
|
||||
basicAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity)
|
||||
basicAnimation.isRemovedOnCompletion = true
|
||||
basicAnimation.isAdditive = true
|
||||
|
||||
let reverseBasicAnimation = CABasicAnimation(keyPath: "sublayerTransform")
|
||||
reverseBasicAnimation.timingFunction = CAMediaTimingFunction(controlPoints: cp1x, cp1y, cp2x, cp2y)
|
||||
reverseBasicAnimation.duration = duration * UIView.animationDurationFactor()
|
||||
reverseBasicAnimation.fromValue = NSValue(caTransform3D: CATransform3DMakeTranslation(0.0, offset, 0.0))
|
||||
reverseBasicAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity)
|
||||
reverseBasicAnimation.isRemovedOnCompletion = true
|
||||
reverseBasicAnimation.isAdditive = true
|
||||
|
||||
animation = basicAnimation
|
||||
reverseAnimation = reverseBasicAnimation
|
||||
case let .Default(duration):
|
||||
if let duration = duration {
|
||||
animationCurve = .easeInOut
|
||||
@ -3122,11 +3168,12 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
self.layer.add(animation, forKey: nil)
|
||||
for itemNode in self.itemNodes {
|
||||
itemNode.applyAbsoluteOffset(value: -offset, animationCurve: animationCurve, duration: animationDuration)
|
||||
itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -offset), animationCurve: animationCurve, duration: animationDuration)
|
||||
}
|
||||
for itemNode in temporaryPreviousNodes {
|
||||
itemNode.applyAbsoluteOffset(value: -offset, animationCurve: animationCurve, duration: animationDuration)
|
||||
itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -offset), animationCurve: animationCurve, duration: animationDuration)
|
||||
}
|
||||
self.didScrollWithOffset?(offset, .animated(duration: animationDuration, curve: animationCurve), nil)
|
||||
if let verticalScrollIndicator = self.verticalScrollIndicator {
|
||||
verticalScrollIndicator.layer.add(reverseAnimation, forKey: nil)
|
||||
}
|
||||
|
||||
@ -183,27 +183,19 @@ public final class ListViewAnimation {
|
||||
}
|
||||
|
||||
public func listViewAnimationDurationAndCurve(transition: ContainedViewLayoutTransition) -> (Double, ListViewAnimationCurve) {
|
||||
var duration: Double = 0.0
|
||||
var curve: UInt = 0
|
||||
switch transition {
|
||||
case .immediate:
|
||||
break
|
||||
return (0.0, .Default(duration: 0.0))
|
||||
case let .animated(animationDuration, animationCurve):
|
||||
duration = animationDuration
|
||||
switch animationCurve {
|
||||
case .linear, .easeInOut, .custom:
|
||||
break
|
||||
case .spring:
|
||||
curve = 7
|
||||
case .linear:
|
||||
return (animationDuration, .Default(duration: animationDuration))
|
||||
case .easeInOut:
|
||||
return (animationDuration, .Default(duration: animationDuration))
|
||||
case .spring:
|
||||
return (animationDuration, .Spring(duration: animationDuration))
|
||||
case let .custom(c1x, c1y, c2x, c2y):
|
||||
return (animationDuration, .Custom(duration: animationDuration, c1x, c1y, c2x, c2y))
|
||||
}
|
||||
}
|
||||
|
||||
let listViewCurve: ListViewAnimationCurve
|
||||
if curve == 7 {
|
||||
listViewCurve = .Spring(duration: duration)
|
||||
} else {
|
||||
listViewCurve = .Default(duration: duration)
|
||||
}
|
||||
|
||||
return (duration, listViewCurve)
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ public enum ListViewScrollToItemDirectionHint {
|
||||
public enum ListViewAnimationCurve {
|
||||
case Spring(duration: Double)
|
||||
case Default(duration: Double?)
|
||||
case Custom(duration: Double, Float, Float, Float, Float)
|
||||
}
|
||||
|
||||
public struct ListViewScrollToItem {
|
||||
|
||||
@ -556,10 +556,10 @@ open class ListViewItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
||||
open func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||
}
|
||||
|
||||
open func applyAbsoluteOffset(value: CGFloat, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
|
||||
open func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
|
||||
if let extractedBackgroundNode = self.extractedBackgroundNode {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: duration, curve: animationCurve)
|
||||
transition.animatePositionAdditive(node: extractedBackgroundNode, offset: CGPoint(x: 0.0, y: -value))
|
||||
transition.animatePositionAdditive(node: extractedBackgroundNode, offset: CGPoint(x: -value.x, y: -value.y))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -353,7 +353,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|> delay(0.15, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
let signal = stickerPacksAttachedToMedia(account: context.account, media: media)
|
||||
let signal = context.engine.stickers.stickerPacksAttachedToMedia(media: media)
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
|
||||
@ -1637,7 +1637,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|
||||
self.isInteractingPromise.set(true)
|
||||
|
||||
let signal = stickerPacksAttachedToMedia(account: self.context.account, media: media)
|
||||
let signal = self.context.engine.stickers.stickerPacksAttachedToMedia(media: media)
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
|
||||
@ -349,7 +349,7 @@ public final class SecretMediaPreviewController: ViewController {
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
if let strongSelf = self, strongSelf.traceVisibility() {
|
||||
if strongSelf.messageId.peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil)]).start()
|
||||
let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start()
|
||||
} else if strongSelf.messageId.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
let _ = addSecretChatMessageScreenshot(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId).start()
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ final class InstantPageFeedbackNode: ASDisplayNode, InstantPageNode {
|
||||
}
|
||||
|
||||
@objc func buttonPressed() {
|
||||
self.resolveDisposable.set((resolvePeerByName(account: self.context.account, name: "previews") |> deliverOnMainQueue).start(next: { [weak self] peerId in
|
||||
self.resolveDisposable.set((self.context.engine.peers.resolvePeerByName(name: "previews") |> deliverOnMainQueue).start(next: { [weak self] peerId in
|
||||
if let strongSelf = self, let _ = peerId, let webPageId = strongSelf.webPage.id?.id {
|
||||
strongSelf.openUrl(InstantPageUrlItem(url: "https://t.me/previews?start=webpage\(webPageId)", webpageId: nil))
|
||||
}
|
||||
|
||||
@ -147,10 +147,11 @@ final class InstantPagePeerReferenceNode: ASDisplayNode, InstantPageNode {
|
||||
self.joinNode.addTarget(self, action: #selector(self.joinPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
let account = self.context.account
|
||||
let context = self.context
|
||||
let signal = actualizedPeer(postbox: account.postbox, network: account.network, peer: initialPeer)
|
||||
|> mapToSignal({ peer -> Signal<Peer, NoError> in
|
||||
if let peer = peer as? TelegramChannel, let username = peer.username, peer.accessHash == nil {
|
||||
return .single(peer) |> then(resolvePeerByName(account: account, name: username)
|
||||
return .single(peer) |> then(context.engine.peers.resolvePeerByName(name: username)
|
||||
|> mapToSignal({ peerId -> Signal<Peer, NoError> in
|
||||
if let peerId = peerId {
|
||||
return account.postbox.transaction({ transaction -> Peer in
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
- (CGRect)frameForSendButton;
|
||||
|
||||
- (void)complete;
|
||||
- (void)dismiss;
|
||||
- (void)dismiss:(bool)cancelled;
|
||||
- (bool)stop;
|
||||
|
||||
+ (void)clearStartImage;
|
||||
@ -44,4 +44,7 @@
|
||||
+ (void)requestCameraAccess:(void (^)(bool granted, bool wasNotDetermined))resultBlock;
|
||||
+ (void)requestMicrophoneAccess:(void (^)(bool granted, bool wasNotDetermined))resultBlock;
|
||||
|
||||
- (UIView *)extractVideoContent;
|
||||
- (void)hideVideoContent;
|
||||
|
||||
@end
|
||||
|
||||
@ -249,7 +249,7 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
||||
_innerCircleView.center = centerPoint;
|
||||
_outerCircleView.center = centerPoint;
|
||||
_decoration.center = centerPoint;
|
||||
_innerIconWrapperView.center = centerPoint;
|
||||
_innerIconWrapperView.center = CGPointMake(_decoration.frame.size.width / 2.0f, _decoration.frame.size.height / 2.0f);
|
||||
|
||||
_lockPanelWrapperView.frame = CGRectMake(floor(centerPoint.x - _lockPanelWrapperView.frame.size.width / 2.0f), floor(centerPoint.y - 122.0f - _lockPanelWrapperView.frame.size.height / 2.0f), _lockPanelWrapperView.frame.size.width, _lockPanelWrapperView.frame.size.height);
|
||||
|
||||
@ -420,8 +420,8 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
||||
_innerIconWrapperView.alpha = 0.0f;
|
||||
_innerIconWrapperView.userInteractionEnabled = false;
|
||||
[_innerIconWrapperView addSubview:_innerIconView];
|
||||
|
||||
[[_presentation view] addSubview:_innerIconWrapperView];
|
||||
|
||||
[_decoration addSubview:_innerIconWrapperView];
|
||||
|
||||
if (_lock == nil) {
|
||||
_stopButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)];
|
||||
@ -448,7 +448,7 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
||||
block();
|
||||
dispatch_async(dispatch_get_main_queue(), block);
|
||||
|
||||
_innerIconWrapperView.transform = CGAffineTransformIdentity;
|
||||
//_innerIconWrapperView.transform = CGAffineTransformIdentity;
|
||||
_innerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
_outerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
_decoration.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
@ -515,11 +515,11 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
||||
_outerCircleView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
if (toSmallSize) {
|
||||
_decoration.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(0.33f, 0.33f), CGAffineTransformMakeTranslation(0, 2 - TGScreenPixel));
|
||||
_innerIconWrapperView.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(0.492f, 0.492f), CGAffineTransformMakeTranslation(-TGScreenPixel, 1));
|
||||
//_innerIconWrapperView.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(0.492f, 0.492f), CGAffineTransformMakeTranslation(-TGScreenPixel, 1));
|
||||
} else {
|
||||
_decoration.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
_decoration.alpha = 0.0;
|
||||
_innerIconWrapperView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
//_innerIconWrapperView.transform = CGAffineTransformMakeScale(0.2f, 0.2f);
|
||||
_innerIconWrapperView.alpha = 0.0f;
|
||||
}
|
||||
_innerCircleView.alpha = 0.0f;
|
||||
@ -864,7 +864,7 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
||||
transform = CGAffineTransformTranslate(transform, _cancelTranslation, 0);
|
||||
|
||||
_innerCircleView.transform = transform;
|
||||
_innerIconWrapperView.transform = transform;
|
||||
//_innerIconWrapperView.transform = transform;
|
||||
_decoration.transform = transform;
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
- (void)stopRunning;
|
||||
|
||||
- (void)startRecording:(NSURL *)url preset:(TGMediaVideoConversionPreset)preset liveUpload:(bool)liveUpload;
|
||||
- (void)stopRecording:(void (^)())completed;
|
||||
- (void)stopRecording:(void (^)(bool))completed;
|
||||
|
||||
- (CGAffineTransform)transformForOrientation:(AVCaptureVideoOrientation)orientation;
|
||||
|
||||
|
||||
@ -135,7 +135,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
||||
{
|
||||
_running = false;
|
||||
|
||||
[self stopRecording:^{}];
|
||||
[self stopRecording:^(__unused bool success) {}];
|
||||
|
||||
[_captureSession stopRunning];
|
||||
[self captureSessionDidStopRunning];
|
||||
@ -300,7 +300,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
||||
|
||||
- (void)captureSessionDidStopRunning
|
||||
{
|
||||
[self stopRecording:^{}];
|
||||
[self stopRecording:^(__unused bool success) {}];
|
||||
[self destroyVideoPipeline];
|
||||
}
|
||||
|
||||
@ -701,7 +701,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
||||
[recorder prepareToRecord];
|
||||
}
|
||||
|
||||
- (void)stopRecording:(void (^)())completed
|
||||
- (void)stopRecording:(void (^)(bool))completed
|
||||
{
|
||||
[[TGVideoCameraPipeline cameraQueue] dispatch:^
|
||||
{
|
||||
@ -709,7 +709,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
||||
{
|
||||
if (_recordingStatus != TGVideoCameraRecordingStatusRecording) {
|
||||
if (completed) {
|
||||
completed();
|
||||
completed(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -721,7 +721,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
||||
[_recorder finishRecording:^{
|
||||
__unused __auto_type description = [self description];
|
||||
if (completed) {
|
||||
completed();
|
||||
completed(true);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
|
||||
@ -658,9 +658,10 @@ typedef enum
|
||||
return;
|
||||
|
||||
[_activityDisposable dispose];
|
||||
[self stopRecording:^{
|
||||
[self stopRecording:^() {
|
||||
TGDispatchOnMainThread(^{
|
||||
[self dismiss:false];
|
||||
//[self dismiss:false];
|
||||
[self description];
|
||||
});
|
||||
}];
|
||||
}
|
||||
@ -955,7 +956,20 @@ typedef enum
|
||||
|
||||
- (void)stopRecording:(void (^)())completed
|
||||
{
|
||||
[_capturePipeline stopRecording:completed];
|
||||
__weak TGVideoMessageCaptureController *weakSelf = self;
|
||||
[_capturePipeline stopRecording:^(bool success) {
|
||||
TGDispatchOnMainThread(^{
|
||||
__strong TGVideoMessageCaptureController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
if (!success) {
|
||||
if (!strongSelf->_dismissed && strongSelf.finishedWithVideo != nil) {
|
||||
strongSelf.finishedWithVideo(nil, nil, 0, 0.0, CGSizeZero, nil, nil, false, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}];
|
||||
[_buttonHandler ignoreEventsFor:1.0f andDisable:true];
|
||||
[_capturePipeline stopRunning];
|
||||
}
|
||||
@ -1015,10 +1029,14 @@ typedef enum
|
||||
}
|
||||
}
|
||||
|
||||
if (!_dismissed && self.finishedWithVideo != nil)
|
||||
if (!_dismissed) {
|
||||
self.finishedWithVideo(url, image, fileSize, duration, dimensions, liveUploadData, adjustments, isSilent, scheduleTimestamp);
|
||||
else
|
||||
} else {
|
||||
[[NSFileManager defaultManager] removeItemAtURL:url error:NULL];
|
||||
if (self.finishedWithVideo != nil) {
|
||||
self.finishedWithVideo(nil, nil, 0, 0.0, CGSizeZero, nil, nil, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImageOrientation)orientationForThumbnailWithTransform:(CGAffineTransform)transform mirrored:(bool)mirrored
|
||||
@ -1501,6 +1519,16 @@ static UIImage *startImage = nil;
|
||||
return CGSizeMake(240.0f, 240.0f);
|
||||
}
|
||||
|
||||
- (UIView *)extractVideoContent {
|
||||
UIView *result = [_circleView snapshotViewAfterScreenUpdates:false];
|
||||
result.frame = [_circleView convertRect:_circleView.bounds toView:nil];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void)hideVideoContent {
|
||||
_circleWrapperView.alpha = 0.02f;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ public final class LegacyLiveUploadInterface: VideoConversionWatcher, TGLiveUplo
|
||||
|
||||
public init(account: Account) {
|
||||
self.account = account
|
||||
self.id = arc4random64()
|
||||
self.id = Int64.random(in: Int64.min ... Int64.max)
|
||||
|
||||
var updateImpl: ((String, Int) -> Void)?
|
||||
super.init(update: { path, size in
|
||||
|
||||
@ -254,7 +254,7 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, String?, [Any]?, String?
|
||||
}
|
||||
}
|
||||
|
||||
public func legacyEnqueueGifMessage(account: Account, data: Data) -> Signal<EnqueueMessage, Void> {
|
||||
public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId: Int64? = nil) -> Signal<EnqueueMessage, Void> {
|
||||
return Signal { subscriber in
|
||||
if let previewImage = UIImage(data: data) {
|
||||
let dimensions = previewImage.size
|
||||
@ -263,7 +263,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data) -> Signal<Enqu
|
||||
let thumbnailSize = dimensions.aspectFitted(CGSize(width: 320.0, height: 320.0))
|
||||
let thumbnailImage = TGScaleImageToPixelSize(previewImage, thumbnailSize)!
|
||||
if let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnailData)
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
}
|
||||
@ -275,7 +275,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data) -> Signal<Enqu
|
||||
let _ = try? FileManager.default.removeItem(atPath: tempFilePath)
|
||||
let _ = try? data.write(to: URL(fileURLWithPath: tempFilePath), options: [.atomic])
|
||||
|
||||
let resource = LocalFileGifMediaResource(randomId: arc4random64(), path: tempFilePath)
|
||||
let resource = LocalFileGifMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: tempFilePath)
|
||||
let fileName: String = "video.mp4"
|
||||
|
||||
let finalDimensions = TGMediaVideoConverter.dimensions(for: dimensions, adjustments: nil, preset: TGMediaVideoConversionPresetAnimation)
|
||||
@ -285,8 +285,8 @@ public func legacyEnqueueGifMessage(account: Account, data: Data) -> Signal<Enqu
|
||||
fileAttributes.append(.FileName(fileName: fileName))
|
||||
fileAttributes.append(.Animated)
|
||||
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: arc4random64()), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
|
||||
subscriber.putNext(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
|
||||
subscriber.putNext(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId))
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
subscriber.putError(Void())
|
||||
@ -296,7 +296,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data) -> Signal<Enqu
|
||||
} |> runOn(Queue.concurrentDefaultQueue())
|
||||
}
|
||||
|
||||
public func legacyEnqueueVideoMessage(account: Account, data: Data) -> Signal<EnqueueMessage, Void> {
|
||||
public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationId: Int64? = nil) -> Signal<EnqueueMessage, Void> {
|
||||
return Signal { subscriber in
|
||||
if let previewImage = UIImage(data: data) {
|
||||
let dimensions = previewImage.size
|
||||
@ -305,7 +305,7 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data) -> Signal<En
|
||||
let thumbnailSize = dimensions.aspectFitted(CGSize(width: 320.0, height: 320.0))
|
||||
let thumbnailImage = TGScaleImageToPixelSize(previewImage, thumbnailSize)!
|
||||
if let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnailData)
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
}
|
||||
@ -317,7 +317,7 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data) -> Signal<En
|
||||
let _ = try? FileManager.default.removeItem(atPath: tempFilePath)
|
||||
let _ = try? data.write(to: URL(fileURLWithPath: tempFilePath), options: [.atomic])
|
||||
|
||||
let resource = LocalFileGifMediaResource(randomId: arc4random64(), path: tempFilePath)
|
||||
let resource = LocalFileGifMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: tempFilePath)
|
||||
let fileName: String = "video.mp4"
|
||||
|
||||
let finalDimensions = TGMediaVideoConverter.dimensions(for: dimensions, adjustments: nil, preset: TGMediaVideoConversionPresetAnimation)
|
||||
@ -327,8 +327,8 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data) -> Signal<En
|
||||
fileAttributes.append(.FileName(fileName: fileName))
|
||||
fileAttributes.append(.Animated)
|
||||
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: arc4random64()), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
|
||||
subscriber.putNext(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
|
||||
subscriber.putNext(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId))
|
||||
subscriber.putCompletion()
|
||||
} else {
|
||||
subscriber.putError(Void())
|
||||
@ -349,7 +349,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
case let .image(data, thumbnail, caption, stickers):
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
if let thumbnail = thumbnail {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
let thumbnailSize = thumbnail.size.aspectFitted(CGSize(width: 320.0, height: 320.0))
|
||||
let thumbnailImage = TGScaleImageToPixelSize(thumbnail, thumbnailSize)!
|
||||
if let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||
@ -391,7 +391,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
}
|
||||
|
||||
var text = caption ?? ""
|
||||
messages.append(.message(text: text, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId))
|
||||
messages.append(.message(text: text, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil))
|
||||
}
|
||||
}
|
||||
case let .asset(asset):
|
||||
@ -399,7 +399,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
arc4random_buf(&randomId, 8)
|
||||
let size = CGSize(width: CGFloat(asset.pixelWidth), height: CGFloat(asset.pixelHeight))
|
||||
let scaledSize = size.aspectFittedOrSmaller(CGSize(width: 1280.0, height: 1280.0))
|
||||
let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64())
|
||||
let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(scaledSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
|
||||
let media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
@ -407,7 +407,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
if let timer = item.timer, timer > 0 && timer <= 60 {
|
||||
attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil))
|
||||
}
|
||||
messages.append(.message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId))
|
||||
messages.append(.message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil))
|
||||
case .tempFile:
|
||||
break
|
||||
}
|
||||
@ -418,13 +418,13 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
arc4random_buf(&randomId, 8)
|
||||
let resource = LocalFileReferenceMediaResource(localFilePath: path, randomId: randomId)
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: nil, attributes: [.FileName(fileName: name)])
|
||||
messages.append(.message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId))
|
||||
messages.append(.message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil))
|
||||
case let .asset(asset):
|
||||
var randomId: Int64 = 0
|
||||
arc4random_buf(&randomId, 8)
|
||||
let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64())
|
||||
let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max))
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: nil, attributes: [.FileName(fileName: name)])
|
||||
messages.append(.message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId))
|
||||
messages.append(.message(text: caption ?? "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil))
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -462,7 +462,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if let thumbnail = thumbnail {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
let thumbnailSize = finalDimensions.aspectFitted(CGSize(width: 320.0, height: 320.0))
|
||||
let thumbnailImage = TGScaleImageToPixelSize(thumbnail, thumbnailSize)!
|
||||
if let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||
@ -505,13 +505,13 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
case let .tempFile(path, _, _):
|
||||
if asFile || (asAnimation && !path.contains(".jpg")) {
|
||||
if let size = fileSize(path) {
|
||||
resource = LocalFileMediaResource(fileId: arc4random64(), size: size)
|
||||
resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max), size: size)
|
||||
account.postbox.mediaBox.moveResourceData(resource.id, fromTempPath: path)
|
||||
} else {
|
||||
continue outer
|
||||
}
|
||||
} else {
|
||||
resource = LocalFileVideoMediaResource(randomId: arc4random64(), path: path, adjustments: resourceAdjustments)
|
||||
resource = LocalFileVideoMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: path, adjustments: resourceAdjustments)
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,12 +547,12 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) -
|
||||
fileAttributes.append(.HasLinkedStickers)
|
||||
}
|
||||
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: arc4random64()), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
|
||||
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
|
||||
|
||||
if let timer = item.timer, timer > 0 && timer <= 60 {
|
||||
attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil))
|
||||
}
|
||||
messages.append(.message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId))
|
||||
messages.append(.message(text: caption ?? "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ public func legacySuggestionContext(context: AccountContext, peerId: PeerId, cha
|
||||
return SSignal.complete()
|
||||
}
|
||||
return SSignal { subscriber in
|
||||
let disposable = (searchEmojiKeywords(postbox: context.account.postbox, inputLanguageCode: inputLanguageCode, query: query, completeMatch: query.count < 3)
|
||||
let disposable = (context.engine.stickers.searchEmojiKeywords(inputLanguageCode: inputLanguageCode, query: query, completeMatch: query.count < 3)
|
||||
|> map { keywords -> [TGAlphacodeEntry] in
|
||||
var result: [TGAlphacodeEntry] = []
|
||||
for keyword in keywords {
|
||||
|
||||
@ -403,7 +403,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
||||
throttledUserLocation(userLocation)
|
||||
|> mapToSignal { location -> Signal<[TelegramMediaMap]?, NoError> in
|
||||
if let location = location, location.horizontalAccuracy > 0 {
|
||||
return combineLatest(nearbyVenues(account: context.account, latitude: location.coordinate.latitude, longitude: location.coordinate.longitude), personalVenues)
|
||||
return combineLatest(nearbyVenues(context: context, latitude: location.coordinate.latitude, longitude: location.coordinate.longitude), personalVenues)
|
||||
|> map { nearbyVenues, personalVenues -> [TelegramMediaMap]? in
|
||||
var resultVenues: [TelegramMediaMap] = []
|
||||
if let personalVenues = personalVenues {
|
||||
@ -431,7 +431,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
||||
if let coordinate = coordinate {
|
||||
return (.single(nil)
|
||||
|> then(
|
||||
nearbyVenues(account: context.account, latitude: coordinate.latitude, longitude: coordinate.longitude)
|
||||
nearbyVenues(context: context, latitude: coordinate.latitude, longitude: coordinate.longitude)
|
||||
|> map { venues -> ([TelegramMediaMap], CLLocation)? in
|
||||
return (venues, CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude))
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ final class LocationSearchContainerNode: ASDisplayNode {
|
||||
}
|
||||
|> mapToSignal { query -> Signal<([LocationSearchEntry], String)?, NoError> in
|
||||
if let query = query, !query.isEmpty {
|
||||
let foundVenues = nearbyVenues(account: context.account, latitude: coordinate.latitude, longitude: coordinate.longitude, query: query)
|
||||
let foundVenues = nearbyVenues(context: context, latitude: coordinate.latitude, longitude: coordinate.longitude, query: query)
|
||||
|> afterCompleted {
|
||||
isSearching.set(false)
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import TelegramStringFormatting
|
||||
import MapKit
|
||||
import AccountContext
|
||||
|
||||
extension TelegramMediaMap {
|
||||
convenience init(coordinate: CLLocationCoordinate2D, liveBroadcastingTimeout: Int32? = nil, proximityNotificationRadius: Int32? = nil) {
|
||||
@ -32,17 +33,17 @@ public func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool
|
||||
return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
|
||||
}
|
||||
|
||||
public func nearbyVenues(account: Account, latitude: Double, longitude: Double, query: String? = nil) -> Signal<[TelegramMediaMap], NoError> {
|
||||
return account.postbox.transaction { transaction -> SearchBotsConfiguration in
|
||||
public func nearbyVenues(context: AccountContext, latitude: Double, longitude: Double, query: String? = nil) -> Signal<[TelegramMediaMap], NoError> {
|
||||
return context.account.postbox.transaction { transaction -> SearchBotsConfiguration in
|
||||
return currentSearchBotsConfiguration(transaction: transaction)
|
||||
} |> mapToSignal { searchBotsConfiguration in
|
||||
return resolvePeerByName(account: account, name: searchBotsConfiguration.venueBotUsername ?? "foursquare")
|
||||
return context.engine.peers.resolvePeerByName(name: searchBotsConfiguration.venueBotUsername ?? "foursquare")
|
||||
|> take(1)
|
||||
|> mapToSignal { peerId -> Signal<ChatContextResultCollection?, NoError> in
|
||||
guard let peerId = peerId else {
|
||||
return .single(nil)
|
||||
}
|
||||
return requestChatContextResults(account: account, botId: peerId, peerId: account.peerId, query: query ?? "", location: .single((latitude, longitude)), offset: "")
|
||||
return requestChatContextResults(account: context.account, botId: peerId, peerId: context.account.peerId, query: query ?? "", location: .single((latitude, longitude)), offset: "")
|
||||
|> map { results -> ChatContextResultCollection? in
|
||||
return results?.results
|
||||
}
|
||||
|
||||
@ -2138,20 +2138,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) {
|
||||
|
||||
NSData *decryptedData = MTAesDecrypt(dataToDecrypt, encryptionKey.key, encryptionKey.iv);
|
||||
|
||||
int32_t messageDataLength = 0;
|
||||
[decryptedData getBytes:&messageDataLength range:NSMakeRange(28, 4)];
|
||||
|
||||
int32_t paddingLength = ((int32_t)decryptedData.length) - messageDataLength;
|
||||
if (paddingLength < 12 || paddingLength > 1024) {
|
||||
__unused NSData *result = MTSha256(decryptedData);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (messageDataLength < 0 || messageDataLength > (int32_t)decryptedData.length) {
|
||||
__unused NSData *result = MTSha256(decryptedData);
|
||||
return nil;
|
||||
}
|
||||
|
||||
int xValue = 8;
|
||||
NSMutableData *msgKeyLargeData = [[NSMutableData alloc] init];
|
||||
[msgKeyLargeData appendBytes:effectiveAuthKey.authKey.bytes + 88 + xValue length:32];
|
||||
@ -2160,8 +2146,21 @@ static NSString *dumpHexString(NSData *data, int maxLength) {
|
||||
NSData *msgKeyLarge = MTSha256(msgKeyLargeData);
|
||||
NSData *messageKey = [msgKeyLarge subdataWithRange:NSMakeRange(8, 16)];
|
||||
|
||||
if (![messageKey isEqualToData:embeddedMessageKey])
|
||||
if (![messageKey isEqualToData:embeddedMessageKey]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
int32_t messageDataLength = 0;
|
||||
[decryptedData getBytes:&messageDataLength range:NSMakeRange(28, 4)];
|
||||
|
||||
int32_t paddingLength = ((int32_t)decryptedData.length) - messageDataLength;
|
||||
if (paddingLength < 12 || paddingLength > 1024) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (messageDataLength < 0 || messageDataLength > (int32_t)decryptedData.length) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return decryptedData;
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ private func processedLegacySecureIdAttachmentItems(postbox: Postbox, signal: SS
|
||||
guard let image = image else {
|
||||
return []
|
||||
}
|
||||
let randomId = arc4random64()
|
||||
let randomId = Int64.random(in: Int64.min ... Int64.max)
|
||||
let tempFilePath = NSTemporaryDirectory() + "\(randomId).jpeg"
|
||||
let scaledSize = image.size.aspectFitted(CGSize(width: 2048.0, height: 2048.0))
|
||||
if let scaledImage = TGScaleImageToPixelSize(image, scaledSize), let scaledImageData = compressImageToJPEG(scaledImage, quality: 0.84) {
|
||||
|
||||
@ -2601,7 +2601,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
}
|
||||
}
|
||||
for resource in resources {
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
innerState.documents.insert(.local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0))), at: addIndex)
|
||||
addIndex += 1
|
||||
}
|
||||
@ -2613,7 +2613,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
innerState = removeDocumentWithId(innerState, id: removeDocumentId)
|
||||
}
|
||||
loop: for resource in resources {
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
innerState.selfieDocument = .local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0)))
|
||||
break loop
|
||||
}
|
||||
@ -2622,7 +2622,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
innerState = removeDocumentWithId(innerState, id: removeDocumentId)
|
||||
}
|
||||
loop: for resource in resources {
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
innerState.frontSideDocument = .local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0)))
|
||||
break loop
|
||||
}
|
||||
@ -2631,7 +2631,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
innerState = removeDocumentWithId(innerState, id: removeDocumentId)
|
||||
}
|
||||
loop: for resource in resources {
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
innerState.backSideDocument = .local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0)))
|
||||
break loop
|
||||
}
|
||||
@ -2647,7 +2647,7 @@ final class SecureIdDocumentFormControllerNode: FormControllerNode<SecureIdDocum
|
||||
}
|
||||
}
|
||||
for resource in resources {
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
innerState.translations.insert(.local(SecureIdVerificationLocalDocument(id: id, resource: SecureIdLocalImageResource(localId: id, source: resource), timestamp: Int32(Date().timeIntervalSince1970), state: .uploading(0.0))), at: addIndex)
|
||||
addIndex += 1
|
||||
}
|
||||
|
||||
@ -732,7 +732,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
|
||||
|
||||
let completedImpl: (UIImage) -> Void = { image in
|
||||
if let data = image.jpegData(compressionQuality: 0.6) {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource, progressiveSizes: [], immediateThumbnailData: nil)
|
||||
updateState {
|
||||
|
||||
@ -682,7 +682,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
||||
foundRemotePeers = .single(([], []))
|
||||
} else {
|
||||
foundContacts = context.account.postbox.searchContacts(query: query.lowercased())
|
||||
foundRemotePeers = .single(([], [])) |> then(searchPeers(account: context.account, query: query)
|
||||
foundRemotePeers = .single(([], [])) |> then(context.engine.peers.searchPeers(query: query)
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue()))
|
||||
}
|
||||
case .searchMembers, .searchBanned, .searchKicked, .searchAdmins:
|
||||
@ -996,7 +996,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
||||
}
|
||||
|
||||
if mode == .banAndPromoteActions || mode == .inviteActions {
|
||||
foundRemotePeers = .single(([], [])) |> then(searchPeers(account: context.account, query: query)
|
||||
foundRemotePeers = .single(([], [])) |> then(context.engine.peers.searchPeers(query: query)
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue()))
|
||||
} else {
|
||||
foundRemotePeers = .single(([], []))
|
||||
|
||||
@ -762,7 +762,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
|
||||
}
|
||||
pushControllerImpl?(controller)
|
||||
}, openChannelExample: {
|
||||
resolveDisposable.set((resolvePeerByName(account: context.account, name: "durov") |> deliverOnMainQueue).start(next: { peerId in
|
||||
resolveDisposable.set((context.engine.peers.resolvePeerByName(name: "durov") |> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
navigateToChatControllerImpl?(peerId)
|
||||
}
|
||||
|
||||
@ -818,9 +818,9 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
}
|
||||
|
||||
let peersDisablingAddressNameAssignment = Promise<[Peer]?>()
|
||||
peersDisablingAddressNameAssignment.set(.single(nil) |> then(context.engine.peerNames.channelAddressNameAssignmentAvailability(peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
||||
peersDisablingAddressNameAssignment.set(.single(nil) |> then(context.engine.peers.channelAddressNameAssignmentAvailability(peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
||||
if case .addressNameLimitReached = result {
|
||||
return context.engine.peerNames.adminedPublicChannels(scope: .all)
|
||||
return context.engine.peers.adminedPublicChannels(scope: .all)
|
||||
|> map(Optional.init)
|
||||
} else {
|
||||
return .single([])
|
||||
@ -871,7 +871,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
return state.withUpdatedEditingPublicLinkText(text)
|
||||
}
|
||||
|
||||
checkAddressNameDisposable.set((context.engine.peerNames.validateAddressNameInteractive(domain: .peer(peerId), name: text)
|
||||
checkAddressNameDisposable.set((context.engine.peers.validateAddressNameInteractive(domain: .peer(peerId), name: text)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
updateState { state in
|
||||
return state.withUpdatedAddressNameValidationStatus(result)
|
||||
@ -893,7 +893,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
return state.withUpdatedRevokingPeerId(peerId)
|
||||
}
|
||||
|
||||
revokeAddressNameDisposable.set((context.engine.peerNames.updateAddressName(domain: .peer(peerId), name: nil) |> deliverOnMainQueue).start(error: { _ in
|
||||
revokeAddressNameDisposable.set((context.engine.peers.updateAddressName(domain: .peer(peerId), name: nil) |> deliverOnMainQueue).start(error: { _ in
|
||||
updateState { state in
|
||||
return state.withUpdatedRevokingPeerId(nil)
|
||||
}
|
||||
@ -1101,7 +1101,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
}
|
||||
_ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(accountManager: context.sharedContext.accountManager).start()
|
||||
|
||||
updateAddressNameDisposable.set((context.engine.peerNames.updateAddressName(domain: .peer(peerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic))
|
||||
updateAddressNameDisposable.set((context.engine.peers.updateAddressName(domain: .peer(peerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic))
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
updateState { state in
|
||||
return state.withUpdatedUpdatingAddressName(false)
|
||||
@ -1173,7 +1173,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
|
||||
let signal = convertGroupToSupergroup(account: context.account, peerId: peerId)
|
||||
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ConvertGroupToSupergroupError> in
|
||||
return context.engine.peerNames.updateAddressName(domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
||||
return context.engine.peers.updateAddressName(domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
||||
|> `catch` { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|
||||
@ -396,7 +396,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! DeviceContactInfoControllerArguments
|
||||
switch self {
|
||||
case let .info(_, _, strings, dateTimeFormat, peer, state, jobSummary, isPlain):
|
||||
case let .info(_, _, _, dateTimeFormat, peer, state, jobSummary, _):
|
||||
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, cachedData: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
@ -647,8 +647,13 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen
|
||||
let jobSummary = jobComponents.joined(separator: " — ")
|
||||
|
||||
let isOrganization = personName.0.isEmpty && personName.1.isEmpty && !contactData.organization.isEmpty
|
||||
|
||||
var firstName: String = isOrganization ? contactData.organization : personName.0
|
||||
if firstName.isEmpty {
|
||||
firstName = presentationData.strings.Message_Contact
|
||||
}
|
||||
|
||||
entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? TelegramUser(id: PeerId(namespace: .max, id: PeerId.Id._internalFromInt32Value(0)), accessHash: nil, firstName: isOrganization ? contactData.organization : personName.0, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare))
|
||||
entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? TelegramUser(id: PeerId(namespace: .max, id: PeerId.Id._internalFromInt32Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare))
|
||||
|
||||
if !selecting {
|
||||
if let _ = peer {
|
||||
|
||||
@ -323,7 +323,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
||||
|
||||
let initialData = Promise<InitialStickerPackData?>()
|
||||
if let currentPackInfo = currentPackInfo {
|
||||
initialData.set(cachedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: .id(id: currentPackInfo.id.id, accessHash: currentPackInfo.accessHash), forceRemote: false)
|
||||
initialData.set(context.engine.stickers.cachedStickerPack(reference: .id(id: currentPackInfo.id.id, accessHash: currentPackInfo.accessHash), forceRemote: false)
|
||||
|> map { result -> InitialStickerPackData? in
|
||||
switch result {
|
||||
case .none:
|
||||
@ -363,7 +363,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
||||
}
|
||||
}
|
||||
return .single((searchText, .searching))
|
||||
|> then((loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: .name(searchText.lowercased()), forceActualized: false) |> delay(0.3, queue: Queue.concurrentDefaultQueue()))
|
||||
|> then((context.engine.stickers.loadedStickerPack(reference: .name(searchText.lowercased()), forceActualized: false) |> delay(0.3, queue: Queue.concurrentDefaultQueue()))
|
||||
|> mapToSignal { value -> Signal<(String, GroupStickerPackSearchState), NoError> in
|
||||
switch value {
|
||||
case .fetching:
|
||||
@ -402,7 +402,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
||||
}, updateSearchText: { text in
|
||||
searchText.set(text)
|
||||
}, openStickersBot: {
|
||||
resolveDisposable.set((resolvePeerByName(account: context.account, name: "stickers") |> deliverOnMainQueue).start(next: { peerId in
|
||||
resolveDisposable.set((context.engine.peers.resolvePeerByName(name: "stickers") |> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
dismissImpl?()
|
||||
navigateToChatControllerImpl?(peerId)
|
||||
|
||||
@ -384,7 +384,7 @@ public func oldChannelsController(context: AccountContext, intent: OldChannelsCo
|
||||
|
||||
let peersSignal: Signal<[InactiveChannel]?, NoError> = .single(nil)
|
||||
|> then(
|
||||
inactiveChannelList(network: context.account.network)
|
||||
context.engine.peers.inactiveChannelList()
|
||||
|> map { peers -> [InactiveChannel]? in
|
||||
return peers.sorted(by: { lhs, rhs in
|
||||
return lhs.lastActivityDate < rhs.lastActivityDate
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -512,7 +512,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|
||||
cancelImpl = {
|
||||
checkCreationAvailabilityDisposable.set(nil)
|
||||
}
|
||||
checkCreationAvailabilityDisposable.set((context.engine.peerNames.checkPublicChannelCreationAvailability(location: true)
|
||||
checkCreationAvailabilityDisposable.set((context.engine.peers.checkPublicChannelCreationAvailability(location: true)
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
|
||||
@ -1110,15 +1110,17 @@ public final class MediaBox {
|
||||
}
|
||||
}
|
||||
|
||||
public func removeCachedResources(_ ids: Set<WrappedMediaResourceId>) -> Signal<Void, NoError> {
|
||||
public func removeCachedResources(_ ids: Set<WrappedMediaResourceId>, force: Bool = false) -> Signal<Void, NoError> {
|
||||
return Signal { subscriber in
|
||||
self.dataQueue.async {
|
||||
for id in ids {
|
||||
if self.fileContexts[id] != nil {
|
||||
continue
|
||||
}
|
||||
if self.keepResourceContexts[id] != nil {
|
||||
continue
|
||||
if !force {
|
||||
if self.fileContexts[id] != nil {
|
||||
continue
|
||||
}
|
||||
if self.keepResourceContexts[id] != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
let paths = self.storePathsForId(id.id)
|
||||
unlink(paths.complete)
|
||||
|
||||
@ -6,11 +6,15 @@ import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
|
||||
public func textAlertController(context: AccountContext, forceTheme: PresentationTheme? = nil, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissOnOutsideTap: Bool = true) -> AlertController {
|
||||
var presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
return textAlertController(sharedContext: context.sharedContext, forceTheme: forceTheme, title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, dismissOnOutsideTap: dismissOnOutsideTap)
|
||||
}
|
||||
|
||||
public func textAlertController(sharedContext: SharedAccountContext, forceTheme: PresentationTheme? = nil, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissOnOutsideTap: Bool = true) -> AlertController {
|
||||
var presentationData = sharedContext.currentPresentationData.with { $0 }
|
||||
if let forceTheme = forceTheme {
|
||||
presentationData = presentationData.withUpdated(theme: forceTheme)
|
||||
}
|
||||
return textAlertController(alertContext: AlertControllerContext(theme: AlertControllerTheme(presentationData: presentationData), themeSignal: context.sharedContext.presentationData |> map {
|
||||
return textAlertController(alertContext: AlertControllerContext(theme: AlertControllerTheme(presentationData: presentationData), themeSignal: sharedContext.presentationData |> map {
|
||||
presentationData in
|
||||
var presentationData = presentationData
|
||||
if let forceTheme = forceTheme {
|
||||
|
||||
@ -96,7 +96,7 @@ public func saveToCameraRoll(context: AccountContext, postbox: Postbox, mediaRef
|
||||
return
|
||||
}
|
||||
|
||||
let tempVideoPath = NSTemporaryDirectory() + "\(arc4random64()).mp4"
|
||||
let tempVideoPath = NSTemporaryDirectory() + "\(Int64.random(in: Int64.min ... Int64.max)).mp4"
|
||||
PHPhotoLibrary.shared().performChanges({
|
||||
if isImage {
|
||||
if let fileData = try? Data(contentsOf: URL(fileURLWithPath: data.path)) {
|
||||
|
||||
@ -90,7 +90,7 @@ final class ChangePhoneNumberController: ViewController, MFMailComposeViewContro
|
||||
}
|
||||
}
|
||||
|
||||
loadServerCountryCodes(accountManager: self.context.sharedContext.accountManager, network: self.context.account.network, completion: { [weak self] in
|
||||
loadServerCountryCodes(accountManager: self.context.sharedContext.accountManager, engine: self.context.engine, completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.updateCountryCode()
|
||||
}
|
||||
|
||||
@ -157,7 +157,7 @@ public func logoutOptionsController(context: AccountContext, navigationControlle
|
||||
dismissImpl?()
|
||||
}, contactSupport: { [weak navigationController] in
|
||||
let supportPeer = Promise<PeerId?>()
|
||||
supportPeer.set(context.engine.peerNames.supportPeerId())
|
||||
supportPeer.set(context.engine.peers.supportPeerId())
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var faqUrl = presentationData.strings.Settings_FAQ_URL
|
||||
|
||||
@ -883,7 +883,7 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
|
||||
}
|
||||
|
||||
let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: synonyms(strings.SettingsSearch_Synonyms_Support), icon: .support, breadcrumbs: [], present: { context, _, present in
|
||||
let _ = (context.engine.peerNames.supportPeerId()
|
||||
let _ = (context.engine.peers.supportPeerId()
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||
|
||||
@ -268,7 +268,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
|
||||
namespace = .masks
|
||||
}
|
||||
let stickerPacks = Promise<[ArchivedStickerPackItem]?>()
|
||||
stickerPacks.set(.single(archived) |> then(archivedStickerPacks(account: context.account, namespace: namespace) |> map(Optional.init)))
|
||||
stickerPacks.set(.single(archived) |> then(context.engine.stickers.archivedStickerPacks(namespace: namespace) |> map(Optional.init)))
|
||||
|
||||
actionsDisposable.add(stickerPacks.get().start(next: { packs in
|
||||
updatedPacks(packs)
|
||||
@ -302,17 +302,16 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
|
||||
if !add {
|
||||
return
|
||||
}
|
||||
let _ = (loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|
||||
let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|
||||
|> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> in
|
||||
switch result {
|
||||
case let .result(info, items, installed):
|
||||
if installed {
|
||||
return .complete()
|
||||
} else {
|
||||
return addStickerPackInteractively(postbox: context.account.postbox, info: info, items: items)
|
||||
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
|
||||
|> ignoreValues
|
||||
|> mapToSignal { _ -> Signal<(StickerPackCollectionInfo, [ItemCollectionItem]), NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> then(.single((info, items)))
|
||||
}
|
||||
@ -336,7 +335,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
|
||||
}
|
||||
}
|
||||
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
return true
|
||||
}), nil)
|
||||
|
||||
@ -390,7 +389,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
|
||||
|
||||
return .complete()
|
||||
}
|
||||
removePackDisposables.set((removeArchivedStickerPack(account: context.account, info: info) |> then(applyPacks) |> deliverOnMainQueue).start(completed: {
|
||||
removePackDisposables.set((context.engine.stickers.removeArchivedStickerPack(info: info) |> then(applyPacks) |> deliverOnMainQueue).start(completed: {
|
||||
updateState { state in
|
||||
var removingPackIds = state.removingPackIds
|
||||
removingPackIds.remove(info.id)
|
||||
|
||||
@ -180,14 +180,14 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr
|
||||
let arguments = FeaturedStickerPacksControllerArguments(account: context.account, openStickerPack: { info in
|
||||
presentStickerPackController?(info)
|
||||
}, addPack: { info in
|
||||
let _ = (loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|
||||
let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
switch result {
|
||||
case let .result(info, items, installed):
|
||||
if installed {
|
||||
return .complete()
|
||||
} else {
|
||||
return addStickerPackInteractively(postbox: context.account.postbox, info: info, items: items)
|
||||
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
|
||||
}
|
||||
case .fetching:
|
||||
break
|
||||
@ -254,7 +254,7 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr
|
||||
if !unreadIds.isEmpty {
|
||||
alreadyReadIds.formUnion(Set(unreadIds))
|
||||
|
||||
let _ = markFeaturedStickerPacksAsSeenInteractively(postbox: context.account.postbox, ids: unreadIds).start()
|
||||
let _ = context.engine.stickers.markFeaturedStickerPacksAsSeenInteractively(ids: unreadIds).start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -532,7 +532,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
let removeAction: (RemoveStickerPackOption) -> Void = { action in
|
||||
let _ = (removeStickerPackInteractively(postbox: context.account.postbox, id: archivedItem.info.id, option: action)
|
||||
let _ = (context.engine.stickers.removeStickerPackInteractively(id: archivedItem.info.id, option: action)
|
||||
|> deliverOnMainQueue).start(next: { indexAndItems in
|
||||
guard let (positionInList, items) = indexAndItems else {
|
||||
return
|
||||
@ -548,9 +548,9 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
}
|
||||
}
|
||||
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: action == .archive ? presentationData.strings.StickerPackActionInfo_ArchivedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).0, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, account: context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: action == .archive ? presentationData.strings.StickerPackActionInfo_ArchivedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).0, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
if case .undo = action {
|
||||
let _ = addStickerPackInteractively(postbox: context.account.postbox, info: archivedItem.info, items: items, positionInList: positionInList).start()
|
||||
let _ = context.engine.stickers.addStickerPackInteractively(info: archivedItem.info, items: items, positionInList: positionInList).start()
|
||||
}
|
||||
return true
|
||||
}))
|
||||
@ -581,7 +581,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
])
|
||||
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
}, openStickersBot: {
|
||||
resolveDisposable.set((resolvePeerByName(account: context.account, name: "stickers") |> deliverOnMainQueue).start(next: { peerId in
|
||||
resolveDisposable.set((context.engine.peers.resolvePeerByName(name: "stickers") |> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
navigateToChatControllerImpl?(peerId)
|
||||
}
|
||||
@ -655,10 +655,10 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
switch mode {
|
||||
case .general, .modal:
|
||||
featured.set(context.account.viewTracker.featuredStickerPacks())
|
||||
archivedPromise.set(.single(archivedPacks) |> then(archivedStickerPacks(account: context.account) |> map(Optional.init)))
|
||||
archivedPromise.set(.single(archivedPacks) |> then(context.engine.stickers.archivedStickerPacks() |> map(Optional.init)))
|
||||
case .masks:
|
||||
featured.set(.single([]))
|
||||
archivedPromise.set(.single(nil) |> then(archivedStickerPacks(account: context.account, namespace: .masks) |> map(Optional.init)))
|
||||
archivedPromise.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks(namespace: .masks) |> map(Optional.init)))
|
||||
}
|
||||
|
||||
var previousPackCount: Int?
|
||||
@ -717,7 +717,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
}
|
||||
}
|
||||
|
||||
let _ = removeStickerPacksInteractively(postbox: context.account.postbox, ids: packIds, option: .delete).start()
|
||||
let _ = context.engine.stickers.removeStickerPacksInteractively(ids: packIds, option: .delete).start()
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
@ -742,7 +742,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
}
|
||||
}
|
||||
|
||||
let _ = removeStickerPacksInteractively(postbox: context.account.postbox, ids: packIds, option: .archive).start()
|
||||
let _ = context.engine.stickers.removeStickerPacksInteractively(ids: packIds, option: .archive).start()
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
@ -954,13 +954,13 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
||||
}
|
||||
switch action {
|
||||
case .add:
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, account: context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||
return true
|
||||
}))
|
||||
case let .remove(positionInList):
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).0, undo: true, info: info, topItem: items.first, account: context.account), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).0, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in
|
||||
if case .undo = action {
|
||||
let _ = addStickerPackInteractively(postbox: context.account.postbox, info: info, items: items, positionInList: positionInList).start()
|
||||
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
|
||||
}
|
||||
return true
|
||||
}))
|
||||
|
||||
@ -130,11 +130,11 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE
|
||||
let thumbnailImage = generateScaledImage(image: croppedImage, size: thumbnailDimensions, scale: 1.0)
|
||||
|
||||
if let data = croppedImage.jpegData(compressionQuality: 0.8), let thumbnailImage = thumbnailImage, let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||
let thumbnailResource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let thumbnailResource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData)
|
||||
context.account.postbox.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData)
|
||||
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||
|
||||
|
||||
@ -443,7 +443,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
|
||||
|> take(1)).start(next: { previewTheme, settings in
|
||||
let saveThemeTemplateFile: (String, LocalFileMediaResource, @escaping () -> Void) -> Void = { title, resource, completion in
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: resource.fileId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/x-tgtheme-ios", size: nil, attributes: [.FileName(fileName: "\(title).tgios-theme")])
|
||||
let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
|
||||
let _ = enqueueMessages(account: context.account, peerId: context.account.peerId, messages: [message]).start()
|
||||
|
||||
@ -478,7 +478,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
|
||||
let themeData: Data?
|
||||
let themeThumbnailData: Data?
|
||||
if let theme = theme, let themeString = encodePresentationTheme(theme), let data = themeString.data(using: .utf8) {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
themeResource = resource
|
||||
|
||||
@ -497,7 +497,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode {
|
||||
guard let name = configuration.imageBotUsername else {
|
||||
return .single(nil)
|
||||
}
|
||||
return resolvePeerByName(account: context.account, name: name)
|
||||
return context.engine.peers.resolvePeerByName(name: name)
|
||||
|> mapToSignal { peerId -> Signal<Peer?, NoError> in
|
||||
if let peerId = peerId {
|
||||
return context.account.postbox.loadedPeerWithId(peerId)
|
||||
|
||||
@ -245,7 +245,7 @@ public final class ThemePreviewController: ViewController {
|
||||
}
|
||||
case .media:
|
||||
if let strings = encodePresentationTheme(previewTheme), let data = strings.data(using: .utf8) {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
||||
theme = .single(.local(PresentationLocalTheme(title: previewTheme.name.string, resource: resource, resolvedWallpaper: nil)))
|
||||
|
||||
@ -407,7 +407,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let dimensions = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
|
||||
contentSize = dimensions
|
||||
displaySize = dimensions.dividedByScreenScale().integralFloor
|
||||
signal = photoWallpaper(postbox: context.account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64()))
|
||||
signal = photoWallpaper(postbox: context.account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max)))
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
subtitleSignal = .single(nil)
|
||||
|
||||
@ -260,7 +260,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController {
|
||||
return state.withUpdatedEditingPublicLinkText(text)
|
||||
}
|
||||
|
||||
checkAddressNameDisposable.set((context.engine.peerNames.validateAddressNameInteractive(domain: .account, name: text)
|
||||
checkAddressNameDisposable.set((context.engine.peers.validateAddressNameInteractive(domain: .account, name: text)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
updateState { state in
|
||||
return state.withUpdatedAddressNameValidationStatus(result)
|
||||
@ -325,7 +325,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController {
|
||||
}
|
||||
|
||||
if let updatedAddressNameValue = updatedAddressNameValue {
|
||||
updateAddressNameDisposable.set((context.engine.peerNames.updateAddressName(domain: .account, name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
||||
updateAddressNameDisposable.set((context.engine.peers.updateAddressName(domain: .account, name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
updateState { state in
|
||||
return state.withUpdatedUpdatingAddressName(false)
|
||||
|
||||
@ -519,9 +519,9 @@ public final class ShareController: ViewController {
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: url + "\n\n" + text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: url + "\n\n" + text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
} else {
|
||||
messages.append(.message(text: url, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: url, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
@ -529,58 +529,58 @@ public final class ShareController: ViewController {
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
messages.append(.message(text: string, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: string, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .quote(string, url):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
|
||||
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .image(representations):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .media(mediaReference):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .mapMedia(media):
|
||||
for peerId in peerIds {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
|
||||
}
|
||||
case let .messages(messages):
|
||||
for peerId in peerIds {
|
||||
var messagesToEnqueue: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
for message in messages {
|
||||
messagesToEnqueue.append(.forward(source: message.id, grouping: .auto, attributes: []))
|
||||
messagesToEnqueue.append(.forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil))
|
||||
}
|
||||
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messagesToEnqueue))
|
||||
}
|
||||
@ -663,7 +663,7 @@ public final class ShareController: ViewController {
|
||||
case let .quote(text, url):
|
||||
collectableItems.append(CollectableExternalShareItem(url: "", text: "\"\(text)\"\n\n\(url)", author: nil, timestamp: nil, mediaReference: nil))
|
||||
case let .image(representations):
|
||||
let media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
let media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
collectableItems.append(CollectableExternalShareItem(url: "", text: "", author: nil, timestamp: nil, mediaReference: .standalone(media: media)))
|
||||
case let .media(mediaReference):
|
||||
collectableItems.append(CollectableExternalShareItem(url: "", text: "", author: nil, timestamp: nil, mediaReference: mediaReference))
|
||||
|
||||
@ -249,7 +249,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
||||
let foundLocalPeers = context.account.postbox.searchPeers(query: query.lowercased())
|
||||
let foundRemotePeers: Signal<([FoundPeer], [FoundPeer]), NoError> = .single(([], []))
|
||||
|> then(
|
||||
searchPeers(account: context.account, query: query)
|
||||
context.engine.peers.searchPeers(query: query)
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
|
||||
|
||||
@ -127,7 +127,7 @@ private func preparedShareItem(account: Account, to peerId: PeerId, value: [Stri
|
||||
|
||||
let estimatedSize = TGMediaVideoConverter.estimatedSize(for: preset, duration: finalDuration, hasAudio: true)
|
||||
|
||||
let resource = LocalFileVideoMediaResource(randomId: arc4random64(), path: asset.url.path, adjustments: resourceAdjustments)
|
||||
let resource = LocalFileVideoMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: asset.url.path, adjustments: resourceAdjustments)
|
||||
return standaloneUploadedFile(account: account, peerId: peerId, text: "", source: .resource(.standalone(resource: resource)), mimeType: "video/mp4", attributes: [.Video(duration: Int(finalDuration), size: PixelDimensions(width: Int32(finalDimensions.width), height: Int32(finalDimensions.height)), flags: flags)], hintFileIsLarge: estimatedSize > 10 * 1024 * 1024)
|
||||
|> mapError { _ -> Void in
|
||||
return Void()
|
||||
@ -394,26 +394,26 @@ public func sentShareItems(account: Account, to peerIds: [PeerId], items: [Prepa
|
||||
}
|
||||
|
||||
if ((mediaTypes.photo + mediaTypes.video) > 1) && (mediaTypes.music == 0 && mediaTypes.other == 0) {
|
||||
groupingKey = arc4random64()
|
||||
groupingKey = Int64.random(in: Int64.min ... Int64.max)
|
||||
} else if ((mediaTypes.photo + mediaTypes.video) == 0) && ((mediaTypes.music > 1 && mediaTypes.other == 0) || (mediaTypes.music == 0 && mediaTypes.other > 1)) {
|
||||
groupingKey = arc4random64()
|
||||
groupingKey = Int64.random(in: Int64.min ... Int64.max)
|
||||
}
|
||||
|
||||
var mediaMessages: [EnqueueMessage] = []
|
||||
for item in items {
|
||||
switch item {
|
||||
case let .text(text):
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil))
|
||||
messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
case let .media(media):
|
||||
switch media {
|
||||
case let .media(reference):
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey)
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey, correlationId: nil)
|
||||
messages.append(message)
|
||||
mediaMessages.append(message)
|
||||
|
||||
}
|
||||
if let _ = groupingKey, mediaMessages.count % 10 == 0 {
|
||||
groupingKey = arc4random64()
|
||||
groupingKey = Int64.random(in: Int64.min ... Int64.max)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
|
||||
self.acceptsFocusWhenInOverlay = true
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
|
||||
self.stickerPackContents.set(loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: stickerPack, forceActualized: true))
|
||||
self.stickerPackContents.set(context.engine.stickers.loadedStickerPack(reference: stickerPack, forceActualized: true))
|
||||
|
||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
@ -132,7 +132,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
|
||||
}
|
||||
|
||||
let account = strongSelf.context.account
|
||||
strongSelf.openMentionDisposable.set((resolvePeerByName(account: strongSelf.context.account, name: mention)
|
||||
strongSelf.openMentionDisposable.set((strongSelf.context.engine.peers.resolvePeerByName(name: mention)
|
||||
|> mapToSignal { peerId -> Signal<Peer?, NoError> in
|
||||
if let peerId = peerId {
|
||||
return account.postbox.loadedPeerWithId(peerId)
|
||||
|
||||
@ -521,7 +521,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
||||
switch stickerPack {
|
||||
case let .result(info, items, installed):
|
||||
if installed {
|
||||
let _ = (removeStickerPackInteractively(postbox: self.context.account.postbox, id: info.id, option: .delete)
|
||||
let _ = (self.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] indexAndItems in
|
||||
guard let strongSelf = self, let (positionInList, _) = indexAndItems else {
|
||||
return
|
||||
@ -532,7 +532,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol
|
||||
self.updateStickerPack(.result(info: info, items: items, installed: false), stickerSettings: stickerSettings)
|
||||
}
|
||||
} else {
|
||||
let _ = addStickerPackInteractively(postbox: self.context.account.postbox, info: info, items: items).start()
|
||||
let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
|
||||
if !dismissOnAction {
|
||||
self.updateStickerPack(.result(info: info, items: items, installed: true), stickerSettings: stickerSettings)
|
||||
}
|
||||
|
||||
@ -238,7 +238,7 @@ private final class StickerPackContainer: ASDisplayNode {
|
||||
return updatedOffset
|
||||
}
|
||||
|
||||
self.itemsDisposable = (loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: stickerPack, forceActualized: false)
|
||||
self.itemsDisposable = (context.engine.stickers.loadedStickerPack(reference: stickerPack, forceActualized: false)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] contents in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -340,9 +340,9 @@ private final class StickerPackContainer: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
if installed {
|
||||
let _ = removeStickerPackInteractively(postbox: strongSelf.context.account.postbox, id: info.id, option: .delete).start()
|
||||
let _ = strongSelf.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete).start()
|
||||
} else {
|
||||
let _ = addStickerPackInteractively(postbox: strongSelf.context.account.postbox, info: info, items: items).start()
|
||||
let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
|
||||
}
|
||||
|
||||
switch strongSelf.decideNextAction(strongSelf, installed ? .remove : .add) {
|
||||
|
||||
@ -19,30 +19,38 @@ public class OutgoingMessageInfoAttribute: MessageAttribute {
|
||||
public let uniqueId: Int64
|
||||
public let flags: OutgoingMessageInfoFlags
|
||||
public let acknowledged: Bool
|
||||
public let correlationId: Int64?
|
||||
|
||||
public init(uniqueId: Int64, flags: OutgoingMessageInfoFlags, acknowledged: Bool) {
|
||||
public init(uniqueId: Int64, flags: OutgoingMessageInfoFlags, acknowledged: Bool, correlationId: Int64?) {
|
||||
self.uniqueId = uniqueId
|
||||
self.flags = flags
|
||||
self.acknowledged = acknowledged
|
||||
self.correlationId = correlationId
|
||||
}
|
||||
|
||||
required public init(decoder: PostboxDecoder) {
|
||||
self.uniqueId = decoder.decodeInt64ForKey("u", orElse: 0)
|
||||
self.flags = OutgoingMessageInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0))
|
||||
self.acknowledged = decoder.decodeInt32ForKey("ack", orElse: 0) != 0
|
||||
self.correlationId = decoder.decodeOptionalInt64ForKey("cid")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64(self.uniqueId, forKey: "u")
|
||||
encoder.encodeInt32(self.flags.rawValue, forKey: "f")
|
||||
encoder.encodeInt32(self.acknowledged ? 1 : 0, forKey: "ack")
|
||||
if let correlationId = self.correlationId {
|
||||
encoder.encodeInt64(correlationId, forKey: "cid")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "cid")
|
||||
}
|
||||
}
|
||||
|
||||
public func withUpdatedFlags(_ flags: OutgoingMessageInfoFlags) -> OutgoingMessageInfoAttribute {
|
||||
return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: flags, acknowledged: self.acknowledged)
|
||||
return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: flags, acknowledged: self.acknowledged, correlationId: self.correlationId)
|
||||
}
|
||||
|
||||
public func withUpdatedAcknowledged(_ acknowledged: Bool) -> OutgoingMessageInfoAttribute {
|
||||
return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: self.flags, acknowledged: acknowledged)
|
||||
return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: self.flags, acknowledged: acknowledged, correlationId: self.correlationId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -425,6 +425,8 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
|
||||
if case .Sticker = attribute {
|
||||
if let s = self.size, s < 300 * 1024 {
|
||||
return !isAnimatedSticker
|
||||
} else if self.size == nil {
|
||||
return !isAnimatedSticker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,7 +353,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1098628881] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaVenue($0) }
|
||||
dict[-1494368259] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaContact($0) }
|
||||
dict[1262639204] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageGame($0) }
|
||||
dict[-717976187] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaInvoice($0) }
|
||||
dict[-672693723] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaInvoice($0) }
|
||||
dict[2002815875] = { return Api.KeyboardButtonRow.parse_keyboardButtonRow($0) }
|
||||
dict[-673242758] = { return Api.StickerSet.parse_stickerSet($0) }
|
||||
dict[-1111085620] = { return Api.messages.ExportedChatInvites.parse_exportedChatInvites($0) }
|
||||
@ -392,7 +392,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-440664550] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) }
|
||||
dict[-78455655] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) }
|
||||
dict[-750828557] = { return Api.InputMedia.parse_inputMediaGame($0) }
|
||||
dict[-186607933] = { return Api.InputMedia.parse_inputMediaInvoice($0) }
|
||||
dict[-646342540] = { return Api.InputMedia.parse_inputMediaInvoice($0) }
|
||||
dict[-1759532989] = { return Api.InputMedia.parse_inputMediaGeoLive($0) }
|
||||
dict[261416433] = { return Api.InputMedia.parse_inputMediaPoll($0) }
|
||||
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
|
||||
|
||||
@ -9020,7 +9020,7 @@ public extension Api {
|
||||
case inputBotInlineMessageMediaVenue(flags: Int32, geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String, replyMarkup: Api.ReplyMarkup?)
|
||||
case inputBotInlineMessageMediaContact(flags: Int32, phoneNumber: String, firstName: String, lastName: String, vcard: String, replyMarkup: Api.ReplyMarkup?)
|
||||
case inputBotInlineMessageGame(flags: Int32, replyMarkup: Api.ReplyMarkup?)
|
||||
case inputBotInlineMessageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, startParam: String, replyMarkup: Api.ReplyMarkup?)
|
||||
case inputBotInlineMessageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, replyMarkup: Api.ReplyMarkup?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -9092,9 +9092,9 @@ public extension Api {
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
||||
break
|
||||
case .inputBotInlineMessageMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let replyMarkup):
|
||||
case .inputBotInlineMessageMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let replyMarkup):
|
||||
if boxed {
|
||||
buffer.appendInt32(-717976187)
|
||||
buffer.appendInt32(-672693723)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
@ -9104,7 +9104,6 @@ public extension Api {
|
||||
serializeBytes(payload, buffer: buffer, boxed: false)
|
||||
serializeString(provider, buffer: buffer, boxed: false)
|
||||
providerData.serialize(buffer, true)
|
||||
serializeString(startParam, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)}
|
||||
break
|
||||
}
|
||||
@ -9124,8 +9123,8 @@ public extension Api {
|
||||
return ("inputBotInlineMessageMediaContact", [("flags", flags), ("phoneNumber", phoneNumber), ("firstName", firstName), ("lastName", lastName), ("vcard", vcard), ("replyMarkup", replyMarkup)])
|
||||
case .inputBotInlineMessageGame(let flags, let replyMarkup):
|
||||
return ("inputBotInlineMessageGame", [("flags", flags), ("replyMarkup", replyMarkup)])
|
||||
case .inputBotInlineMessageMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let replyMarkup):
|
||||
return ("inputBotInlineMessageMediaInvoice", [("flags", flags), ("title", title), ("description", description), ("photo", photo), ("invoice", invoice), ("payload", payload), ("provider", provider), ("providerData", providerData), ("startParam", startParam), ("replyMarkup", replyMarkup)])
|
||||
case .inputBotInlineMessageMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let replyMarkup):
|
||||
return ("inputBotInlineMessageMediaInvoice", [("flags", flags), ("title", title), ("description", description), ("photo", photo), ("invoice", invoice), ("payload", payload), ("provider", provider), ("providerData", providerData), ("replyMarkup", replyMarkup)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -9310,11 +9309,9 @@ public extension Api {
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
}
|
||||
var _9: String?
|
||||
_9 = parseString(reader)
|
||||
var _10: Api.ReplyMarkup?
|
||||
var _9: Api.ReplyMarkup?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_10 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
@ -9324,10 +9321,9 @@ public extension Api {
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
let _c10 = (Int(_1!) & Int(1 << 2) == 0) || _10 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
||||
return Api.InputBotInlineMessage.inputBotInlineMessageMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7!, providerData: _8!, startParam: _9!, replyMarkup: _10)
|
||||
let _c9 = (Int(_1!) & Int(1 << 2) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.InputBotInlineMessage.inputBotInlineMessageMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7!, providerData: _8!, replyMarkup: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -9939,7 +9935,7 @@ public extension Api {
|
||||
case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
|
||||
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?)
|
||||
case inputMediaGame(id: Api.InputGame)
|
||||
case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, startParam: String)
|
||||
case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, startParam: String?)
|
||||
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
|
||||
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
|
||||
case inputMediaDice(emoticon: String)
|
||||
@ -10052,7 +10048,7 @@ public extension Api {
|
||||
break
|
||||
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam):
|
||||
if boxed {
|
||||
buffer.appendInt32(-186607933)
|
||||
buffer.appendInt32(-646342540)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
@ -10062,7 +10058,7 @@ public extension Api {
|
||||
serializeBytes(payload, buffer: buffer, boxed: false)
|
||||
serializeString(provider, buffer: buffer, boxed: false)
|
||||
providerData.serialize(buffer, true)
|
||||
serializeString(startParam, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
|
||||
if boxed {
|
||||
@ -10373,7 +10369,7 @@ public extension Api {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
}
|
||||
var _9: String?
|
||||
_9 = parseString(reader)
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_9 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -10382,9 +10378,9 @@ public extension Api {
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.InputMedia.inputMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7!, providerData: _8!, startParam: _9!)
|
||||
return Api.InputMedia.inputMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7!, providerData: _8!, startParam: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
||||
@ -7868,15 +7868,17 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func editGroupCallParticipant(flags: Int32, call: Api.InputGroupCall, participant: Api.InputPeer, volume: Int32?, raiseHand: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
public static func editGroupCallParticipant(flags: Int32, call: Api.InputGroupCall, participant: Api.InputPeer, muted: Api.Bool?, volume: Int32?, raiseHand: Api.Bool?, videoMuted: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-646583424)
|
||||
buffer.appendInt32(-1362751260)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
call.serialize(buffer, true)
|
||||
participant.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {muted!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {raiseHand!.serialize(buffer, true)}
|
||||
return (FunctionDescription(name: "phone.editGroupCallParticipant", parameters: [("flags", flags), ("call", call), ("participant", participant), ("volume", volume), ("raiseHand", raiseHand)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
if Int(flags) & Int(1 << 3) != 0 {videoMuted!.serialize(buffer, true)}
|
||||
return (FunctionDescription(name: "phone.editGroupCallParticipant", parameters: [("flags", flags), ("call", call), ("participant", participant), ("muted", muted), ("volume", volume), ("raiseHand", raiseHand), ("videoMuted", videoMuted)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
|
||||
@ -245,11 +245,11 @@ func rateCallAndSendLogs(account: Account, callId: CallId, starsCount: Int, comm
|
||||
|
||||
let rate = rateCall(account: account, callId: callId, starsCount: Int32(starsCount), comment: comment, userInitiated: userInitiated)
|
||||
if includeLogs {
|
||||
let id = arc4random64()
|
||||
let id = Int64.random(in: Int64.min ... Int64.max)
|
||||
let name = "\(callId.id)_\(callId.accessHash).log.json"
|
||||
let path = callLogsPath(account: account) + "/" + name
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)])
|
||||
let message = EnqueueMessage.message(text: comment, attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
let message = EnqueueMessage.message(text: comment, attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
|
||||
return rate
|
||||
|> then(enqueueMessages(account: account, peerId: peerId, messages: [message])
|
||||
|> mapToSignal({ _ -> Signal<Void, NoError> in
|
||||
@ -257,7 +257,7 @@ func rateCallAndSendLogs(account: Account, callId: CallId, starsCount: Int, comm
|
||||
}))
|
||||
} else if !comment.isEmpty {
|
||||
return rate
|
||||
|> then(enqueueMessages(account: account, peerId: peerId, messages: [.message(text: comment, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)])
|
||||
|> then(enqueueMessages(account: account, peerId: peerId, messages: [.message(text: comment, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)])
|
||||
|> mapToSignal({ _ -> Signal<Void, NoError> in
|
||||
return .single(Void())
|
||||
}))
|
||||
|
||||
@ -932,6 +932,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
activityTimestamp: strongSelf.temporaryActivityTimestamp,
|
||||
activityRank: strongSelf.temporaryActivityRank,
|
||||
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
|
||||
isVideoMuted: true,
|
||||
volume: nil,
|
||||
about: about
|
||||
))
|
||||
@ -1012,6 +1013,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
activityTimestamp: strongSelf.temporaryActivityTimestamp,
|
||||
activityRank: strongSelf.temporaryActivityRank,
|
||||
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
|
||||
isVideoMuted: true,
|
||||
volume: nil,
|
||||
about: about
|
||||
))
|
||||
@ -1174,6 +1176,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
activityTimestamp: strongSelf.temporaryActivityTimestamp,
|
||||
activityRank: strongSelf.temporaryActivityRank,
|
||||
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canManageCall || !state.defaultParticipantsAreMuted.isMuted, mutedByYou: false),
|
||||
isVideoMuted: true,
|
||||
volume: nil,
|
||||
about: about
|
||||
))
|
||||
@ -1748,6 +1751,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
activityTimestamp: strongSelf.temporaryActivityTimestamp,
|
||||
activityRank: strongSelf.temporaryActivityRank,
|
||||
muteState: strongSelf.temporaryMuteState ?? GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false),
|
||||
isVideoMuted: true,
|
||||
volume: nil,
|
||||
about: about
|
||||
))
|
||||
@ -2344,7 +2348,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if id == peerId {
|
||||
self.callContext?.setVolume(ssrc: ssrc, volume: Double(volume) / 10000.0)
|
||||
if sync {
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: volume, raiseHand: nil)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, isVideoMuted: nil, volume: volume, raiseHand: nil)
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -2452,19 +2456,19 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
canThenUnmute = true
|
||||
}
|
||||
let muteState = isMuted ? GroupCallParticipantsContext.Participant.MuteState(canUnmute: canThenUnmute, mutedByYou: mutedByYou) : nil
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil, raiseHand: nil)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, isVideoMuted: nil, volume: nil, raiseHand: nil)
|
||||
return muteState
|
||||
} else {
|
||||
if peerId == self.joinAsPeerId {
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil, raiseHand: nil)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: nil)
|
||||
return nil
|
||||
} else if self.stateValue.canManageCall || self.stateValue.adminIds.contains(self.accountContext.account.peerId) {
|
||||
let muteState = GroupCallParticipantsContext.Participant.MuteState(canUnmute: true, mutedByYou: false)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, volume: nil, raiseHand: nil)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: muteState, isVideoMuted: nil, volume: nil, raiseHand: nil)
|
||||
return muteState
|
||||
} else {
|
||||
self.setVolume(peerId: peerId, volume: 10000, sync: true)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, volume: nil, raiseHand: nil)
|
||||
self.participantsContext?.updateMuteState(peerId: peerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: nil)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -1108,7 +1108,7 @@ public final class VoiceChatController: ViewController {
|
||||
dismissController?()
|
||||
|
||||
if let strongSelf = self {
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)])
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentUndoOverlay(content: .forward(savedMessages: false, text: strongSelf.presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), action: { _ in return true })
|
||||
@ -4708,7 +4708,7 @@ public final class VoiceChatController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
self.call.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource, progressiveSizes: [], immediateThumbnailData: nil)
|
||||
|
||||
@ -4743,7 +4743,7 @@ public final class VoiceChatController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
let photoResource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let photoResource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
self.context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
|
||||
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: photoResource, progressiveSizes: [], immediateThumbnailData: nil)
|
||||
|
||||
@ -4808,7 +4808,7 @@ public final class VoiceChatController: ViewController {
|
||||
if let liveUploadData = result.liveUploadData as? LegacyLiveUploadInterfaceResult {
|
||||
resource = LocalFileMediaResource(fileId: liveUploadData.id)
|
||||
} else {
|
||||
resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
}
|
||||
account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
subscriber.putNext(resource)
|
||||
|
||||
@ -67,6 +67,11 @@ public class UnauthorizedAccount {
|
||||
public var updateLoginTokenEvents: Signal<Void, NoError> {
|
||||
return self.updateLoginTokenPipe.signal()
|
||||
}
|
||||
|
||||
private let serviceNotificationPipe = ValuePipe<String>()
|
||||
public var serviceNotificationEvents: Signal<String, NoError> {
|
||||
return self.serviceNotificationPipe.signal()
|
||||
}
|
||||
|
||||
public var masterDatacenterId: Int32 {
|
||||
return Int32(self.network.mtProto.datacenterId)
|
||||
@ -83,8 +88,11 @@ public class UnauthorizedAccount {
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
let updateLoginTokenPipe = self.updateLoginTokenPipe
|
||||
let serviceNotificationPipe = self.serviceNotificationPipe
|
||||
self.stateManager = UnauthorizedAccountStateManager(network: network, updateLoginToken: {
|
||||
updateLoginTokenPipe.putNext(Void())
|
||||
}, displayServiceNotification: { text in
|
||||
serviceNotificationPipe.putNext(text)
|
||||
})
|
||||
|
||||
network.shouldKeepConnection.set(self.shouldBeServiceTaskMaster.get()
|
||||
|
||||
@ -467,7 +467,7 @@ public func signUpWithName(accountManager: AccountManager, account: Unauthorized
|
||||
|> castError(SignUpError.self)
|
||||
|
||||
if let avatarData = avatarData {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
account.postbox.mediaBox.storeResourceData(resource.id, data: avatarData)
|
||||
|
||||
return updatePeerPhotoInternal(postbox: account.postbox, network: account.network, stateManager: nil, accountPeerId: user.id, peer: .single(user), photo: uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: resource), video: avatarVideo, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { _, _ in .single([:]) })
|
||||
|
||||
@ -246,7 +246,7 @@ private final class CallSessionContext {
|
||||
var isVideoPossible: Bool
|
||||
var state: CallSessionInternalState
|
||||
let subscribers = Bag<(CallSession) -> Void>()
|
||||
let signalingSubscribers = Bag<(Data) -> Void>()
|
||||
var signalingReceiver: (([Data]) -> Void)?
|
||||
|
||||
let signalingDisposables = DisposableSet()
|
||||
|
||||
@ -254,7 +254,7 @@ private final class CallSessionContext {
|
||||
|
||||
var isEmpty: Bool {
|
||||
if case .terminated = self.state {
|
||||
return self.subscribers.isEmpty && self.signalingSubscribers.isEmpty
|
||||
return self.subscribers.isEmpty
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@ -303,6 +303,8 @@ private final class CallSessionManagerContext {
|
||||
private let ringingSubscribers = Bag<([CallSessionRingingState]) -> Void>()
|
||||
private var contexts: [CallSessionInternalId: CallSessionContext] = [:]
|
||||
private var contextIdByStableId: [CallSessionStableId: CallSessionInternalId] = [:]
|
||||
|
||||
private var enqueuedSignalingData: [Int64: [Data]] = [:]
|
||||
|
||||
private let disposables = DisposableSet()
|
||||
|
||||
@ -395,29 +397,31 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
}
|
||||
|
||||
func callSignalingData(internalId: CallSessionInternalId) -> Signal<Data, NoError> {
|
||||
func beginReceivingCallSignalingData(internalId: CallSessionInternalId, _ receiver: @escaping ([Data]) -> Void) -> Disposable {
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
queue.async {
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
let index = context.signalingSubscribers.add { next in
|
||||
subscriber.putNext(next)
|
||||
|
||||
let disposable = MetaDisposable()
|
||||
queue.async { [weak self] in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
context.signalingReceiver = receiver
|
||||
|
||||
for (listStableId, listInternalId) in strongSelf.contextIdByStableId {
|
||||
if listInternalId == internalId {
|
||||
strongSelf.deliverCallSignalingData(id: listStableId)
|
||||
break
|
||||
}
|
||||
disposable.set(ActionDisposable {
|
||||
queue.async {
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
context.signalingSubscribers.remove(index)
|
||||
if context.isEmpty {
|
||||
strongSelf.contexts.removeValue(forKey: internalId)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
queue.async {
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
context.signalingReceiver = nil
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
|
||||
private func ringingStatesValue() -> [CallSessionRingingState] {
|
||||
@ -475,6 +479,7 @@ private final class CallSessionManagerContext {
|
||||
}))
|
||||
self.contextIdByStableId[stableId] = internalId
|
||||
self.contextUpdated(internalId: internalId)
|
||||
self.deliverCallSignalingData(id: stableId)
|
||||
self.ringingStatesUpdated()
|
||||
return internalId
|
||||
} else {
|
||||
@ -596,7 +601,7 @@ private final class CallSessionManagerContext {
|
||||
func accept(internalId: CallSessionInternalId) {
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .ringing(id, accessHash, gAHash, b, remoteVersions):
|
||||
case let .ringing(id, accessHash, gAHash, b, _):
|
||||
let acceptVersions = self.versions.map({ $0.version })
|
||||
context.state = .accepting(id: id, accessHash: accessHash, gAHash: gAHash, b: b, disposable: (acceptCallSession(postbox: self.postbox, network: self.network, stableId: id, accessHash: accessHash, b: b, maxLayer: self.maxLayer, versions: acceptVersions) |> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
@ -652,7 +657,7 @@ private final class CallSessionManagerContext {
|
||||
switch call {
|
||||
case .phoneCallEmpty:
|
||||
break
|
||||
case let .phoneCallAccepted(flags, id, _, _, _, _, gB, remoteProtocol):
|
||||
case let .phoneCallAccepted(_, id, _, _, _, _, gB, remoteProtocol):
|
||||
let remoteVersions: [String]
|
||||
switch remoteProtocol {
|
||||
case let .phoneCallProtocol(_, _, _, versions):
|
||||
@ -854,11 +859,22 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
|
||||
func addCallSignalingData(id: Int64, data: Data) {
|
||||
if self.enqueuedSignalingData[id] == nil {
|
||||
self.enqueuedSignalingData[id] = []
|
||||
}
|
||||
self.enqueuedSignalingData[id]?.append(data)
|
||||
|
||||
self.deliverCallSignalingData(id: id)
|
||||
}
|
||||
|
||||
private func deliverCallSignalingData(id: Int64) {
|
||||
guard let internalId = self.contextIdByStableId[id], let context = self.contexts[internalId] else {
|
||||
return
|
||||
}
|
||||
for f in context.signalingSubscribers.copyItems() {
|
||||
f(data)
|
||||
if let signalingReceiver = context.signalingReceiver {
|
||||
if let data = self.enqueuedSignalingData.removeValue(forKey: id) {
|
||||
signalingReceiver(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -902,6 +918,7 @@ private final class CallSessionManagerContext {
|
||||
context.state = .requested(id: id, accessHash: accessHash, a: a, gA: gA, config: config, remoteConfirmationTimestamp: remoteConfirmationTimestamp)
|
||||
strongSelf.contextIdByStableId[id] = internalId
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
strongSelf.deliverCallSignalingData(id: id)
|
||||
case let .failed(error):
|
||||
context.state = .terminated(id: nil, accessHash: nil, reason: .error(error), reportRating: false, sendDebugLogs: false)
|
||||
strongSelf.contextUpdated(internalId: internalId)
|
||||
@ -1044,16 +1061,14 @@ public final class CallSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func callSignalingData(internalId: CallSessionInternalId) -> Signal<Data, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self?.withContext { context in
|
||||
disposable.set(context.callSignalingData(internalId: internalId).start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}))
|
||||
}
|
||||
return disposable
|
||||
public func beginReceivingCallSignalingData(internalId: CallSessionInternalId, _ receiver: @escaping ([Data]) -> Void) -> Disposable {
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.withContext { context in
|
||||
disposable.set(context.beginReceivingCallSignalingData(internalId: internalId, receiver))
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
import Foundation
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramApi
|
||||
|
||||
public enum DeleteAccountError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func deleteAccount(account: Account) -> Signal<Never, DeleteAccountError> {
|
||||
return account.network.request(Api.functions.account.deleteAccount(reason: "GDPR"))
|
||||
|> mapError { _ -> DeleteAccountError in
|
||||
return .generic
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
@ -35,7 +35,7 @@ public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [M
|
||||
}
|
||||
}
|
||||
if !resourceIds.isEmpty {
|
||||
let _ = mediaBox.removeCachedResources(Set(resourceIds)).start()
|
||||
let _ = mediaBox.removeCachedResources(Set(resourceIds), force: true).start()
|
||||
}
|
||||
for id in ids {
|
||||
if id.peerId.namespace == Namespaces.Peer.CloudChannel && id.namespace == Namespaces.Message.Cloud {
|
||||
@ -73,7 +73,7 @@ public func deleteAllMessagesWithForwardAuthor(transaction: Transaction, mediaBo
|
||||
addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds)
|
||||
})
|
||||
if !resourceIds.isEmpty {
|
||||
let _ = mediaBox.removeCachedResources(Set(resourceIds)).start()
|
||||
let _ = mediaBox.removeCachedResources(Set(resourceIds), force: true).start()
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: P
|
||||
return true
|
||||
})
|
||||
if !resourceIds.isEmpty {
|
||||
let _ = mediaBox.removeCachedResources(Set(resourceIds)).start()
|
||||
let _ = mediaBox.removeCachedResources(Set(resourceIds), force: true).start()
|
||||
}
|
||||
}
|
||||
transaction.clearHistory(peerId, namespaces: namespaces, forEachMedia: { _ in
|
||||
|
||||
@ -80,7 +80,7 @@ func deleteMessagesInteractively(transaction: Transaction, stateManager: Account
|
||||
globallyUniqueIds.append(globallyUniqueId)
|
||||
}
|
||||
}
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.deleteMessages(layer: layer, actionGloballyUniqueId: arc4random64(), globallyUniqueIds: globallyUniqueIds), state: state)
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.deleteMessages(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), globallyUniqueIds: globallyUniqueIds), state: state)
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
}
|
||||
@ -137,7 +137,7 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: In
|
||||
}
|
||||
|
||||
if let layer = layer {
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.clearHistory(layer: layer, actionGloballyUniqueId: arc4random64()), state: state)
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.clearHistory(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max)), state: state)
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(peerId, state: updatedState)
|
||||
}
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
public enum Either<Left, Right> {
|
||||
case left(value: Left)
|
||||
case right(value: Right)
|
||||
}
|
||||
@ -11,13 +11,13 @@ public enum EnqueueMessageGrouping {
|
||||
}
|
||||
|
||||
public enum EnqueueMessage {
|
||||
case message(text: String, attributes: [MessageAttribute], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?)
|
||||
case forward(source: MessageId, grouping: EnqueueMessageGrouping, attributes: [MessageAttribute])
|
||||
case message(text: String, attributes: [MessageAttribute], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?, correlationId: Int64?)
|
||||
case forward(source: MessageId, grouping: EnqueueMessageGrouping, attributes: [MessageAttribute], correlationId: Int64?)
|
||||
|
||||
public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage {
|
||||
switch self {
|
||||
case let .message(text, attributes, mediaReference, _, localGroupingKey):
|
||||
return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey)
|
||||
case let .message(text, attributes, mediaReference, _, localGroupingKey, correlationId):
|
||||
return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)
|
||||
case .forward:
|
||||
return self
|
||||
}
|
||||
@ -25,21 +25,41 @@ public enum EnqueueMessage {
|
||||
|
||||
public func withUpdatedAttributes(_ f: ([MessageAttribute]) -> [MessageAttribute]) -> EnqueueMessage {
|
||||
switch self {
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey):
|
||||
return .message(text: text, attributes: f(attributes), mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey)
|
||||
case let .forward(source, grouping, attributes):
|
||||
return .forward(source: source, grouping: grouping, attributes: f(attributes))
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId):
|
||||
return .message(text: text, attributes: f(attributes), mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)
|
||||
case let .forward(source, grouping, attributes, correlationId):
|
||||
return .forward(source: source, grouping: grouping, attributes: f(attributes), correlationId: correlationId)
|
||||
}
|
||||
}
|
||||
|
||||
public func withUpdatedGroupingKey(_ f: (Int64?) -> Int64?) -> EnqueueMessage {
|
||||
switch self {
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey):
|
||||
return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey))
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId):
|
||||
return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey), correlationId: correlationId)
|
||||
case .forward:
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
public func withUpdatedCorrelationId(_ value: Int64?) -> EnqueueMessage {
|
||||
switch self {
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, _):
|
||||
return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: value)
|
||||
case let .forward(source, grouping, attributes, _):
|
||||
return .forward(source: source, grouping: grouping, attributes: attributes, correlationId: value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension EnqueueMessage {
|
||||
var correlationId: Int64? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, correlationId):
|
||||
return correlationId
|
||||
case let .forward(_, _, _, correlationId):
|
||||
return correlationId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func augmentMediaWithReference(_ mediaReference: AnyMediaReference) -> Media {
|
||||
@ -62,9 +82,9 @@ func augmentMediaWithReference(_ mediaReference: AnyMediaReference) -> Media {
|
||||
|
||||
private func convertForwardedMediaForSecretChat(_ media: Media) -> Media {
|
||||
if let file = media as? TelegramMediaFile {
|
||||
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: arc4random64()), partialReference: file.partialReference, resource: file.resource, previewRepresentations: file.previewRepresentations, videoThumbnails: file.videoThumbnails, immediateThumbnailData: file.immediateThumbnailData, mimeType: file.mimeType, size: file.size, attributes: file.attributes)
|
||||
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: file.partialReference, resource: file.resource, previewRepresentations: file.previewRepresentations, videoThumbnails: file.videoThumbnails, immediateThumbnailData: file.immediateThumbnailData, mimeType: file.mimeType, size: file.size, attributes: file.attributes)
|
||||
} else if let image = media as? TelegramMediaImage {
|
||||
return TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()), representations: image.representations, immediateThumbnailData: image.immediateThumbnailData, reference: image.reference, partialReference: image.partialReference, flags: [])
|
||||
return TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: image.representations, immediateThumbnailData: image.immediateThumbnailData, reference: image.reference, partialReference: image.partialReference, flags: [])
|
||||
} else {
|
||||
return media
|
||||
}
|
||||
@ -139,7 +159,7 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox:
|
||||
var hasMedia = false
|
||||
loop: for message in messages {
|
||||
switch message {
|
||||
case let .message(_, _, mediaReference, _, _):
|
||||
case let .message(_, _, mediaReference, _, _, _):
|
||||
if mediaReference != nil {
|
||||
hasMedia = true
|
||||
break loop
|
||||
@ -156,14 +176,14 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox:
|
||||
var signals: [Signal<(Bool, EnqueueMessage), NoError>] = []
|
||||
for message in messages {
|
||||
switch message {
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey):
|
||||
case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId):
|
||||
if let mediaReference = mediaReference {
|
||||
signals.append(opportunisticallyTransformMessageWithMedia(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, mediaReference: mediaReference, userInteractive: userInteractive)
|
||||
|> map { result -> (Bool, EnqueueMessage) in
|
||||
if let result = result {
|
||||
return (true, .message(text: text, attributes: attributes, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey))
|
||||
return (true, .message(text: text, attributes: attributes, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId))
|
||||
} else {
|
||||
return (false, .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey))
|
||||
return (false, .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -235,7 +255,7 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<
|
||||
}
|
||||
}
|
||||
|
||||
messages.append(.message(text: message.text, attributes: filteredAttributes, mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey))
|
||||
messages.append(.message(text: message.text, attributes: filteredAttributes, mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey, correlationId: nil))
|
||||
}
|
||||
}
|
||||
let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages.map { (false, $0) })
|
||||
@ -258,7 +278,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
}
|
||||
}
|
||||
switch message {
|
||||
case let .message(_, _, _, replyToMessageId, _):
|
||||
case let .message(_, _, _, replyToMessageId, _, _):
|
||||
if let replyToMessageId = replyToMessageId, replyToMessageId.peerId != peerId, let replyMessage = transaction.getMessage(replyToMessageId) {
|
||||
var canBeForwarded = true
|
||||
if replyMessage.id.namespace != Namespaces.Message.Cloud {
|
||||
@ -271,10 +291,10 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
}
|
||||
}
|
||||
if canBeForwarded {
|
||||
updatedMessages.append((true, .forward(source: replyToMessageId, grouping: .none, attributes: [])))
|
||||
updatedMessages.append((true, .forward(source: replyToMessageId, grouping: .none, attributes: [], correlationId: nil)))
|
||||
}
|
||||
}
|
||||
case let .forward(sourceId, _, _):
|
||||
case let .forward(sourceId, _, _, _):
|
||||
if let sourceMessage = forwardedMessageToBeReuploaded(transaction: transaction, id: sourceId) {
|
||||
var mediaReference: AnyMediaReference?
|
||||
if sourceMessage.id.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
@ -282,7 +302,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
mediaReference = .standalone(media: media)
|
||||
}
|
||||
}
|
||||
updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil)))
|
||||
updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)))
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
@ -319,11 +339,11 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
if transformedMedia {
|
||||
infoFlags.insert(.transformedMedia)
|
||||
}
|
||||
attributes.append(OutgoingMessageInfoAttribute(uniqueId: randomId, flags: infoFlags, acknowledged: false))
|
||||
attributes.append(OutgoingMessageInfoAttribute(uniqueId: randomId, flags: infoFlags, acknowledged: false, correlationId: message.correlationId))
|
||||
globallyUniqueIds.append(randomId)
|
||||
|
||||
switch message {
|
||||
case let .message(text, requestedAttributes, mediaReference, replyToMessageId, localGroupingKey):
|
||||
case let .message(text, requestedAttributes, mediaReference, replyToMessageId, localGroupingKey, correlationId):
|
||||
var peerAutoremoveTimeout: Int32?
|
||||
if let peer = peer as? TelegramSecretChat {
|
||||
var isAction = false
|
||||
@ -495,7 +515,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
}
|
||||
|
||||
storeMessages.append(StoreMessage(peerId: peerId, namespace: messageNamespace, globallyUniqueId: randomId, groupingKey: localGroupingKey, threadId: threadId, timestamp: effectiveTimestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList))
|
||||
case let .forward(source, grouping, requestedAttributes):
|
||||
case let .forward(source, grouping, requestedAttributes, correlationId):
|
||||
let sourceMessage = transaction.getMessage(source)
|
||||
if let sourceMessage = sourceMessage, let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] {
|
||||
if let peer = peer as? TelegramSecretChat {
|
||||
@ -676,7 +696,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
if let generatedKey = localGroupingKeyBySourceKey[groupingKey] {
|
||||
localGroupingKey = generatedKey
|
||||
} else {
|
||||
let generatedKey = arc4random64()
|
||||
let generatedKey = Int64.random(in: Int64.min ... Int64.max)
|
||||
localGroupingKeyBySourceKey[groupingKey] = generatedKey
|
||||
localGroupingKey = generatedKey
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import SwiftSignalKit
|
||||
public func forwardGameWithScore(account: Account, messageId: MessageId, to peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
if let _ = transaction.getMessage(messageId), let fromPeer = transaction.getPeer(messageId.peerId), let fromInputPeer = apiInputPeer(fromPeer), let toPeer = transaction.getPeer(peerId), let toInputPeer = apiInputPeer(toPeer) {
|
||||
return account.network.request(Api.functions.messages.forwardMessages(flags: 1 << 8, fromPeer: fromInputPeer, id: [messageId.id], randomId: [arc4random64()], toPeer: toInputPeer, scheduleDate: nil))
|
||||
return account.network.request(Api.functions.messages.forwardMessages(flags: 1 << 8, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, scheduleDate: nil))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
|
||||
@ -157,6 +157,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
jsonParams = data
|
||||
}
|
||||
}
|
||||
let isVideoMuted = (flags & (1 << 14)) != 0
|
||||
parsedParticipants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: peer,
|
||||
ssrc: ssrc,
|
||||
@ -167,6 +168,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
activityRank: nil,
|
||||
muteState: muteState,
|
||||
isVideoMuted: isVideoMuted,
|
||||
volume: volume,
|
||||
about: about
|
||||
))
|
||||
@ -472,6 +474,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
jsonParams = data
|
||||
}
|
||||
}
|
||||
let isVideoMuted = (flags & (1 << 14)) != 0
|
||||
parsedParticipants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: peer,
|
||||
ssrc: ssrc,
|
||||
@ -482,6 +485,7 @@ public func getGroupCallParticipants(account: Account, callId: Int64, accessHash
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
activityRank: nil,
|
||||
muteState: muteState,
|
||||
isVideoMuted: isVideoMuted,
|
||||
volume: volume,
|
||||
about: about
|
||||
))
|
||||
@ -716,6 +720,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
|
||||
jsonParams = data
|
||||
}
|
||||
}
|
||||
let isVideoMuted = (flags & (1 << 14)) != 0
|
||||
if !state.participants.contains(where: { $0.peer.id == peer.id }) {
|
||||
state.participants.append(GroupCallParticipantsContext.Participant(
|
||||
peer: peer,
|
||||
@ -727,6 +732,7 @@ public func joinGroupCall(account: Account, peerId: PeerId, joinAs: PeerId?, cal
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
activityRank: nil,
|
||||
muteState: muteState,
|
||||
isVideoMuted: isVideoMuted,
|
||||
volume: volume,
|
||||
about: about
|
||||
))
|
||||
@ -880,6 +886,7 @@ public final class GroupCallParticipantsContext {
|
||||
public var activityTimestamp: Double?
|
||||
public var activityRank: Int?
|
||||
public var muteState: MuteState?
|
||||
public var isVideoMuted: Bool
|
||||
public var volume: Int32?
|
||||
public var about: String?
|
||||
|
||||
@ -893,6 +900,7 @@ public final class GroupCallParticipantsContext {
|
||||
activityTimestamp: Double?,
|
||||
activityRank: Int?,
|
||||
muteState: MuteState?,
|
||||
isVideoMuted: Bool,
|
||||
volume: Int32?,
|
||||
about: String?
|
||||
) {
|
||||
@ -905,6 +913,7 @@ public final class GroupCallParticipantsContext {
|
||||
self.activityTimestamp = activityTimestamp
|
||||
self.activityRank = activityRank
|
||||
self.muteState = muteState
|
||||
self.isVideoMuted = isVideoMuted
|
||||
self.volume = volume
|
||||
self.about = about
|
||||
}
|
||||
@ -945,6 +954,9 @@ public final class GroupCallParticipantsContext {
|
||||
if lhs.muteState != rhs.muteState {
|
||||
return false
|
||||
}
|
||||
if lhs.isVideoMuted != rhs.isVideoMuted {
|
||||
return false
|
||||
}
|
||||
if lhs.volume != rhs.volume {
|
||||
return false
|
||||
}
|
||||
@ -1128,6 +1140,7 @@ public final class GroupCallParticipantsContext {
|
||||
public var activityTimestamp: Double?
|
||||
public var raiseHandRating: Int64?
|
||||
public var muteState: Participant.MuteState?
|
||||
public var isVideoMuted: Bool
|
||||
public var participationStatusChange: ParticipationStatusChange
|
||||
public var volume: Int32?
|
||||
public var about: String?
|
||||
@ -1141,6 +1154,7 @@ public final class GroupCallParticipantsContext {
|
||||
activityTimestamp: Double?,
|
||||
raiseHandRating: Int64?,
|
||||
muteState: Participant.MuteState?,
|
||||
isVideoMuted: Bool,
|
||||
participationStatusChange: ParticipationStatusChange,
|
||||
volume: Int32?,
|
||||
about: String?,
|
||||
@ -1153,6 +1167,7 @@ public final class GroupCallParticipantsContext {
|
||||
self.activityTimestamp = activityTimestamp
|
||||
self.raiseHandRating = raiseHandRating
|
||||
self.muteState = muteState
|
||||
self.isVideoMuted = isVideoMuted
|
||||
self.participationStatusChange = participationStatusChange
|
||||
self.volume = volume
|
||||
self.about = about
|
||||
@ -1690,6 +1705,7 @@ public final class GroupCallParticipantsContext {
|
||||
activityTimestamp: activityTimestamp,
|
||||
activityRank: previousActivityRank,
|
||||
muteState: muteState,
|
||||
isVideoMuted: participantUpdate.isVideoMuted,
|
||||
volume: volume,
|
||||
about: participantUpdate.about
|
||||
)
|
||||
@ -1767,7 +1783,7 @@ public final class GroupCallParticipantsContext {
|
||||
}))
|
||||
}
|
||||
|
||||
public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?, volume: Int32?, raiseHand: Bool?) {
|
||||
public func updateMuteState(peerId: PeerId, muteState: Participant.MuteState?, isVideoMuted: Bool?, volume: Int32?, raiseHand: Bool?) {
|
||||
if let current = self.stateValue.overlayState.pendingMuteStateChanges[peerId] {
|
||||
if current.state == muteState {
|
||||
return
|
||||
@ -1814,8 +1830,15 @@ public final class GroupCallParticipantsContext {
|
||||
if let volume = volume, volume > 0 {
|
||||
flags |= 1 << 1
|
||||
}
|
||||
var muted: Api.Bool?
|
||||
if let muteState = muteState, (!muteState.canUnmute || peerId == myPeerId || muteState.mutedByYou) {
|
||||
flags |= 1 << 0
|
||||
muted = .boolTrue
|
||||
}
|
||||
var videoMuted: Api.Bool?
|
||||
if let isVideoMuted = isVideoMuted {
|
||||
videoMuted = isVideoMuted ? .boolTrue : .boolFalse
|
||||
flags |= 1 << 3
|
||||
}
|
||||
let raiseHandApi: Api.Bool?
|
||||
if let raiseHand = raiseHand {
|
||||
@ -1825,7 +1848,7 @@ public final class GroupCallParticipantsContext {
|
||||
raiseHandApi = nil
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.phone.editGroupCallParticipant(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), participant: inputPeer, volume: volume, raiseHand: raiseHandApi))
|
||||
return account.network.request(Api.functions.phone.editGroupCallParticipant(flags: flags, call: .inputGroupCall(id: id, accessHash: accessHash), participant: inputPeer, muted: muted, volume: volume, raiseHand: raiseHandApi, videoMuted: videoMuted))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
@ -1866,11 +1889,11 @@ public final class GroupCallParticipantsContext {
|
||||
}
|
||||
|
||||
public func raiseHand() {
|
||||
self.updateMuteState(peerId: self.myPeerId, muteState: nil, volume: nil, raiseHand: true)
|
||||
self.updateMuteState(peerId: self.myPeerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: true)
|
||||
}
|
||||
|
||||
public func lowerHand() {
|
||||
self.updateMuteState(peerId: self.myPeerId, muteState: nil, volume: nil, raiseHand: false)
|
||||
self.updateMuteState(peerId: self.myPeerId, muteState: nil, isVideoMuted: nil, volume: nil, raiseHand: false)
|
||||
}
|
||||
|
||||
public func updateShouldBeRecording(_ shouldBeRecording: Bool, title: String?) {
|
||||
@ -1985,6 +2008,7 @@ extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
|
||||
jsonParams = data
|
||||
}
|
||||
}
|
||||
let isVideoMuted = (flags & (1 << 14)) != 0
|
||||
|
||||
self.init(
|
||||
peerId: peerId,
|
||||
@ -1994,6 +2018,7 @@ extension GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate {
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
raiseHandRating: raiseHandRating,
|
||||
muteState: muteState,
|
||||
isVideoMuted: isVideoMuted,
|
||||
participationStatusChange: participationStatusChange,
|
||||
volume: volume,
|
||||
about: about,
|
||||
@ -2041,6 +2066,7 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
|
||||
jsonParams = data
|
||||
}
|
||||
}
|
||||
let isVideoMuted = (flags & (1 << 14)) != 0
|
||||
|
||||
participantUpdates.append(GroupCallParticipantsContext.Update.StateUpdate.ParticipantUpdate(
|
||||
peerId: peerId,
|
||||
@ -2050,6 +2076,7 @@ extension GroupCallParticipantsContext.Update.StateUpdate {
|
||||
activityTimestamp: activeDate.flatMap(Double.init),
|
||||
raiseHandRating: raiseHandRating,
|
||||
muteState: muteState,
|
||||
isVideoMuted: isVideoMuted,
|
||||
participationStatusChange: participationStatusChange,
|
||||
volume: volume,
|
||||
about: about,
|
||||
|
||||
@ -12,7 +12,7 @@ public enum InternalUpdaterError {
|
||||
}
|
||||
|
||||
public func requestUpdatesXml(account: Account, source: String) -> Signal<Data, InternalUpdaterError> {
|
||||
return resolvePeerByName(account: account, name: source)
|
||||
return TelegramEngine(account: account).peers.resolvePeerByName(name: source)
|
||||
|> castError(InternalUpdaterError.self)
|
||||
|> mapToSignal { peerId -> Signal<Peer?, InternalUpdaterError> in
|
||||
return account.postbox.transaction { transaction in
|
||||
@ -79,7 +79,7 @@ public enum AppUpdateDownloadResult {
|
||||
}
|
||||
|
||||
public func downloadAppUpdate(account: Account, source: String, messageId: Int32) -> Signal<AppUpdateDownloadResult, InternalUpdaterError> {
|
||||
return resolvePeerByName(account: account, name: source)
|
||||
return TelegramEngine(account: account).peers.resolvePeerByName(name: source)
|
||||
|> castError(InternalUpdaterError.self)
|
||||
|> mapToSignal { peerId -> Signal<Peer?, InternalUpdaterError> in
|
||||
return account.postbox.transaction { transaction in
|
||||
|
||||
@ -32,7 +32,7 @@ public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageI
|
||||
var globallyUniqueIds: [Int64] = []
|
||||
if let globallyUniqueId = message.globallyUniqueId {
|
||||
globallyUniqueIds.append(globallyUniqueId)
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: message.id.peerId, operation: SecretChatOutgoingOperationContents.readMessagesContent(layer: layer, actionGloballyUniqueId: arc4random64(), globallyUniqueIds: globallyUniqueIds), state: state)
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: message.id.peerId, operation: SecretChatOutgoingOperationContents.readMessagesContent(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), globallyUniqueIds: globallyUniqueIds), state: state)
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(message.id.peerId, state: updatedState)
|
||||
}
|
||||
@ -75,7 +75,7 @@ public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageI
|
||||
}
|
||||
|
||||
if let state = state, let layer = layer, let globallyUniqueId = message.globallyUniqueId {
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: messageId.peerId, operation: .readMessagesContent(layer: layer, actionGloballyUniqueId: arc4random64(), globallyUniqueIds: [globallyUniqueId]), state: state)
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: messageId.peerId, operation: .readMessagesContent(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), globallyUniqueIds: [globallyUniqueId]), state: state)
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(messageId.peerId, state: updatedState)
|
||||
}
|
||||
@ -106,7 +106,7 @@ public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageI
|
||||
}
|
||||
|
||||
if let state = state, let layer = layer, let globallyUniqueId = message.globallyUniqueId {
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: messageId.peerId, operation: .readMessagesContent(layer: layer, actionGloballyUniqueId: arc4random64(), globallyUniqueIds: [globallyUniqueId]), state: state)
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: messageId.peerId, operation: .readMessagesContent(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), globallyUniqueIds: [globallyUniqueId]), state: state)
|
||||
if updatedState != state {
|
||||
transaction.setPeerChatState(messageId.peerId, state: updatedState)
|
||||
}
|
||||
|
||||
@ -445,7 +445,7 @@ private final class MultipartFetchManager {
|
||||
init(resource: TelegramMediaResource, parameters: MediaResourceFetchParameters?, size: Int?, intervals: Signal<[(Range<Int>, MediaBoxFetchPriority)], NoError>, encryptionKey: SecretFileEncryptionKey?, decryptedSize: Int32?, location: MultipartFetchMasterLocation, postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext, partReady: @escaping (Int, Data) -> Void, reportCompleteSize: @escaping (Int) -> Void) {
|
||||
self.resource = resource
|
||||
self.parameters = parameters
|
||||
self.consumerId = arc4random64()
|
||||
self.consumerId = Int64.random(in: Int64.min ... Int64.max)
|
||||
|
||||
self.completeSize = size
|
||||
if let size = size {
|
||||
|
||||
@ -395,7 +395,7 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload
|
||||
|
||||
let uploadInterface: Signal<UploadInterface, NoError>
|
||||
if useMultiplexedRequests {
|
||||
uploadInterface = .single(.multiplexed(manager: network.multiplexedRequestManager, datacenterId: network.datacenterId, consumerId: arc4random64()))
|
||||
uploadInterface = .single(.multiplexed(manager: network.multiplexedRequestManager, datacenterId: network.datacenterId, consumerId: Int64.random(in: Int64.min ... Int64.max)))
|
||||
} else {
|
||||
uploadInterface = network.upload(tag: tag)
|
||||
|> map { download -> UploadInterface in
|
||||
|
||||
@ -4,7 +4,7 @@ import SwiftSignalKit
|
||||
import SyncCore
|
||||
|
||||
|
||||
public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: ChatContextResultCollection, result: ChatContextResult, hideVia: Bool = false, scheduleTime: Int32? = nil) -> EnqueueMessage? {
|
||||
public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: ChatContextResultCollection, result: ChatContextResult, hideVia: Bool = false, scheduleTime: Int32? = nil, correlationId: Int64? = nil) -> EnqueueMessage? {
|
||||
var attributes: [MessageAttribute] = []
|
||||
attributes.append(OutgoingChatContextResultMessageAttribute(queryId: result.queryId, id: result.id, hideVia: hideVia))
|
||||
if !hideVia {
|
||||
@ -32,19 +32,19 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha
|
||||
return true
|
||||
}
|
||||
if let media: Media = internalReference.file ?? internalReference.image {
|
||||
return .message(text: caption, attributes: filteredAttributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: filteredAttributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
} else {
|
||||
return .message(text: caption, attributes: filteredAttributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: filteredAttributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
}
|
||||
} else {
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
}
|
||||
} else if let file = internalReference.file, internalReference.type == "gif" {
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
} else if let image = internalReference.image {
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: image), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: image), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
} else if let file = internalReference.file {
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -56,9 +56,9 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha
|
||||
let thumbnailResource = thumbnail.resource
|
||||
let imageDimensions = thumbnail.dimensions ?? PixelDimensions(width: 128, height: 128)
|
||||
let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: [TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: tmpImage), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: tmpImage), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
} else {
|
||||
return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
}
|
||||
} else if externalReference.type == "document" || externalReference.type == "gif" || externalReference.type == "audio" || externalReference.type == "voice" {
|
||||
var videoThumbnails: [TelegramMediaFile.VideoThumbnail] = []
|
||||
@ -118,9 +118,9 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha
|
||||
}
|
||||
|
||||
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: nil, mimeType: externalReference.content?.mimeType ?? "application/binary", size: nil, attributes: fileAttributes)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
} else {
|
||||
return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
}
|
||||
}
|
||||
case let .text(text, entities, disableUrlPreview, replyMarkup):
|
||||
@ -130,21 +130,21 @@ public func outgoingMessageWithChatContextResult(to peerId: PeerId, results: Cha
|
||||
if let replyMarkup = replyMarkup {
|
||||
attributes.append(replyMarkup)
|
||||
}
|
||||
return .message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
case let .mapLocation(media, replyMarkup):
|
||||
if let replyMarkup = replyMarkup {
|
||||
attributes.append(replyMarkup)
|
||||
}
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
case let .contact(media, replyMarkup):
|
||||
if let replyMarkup = replyMarkup {
|
||||
attributes.append(replyMarkup)
|
||||
}
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
case let .invoice(media, replyMarkup):
|
||||
if let replyMarkup = replyMarkup {
|
||||
attributes.append(replyMarkup)
|
||||
}
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil)
|
||||
return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ public func peerSpecificStickerPack(postbox: Postbox, network: Network, peerId:
|
||||
return signal
|
||||
|> mapToSignal { info, canInstall -> Signal<PeerSpecificStickerPackData, NoError> in
|
||||
if let info = info.info {
|
||||
return cachedStickerPack(postbox: postbox, network: network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceRemote: false)
|
||||
return _internal_cachedStickerPack(postbox: postbox, network: network, reference: .id(id: info.id.id, accessHash: info.accessHash), forceRemote: false)
|
||||
|> map { result -> PeerSpecificStickerPackData in
|
||||
if case let .result(info, items, _) = result {
|
||||
return PeerSpecificStickerPackData(packInfo: (info, items), canSetup: canInstall)
|
||||
|
||||
@ -374,7 +374,7 @@ private func uploadedMediaImageContent(network: Network, postbox: Postbox, trans
|
||||
let attribute = updatedAttributes[index] as! OutgoingMessageInfoAttribute
|
||||
updatedAttributes[index] = attribute.withUpdatedFlags(attribute.flags.union([.transformedMedia]))
|
||||
} else {
|
||||
updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: arc4random64(), flags: [.transformedMedia], acknowledged: false))
|
||||
updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: Int64.random(in: Int64.min ... Int64.max), flags: [.transformedMedia], acknowledged: false, correlationId: nil))
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: currentMessage.media))
|
||||
})
|
||||
@ -664,7 +664,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
||||
let attribute = updatedAttributes[index] as! OutgoingMessageInfoAttribute
|
||||
updatedAttributes[index] = attribute.withUpdatedFlags(attribute.flags.union([.transformedMedia]))
|
||||
} else {
|
||||
updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: arc4random64(), flags: [.transformedMedia], acknowledged: false))
|
||||
updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: Int64.random(in: Int64.min ... Int64.max), flags: [.transformedMedia], acknowledged: false, correlationId: nil))
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: currentMessage.media))
|
||||
})
|
||||
|
||||
@ -190,7 +190,7 @@ func processSecretChatIncomingDecryptedOperations(encryptionProvider: Encryption
|
||||
let role = updatedState.role
|
||||
let fromSeqNo: Int32 = (topProcessedCanonicalIncomingOperationIndex + 1) * 2 + (role == .creator ? 0 : 1)
|
||||
let toSeqNo: Int32 = (canonicalIncomingIndex - 1) * 2 + (role == .creator ? 0 : 1)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.resendOperations(layer: layer, actionGloballyUniqueId: arc4random64(), fromSeqNo: fromSeqNo, toSeqNo: toSeqNo), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.resendOperations(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), fromSeqNo: fromSeqNo, toSeqNo: toSeqNo), state: updatedState)
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
@ -204,7 +204,7 @@ func processSecretChatIncomingDecryptedOperations(encryptionProvider: Encryption
|
||||
let role = updatedState.role
|
||||
let fromSeqNo: Int32 = Int32(0 * 2) + (role == .creator ? Int32(0) : Int32(1))
|
||||
let toSeqNo: Int32 = (canonicalIncomingIndex - 1) * 2 + (role == .creator ? 0 : 1)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.resendOperations(layer: layer, actionGloballyUniqueId: arc4random64(), fromSeqNo: fromSeqNo, toSeqNo: toSeqNo), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.resendOperations(layer: layer, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), fromSeqNo: fromSeqNo, toSeqNo: toSeqNo), state: updatedState)
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
@ -230,15 +230,15 @@ func processSecretChatIncomingDecryptedOperations(encryptionProvider: Encryption
|
||||
if layerSupport >= 101 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer101, locallyRequestedLayer: 101, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer101, actionGloballyUniqueId: arc4random64(), layerSupport: 101), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer101, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), layerSupport: 101), state: updatedState)
|
||||
} else if layerSupport >= 73 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer73, locallyRequestedLayer: 73, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer73, actionGloballyUniqueId: arc4random64(), layerSupport: 101), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer73, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), layerSupport: 101), state: updatedState)
|
||||
} else if layerSupport >= 46 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer46, locallyRequestedLayer: 46, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer46, actionGloballyUniqueId: arc4random64(), layerSupport: 101), state: updatedState)
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer46, actionGloballyUniqueId: Int64.random(in: Int64.min ... Int64.max), layerSupport: 101), state: updatedState)
|
||||
} else {
|
||||
throw MessageParsingError.contentParsingError
|
||||
}
|
||||
@ -711,7 +711,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
if let file = file {
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -737,7 +737,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -752,7 +752,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
let parsedAttributes: [TelegramMediaFileAttribute] = [.Video(duration: Int(duration), size: PixelDimensions(width: w, height: h), flags: []), .FileName(fileName: "video.mov")]
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -792,7 +792,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: arc4random64()), content: .Pending(0, url)))
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: Int64.random(in: Int64.min ... Int64.max)), content: .Pending(0, url)))
|
||||
case let .decryptedMessageMediaGeoPoint(lat, long):
|
||||
parsedMedia.append(TelegramMediaMap(latitude: lat, longitude: long, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))
|
||||
case let .decryptedMessageMediaContact(phoneNumber, firstName, lastName, userId):
|
||||
@ -913,7 +913,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
if let file = file {
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -940,7 +940,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -971,7 +971,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
let parsedAttributes: [TelegramMediaFileAttribute] = [.Video(duration: Int(duration), size: PixelDimensions(width: w, height: h), flags: []), .FileName(fileName: "video.mov")]
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -1011,7 +1011,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: arc4random64()), content: .Pending(0, url)))
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: Int64.random(in: Int64.min ... Int64.max)), content: .Pending(0, url)))
|
||||
case let .decryptedMessageMediaGeoPoint(lat, long):
|
||||
parsedMedia.append(TelegramMediaMap(latitude: lat, longitude: long, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))
|
||||
case let .decryptedMessageMediaContact(phoneNumber, firstName, lastName, userId):
|
||||
@ -1151,7 +1151,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
if let file = file {
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -1178,7 +1178,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -1209,7 +1209,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
let parsedAttributes: [TelegramMediaFileAttribute] = [.Video(duration: Int(duration), size: PixelDimensions(width: w, height: h), flags: []), .FileName(fileName: "video.mov")]
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: thumbW, height: thumbH), resource: resource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
@ -1249,7 +1249,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: arc4random64()), content: .Pending(0, url)))
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: Int64.random(in: Int64.min ... Int64.max)), content: .Pending(0, url)))
|
||||
case let .decryptedMessageMediaGeoPoint(lat, long):
|
||||
parsedMedia.append(TelegramMediaMap(latitude: lat, longitude: long, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))
|
||||
case let .decryptedMessageMediaContact(phoneNumber, firstName, lastName, userId):
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
public func arc4random64() -> Int64 {
|
||||
var value: Int64 = 0
|
||||
arc4random_buf(&value, 8)
|
||||
return value
|
||||
}
|
||||
@ -12,7 +12,7 @@ public func requestPhoneNumber(account: Account, peerId: PeerId) -> Signal<Never
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .complete()
|
||||
}
|
||||
return account.network.request(Api.functions.messages.sendPhoneNumberRequest(peer: inputPeer, randomId: arc4random64()))
|
||||
return account.network.request(Api.functions.messages.sendPhoneNumberRequest(peer: inputPeer, randomId: Int64.random(in: Int64.min ... Int64.max)))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user