mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Animation experiment
This commit is contained in:
parent
ebb26bb22d
commit
065150e048
@ -522,6 +522,7 @@
|
|||||||
"Notification.Kicked" = "%@ removed %@";
|
"Notification.Kicked" = "%@ removed %@";
|
||||||
"Notification.CreatedChat" = "%@ created a group";
|
"Notification.CreatedChat" = "%@ created a group";
|
||||||
"Notification.CreatedChannel" = "Channel created";
|
"Notification.CreatedChannel" = "Channel created";
|
||||||
|
"Notification.CreatedGroup" = "Group created";
|
||||||
"Notification.CreatedChatWithTitle" = "%@ created the group \"%@\" ";
|
"Notification.CreatedChatWithTitle" = "%@ created the group \"%@\" ";
|
||||||
"Notification.Joined" = "%@ joined Telegram";
|
"Notification.Joined" = "%@ joined Telegram";
|
||||||
"Notification.ChangedGroupName" = "%@ changed group name to \"%@\" ";
|
"Notification.ChangedGroupName" = "%@ changed group name to \"%@\" ";
|
||||||
|
@ -72,8 +72,9 @@ public final class AnimatedStickerFrame {
|
|||||||
public let bytesPerRow: Int
|
public let bytesPerRow: Int
|
||||||
let index: Int
|
let index: Int
|
||||||
let isLastFrame: Bool
|
let isLastFrame: Bool
|
||||||
|
let totalFrames: Int
|
||||||
|
|
||||||
init(data: Data, type: AnimationRendererFrameType, width: Int, height: Int, bytesPerRow: Int, index: Int, isLastFrame: Bool) {
|
init(data: Data, type: AnimationRendererFrameType, width: Int, height: Int, bytesPerRow: Int, index: Int, isLastFrame: Bool, totalFrames: Int) {
|
||||||
self.data = data
|
self.data = data
|
||||||
self.type = type
|
self.type = type
|
||||||
self.width = width
|
self.width = width
|
||||||
@ -81,6 +82,7 @@ public final class AnimatedStickerFrame {
|
|||||||
self.bytesPerRow = bytesPerRow
|
self.bytesPerRow = bytesPerRow
|
||||||
self.index = index
|
self.index = index
|
||||||
self.isLastFrame = isLastFrame
|
self.isLastFrame = isLastFrame
|
||||||
|
self.totalFrames = totalFrames
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +257,7 @@ public final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let frameData = frameData, draw {
|
if let frameData = frameData, draw {
|
||||||
return AnimatedStickerFrame(data: frameData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: isLastFrame)
|
return AnimatedStickerFrame(data: frameData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: isLastFrame, totalFrames: self.frameCount)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -633,7 +635,7 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource
|
|||||||
self.currentFrame += 1
|
self.currentFrame += 1
|
||||||
if draw {
|
if draw {
|
||||||
if let cache = self.cache, let yuvData = cache.readUncompressedYuvFrame(index: frameIndex) {
|
if let cache = self.cache, let yuvData = cache.readUncompressedYuvFrame(index: frameIndex) {
|
||||||
return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: 0, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1)
|
return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: 0, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
||||||
} else {
|
} else {
|
||||||
var frameData = Data(count: self.bytesPerRow * self.height)
|
var frameData = Data(count: self.bytesPerRow * self.height)
|
||||||
frameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) -> Void in
|
frameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) -> Void in
|
||||||
@ -643,7 +645,7 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource
|
|||||||
if let cache = self.cache {
|
if let cache = self.cache {
|
||||||
cache.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData)
|
cache.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData)
|
||||||
}
|
}
|
||||||
return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1)
|
return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
@ -744,6 +746,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
private var reportedStarted = false
|
private var reportedStarted = false
|
||||||
|
|
||||||
public var completed: (Bool) -> Void = { _ in }
|
public var completed: (Bool) -> Void = { _ in }
|
||||||
|
public var frameUpdated: (Int, Int) -> Void = { _, _ in }
|
||||||
|
|
||||||
private let timer = Atomic<SwiftSignalKit.Timer?>(value: nil)
|
private let timer = Atomic<SwiftSignalKit.Timer?>(value: nil)
|
||||||
private let frameSource = Atomic<QueueLocalObject<AnimatedStickerFrameSourceWrapper>?>(value: nil)
|
private let frameSource = Atomic<QueueLocalObject<AnimatedStickerFrameSourceWrapper>?>(value: nil)
|
||||||
@ -966,6 +969,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
strongSelf.frameUpdated(frame.index, frame.totalFrames)
|
||||||
|
|
||||||
if frame.isLastFrame {
|
if frame.isLastFrame {
|
||||||
var stopped = false
|
var stopped = false
|
||||||
var stopNow = false
|
var stopNow = false
|
||||||
@ -1049,6 +1054,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
strongSelf.frameUpdated(frame.index, frame.totalFrames)
|
||||||
|
|
||||||
if frame.isLastFrame {
|
if frame.isLastFrame {
|
||||||
var stopped = false
|
var stopped = false
|
||||||
var stopNow = false
|
var stopNow = false
|
||||||
|
@ -17,6 +17,59 @@ import ConfettiEffect
|
|||||||
import TelegramUniversalVideoContent
|
import TelegramUniversalVideoContent
|
||||||
import SolidRoundedButtonNode
|
import SolidRoundedButtonNode
|
||||||
|
|
||||||
|
private final class ProgressEstimator {
|
||||||
|
private var samples: [(Double, Float)] = []
|
||||||
|
|
||||||
|
private var estimatedCompletion: Double?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSample(progress: Float) {
|
||||||
|
let timestamp = CACurrentMediaTime()
|
||||||
|
|
||||||
|
self.samples.append((CACurrentMediaTime(), progress))
|
||||||
|
|
||||||
|
self.samples = self.samples.filter({ $0.0 >= timestamp - 3.0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
func estimateETA() -> Double? {
|
||||||
|
if self.samples.count < 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalTime: Double = 0.0
|
||||||
|
var totalProgress: Double = 0.0
|
||||||
|
var lastProgress: Double = 0.0
|
||||||
|
var lastTimestamp: Double = 0.0
|
||||||
|
for i in 1 ..< samples.count {
|
||||||
|
totalTime += samples[i].0 - samples[i - 1].0
|
||||||
|
totalProgress += Double(samples[i].1 - samples[i - 1].1)
|
||||||
|
lastProgress = Double(samples[i].1)
|
||||||
|
lastTimestamp = samples[i].0
|
||||||
|
}
|
||||||
|
|
||||||
|
let remainingProgress = 1.0 - lastProgress
|
||||||
|
let timeOffset = CACurrentMediaTime() - lastTimestamp
|
||||||
|
let remainingTime = remainingProgress * totalTime / totalProgress - timeOffset
|
||||||
|
/*print("remainingProgress = \(remainingProgress)")
|
||||||
|
print("totalTime = \(totalTime)")
|
||||||
|
print("totalProgress = \(totalProgress)")
|
||||||
|
print("ETA = \(remainingProgress * totalTime / totalProgress) - \(timeOffset) = \(remainingTime)")*/
|
||||||
|
return max(0.0, remainingTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func markEstimatedCompletion() {
|
||||||
|
self.estimatedCompletion = CACurrentMediaTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
func markActualCompletion() {
|
||||||
|
if let estimatedCompletion = self.estimatedCompletion {
|
||||||
|
print("Estimator error: \(CACurrentMediaTime() - estimatedCompletion)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public final class ChatImportActivityScreen: ViewController {
|
public final class ChatImportActivityScreen: ViewController {
|
||||||
enum ImportError {
|
enum ImportError {
|
||||||
case generic
|
case generic
|
||||||
@ -57,6 +110,8 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
private var videoNode: UniversalVideoNode?
|
private var videoNode: UniversalVideoNode?
|
||||||
private var feedback: HapticFeedback?
|
private var feedback: HapticFeedback?
|
||||||
|
|
||||||
|
fileprivate var remainingAnimationSeconds: Double?
|
||||||
|
|
||||||
init(controller: ChatImportActivityScreen, context: AccountContext, totalBytes: Int) {
|
init(controller: ChatImportActivityScreen, context: AccountContext, totalBytes: Int) {
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -109,11 +164,11 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
|
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
|
||||||
|
|
||||||
if let path = getAppBundle().path(forResource: "HistoryImport", ofType: "tgs") {
|
if let path = getAppBundle().path(forResource: "HistoryImport", ofType: "tgs") {
|
||||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 170 * 2, height: 170 * 2, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
|
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 190 * 2, height: 190 * 2, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
|
||||||
self.animationNode.visibility = true
|
self.animationNode.visibility = true
|
||||||
}
|
}
|
||||||
if let path = getAppBundle().path(forResource: "HistoryImportDone", ofType: "tgs") {
|
if let path = getAppBundle().path(forResource: "HistoryImportDone", ofType: "tgs") {
|
||||||
self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 170 * 2, height: 170 * 2, playbackMode: .once, mode: .direct(cachePathPrefix: nil))
|
self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 190 * 2, height: 190 * 2, playbackMode: .once, mode: .direct(cachePathPrefix: nil))
|
||||||
self.doneAnimationNode.started = { [weak self] in
|
self.doneAnimationNode.started = { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -157,6 +212,16 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
strongSelf.doneAnimationNode.isHidden = false
|
strongSelf.doneAnimationNode.isHidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.animationNode.frameUpdated = { [weak self] index, totalCount in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let remainingSeconds = Double(totalCount - index) / 60.0
|
||||||
|
strongSelf.remainingAnimationSeconds = remainingSeconds
|
||||||
|
strongSelf.controller?.updateProgressEstimation()
|
||||||
|
}
|
||||||
|
|
||||||
if let path = getAppBundle().path(forResource: "BlankVideo", ofType: "m4v"), let size = fileSize(path) {
|
if let path = getAppBundle().path(forResource: "BlankVideo", ofType: "m4v"), let size = fileSize(path) {
|
||||||
let decoration = ChatBubbleVideoDecoration(corners: ImageCorners(), nativeSize: CGSize(width: 100.0, height: 100.0), contentMode: .aspectFit, backgroundColor: .black)
|
let decoration = ChatBubbleVideoDecoration(corners: ImageCorners(), nativeSize: CGSize(width: 100.0, height: 100.0), contentMode: .aspectFit, backgroundColor: .black)
|
||||||
|
|
||||||
@ -200,9 +265,9 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
let isFirstLayout = self.validLayout == nil
|
let isFirstLayout = self.validLayout == nil
|
||||||
self.validLayout = (layout, navigationHeight)
|
self.validLayout = (layout, navigationHeight)
|
||||||
|
|
||||||
let iconSize = CGSize(width: 170.0, height: 170.0)
|
let iconSize = CGSize(width: 190.0, height: 190.0)
|
||||||
let radialStatusSize = CGSize(width: 186.0, height: 186.0)
|
let radialStatusSize = CGSize(width: 186.0, height: 186.0)
|
||||||
let maxIconStatusSpacing: CGFloat = 62.0
|
let maxIconStatusSpacing: CGFloat = 46.0
|
||||||
let maxProgressTextSpacing: CGFloat = 33.0
|
let maxProgressTextSpacing: CGFloat = 33.0
|
||||||
let progressStatusSpacing: CGFloat = 14.0
|
let progressStatusSpacing: CGFloat = 14.0
|
||||||
let statusButtonSpacing: CGFloat = 19.0
|
let statusButtonSpacing: CGFloat = 19.0
|
||||||
@ -331,6 +396,10 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func transitionToDoneAnimation() {
|
||||||
|
self.animationNode.stopAtNearestLoop = true
|
||||||
|
}
|
||||||
|
|
||||||
func updateState(state: State, animated: Bool) {
|
func updateState(state: State, animated: Bool) {
|
||||||
var wasDone = false
|
var wasDone = false
|
||||||
if case .done = self.state {
|
if case .done = self.state {
|
||||||
@ -388,8 +457,6 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
self.feedback = HapticFeedback()
|
self.feedback = HapticFeedback()
|
||||||
}
|
}
|
||||||
self.feedback?.success()
|
self.feedback?.success()
|
||||||
|
|
||||||
self.animationNode.stopAtNearestLoop = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -409,6 +476,10 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
private let mainEntrySize: Int
|
private let mainEntrySize: Int
|
||||||
private let otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>)]
|
private let otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType, Promise<TempBoxFile?>)]
|
||||||
private let totalBytes: Int
|
private let totalBytes: Int
|
||||||
|
private let totalMediaBytes: Int
|
||||||
|
|
||||||
|
private var progressEstimator: ProgressEstimator?
|
||||||
|
private var beganCompletion: Bool = false
|
||||||
|
|
||||||
private var pendingEntries: [String: (Int, Float)] = [:]
|
private var pendingEntries: [String: (Int, Float)] = [:]
|
||||||
|
|
||||||
@ -458,11 +529,12 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
self.pendingEntries[fileName] = (Int(entry.uncompressedSize), 0.0)
|
self.pendingEntries[fileName] = (Int(entry.uncompressedSize), 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalBytes: Int = self.mainEntrySize
|
var totalMediaBytes = 0
|
||||||
for entry in self.otherEntries {
|
for entry in self.otherEntries {
|
||||||
totalBytes += Int(entry.0.uncompressedSize)
|
totalMediaBytes += Int(entry.0.uncompressedSize)
|
||||||
}
|
}
|
||||||
self.totalBytes = totalBytes
|
self.totalBytes = self.mainEntrySize + totalMediaBytes
|
||||||
|
self.totalMediaBytes = totalMediaBytes
|
||||||
|
|
||||||
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
@ -516,6 +588,9 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
self.pendingEntries[key] = (value.0, 0.0)
|
self.pendingEntries[key] = (value.0, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.progressEstimator = ProgressEstimator()
|
||||||
|
self.beganCompletion = false
|
||||||
|
|
||||||
self.controllerNode.updateState(state: .progress(0.0), animated: true)
|
self.controllerNode.updateState(state: .progress(0.0), animated: true)
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
@ -612,16 +687,28 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalDoneBytes = strongSelf.mainEntrySize
|
var totalDoneMediaBytes = 0
|
||||||
for (_, sizeAndProgress) in strongSelf.pendingEntries {
|
for (_, sizeAndProgress) in strongSelf.pendingEntries {
|
||||||
totalDoneBytes += Int(Float(sizeAndProgress.0) * sizeAndProgress.1)
|
totalDoneMediaBytes += Int(Float(sizeAndProgress.0) * sizeAndProgress.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let totalDoneBytes = strongSelf.mainEntrySize + totalDoneMediaBytes
|
||||||
|
|
||||||
var totalProgress: CGFloat = 1.0
|
var totalProgress: CGFloat = 1.0
|
||||||
if !strongSelf.otherEntries.isEmpty {
|
if !strongSelf.otherEntries.isEmpty {
|
||||||
totalProgress = CGFloat(totalDoneBytes) / CGFloat(strongSelf.totalBytes)
|
totalProgress = CGFloat(totalDoneBytes) / CGFloat(strongSelf.totalBytes)
|
||||||
}
|
}
|
||||||
|
var totalMediaProgress: CGFloat = 1.0
|
||||||
|
if !strongSelf.otherEntries.isEmpty {
|
||||||
|
totalProgress = CGFloat(totalDoneBytes) / CGFloat(strongSelf.totalBytes)
|
||||||
|
totalMediaProgress = CGFloat(totalDoneMediaBytes) / CGFloat(strongSelf.totalMediaBytes)
|
||||||
|
}
|
||||||
strongSelf.controllerNode.updateState(state: .progress(totalProgress), animated: true)
|
strongSelf.controllerNode.updateState(state: .progress(totalProgress), animated: true)
|
||||||
|
|
||||||
|
if let progressEstimator = strongSelf.progressEstimator {
|
||||||
|
progressEstimator.addSample(progress: Float(totalMediaProgress))
|
||||||
|
strongSelf.updateProgressEstimation()
|
||||||
|
}
|
||||||
}, error: { [weak self] error in
|
}, error: { [weak self] error in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -638,4 +725,14 @@ public final class ChatImportActivityScreen: ViewController {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate func updateProgressEstimation() {
|
||||||
|
if !self.beganCompletion, let progressEstimator = self.progressEstimator, let remainingAnimationSeconds = self.controllerNode.remainingAnimationSeconds {
|
||||||
|
if let eta = progressEstimator.estimateETA(), eta <= remainingAnimationSeconds + 1.5 {
|
||||||
|
self.beganCompletion = true
|
||||||
|
progressEstimator.markEstimatedCompletion()
|
||||||
|
self.controllerNode.transitionToDoneAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,12 +262,12 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
hideAuthor = true
|
hideAuthor = true
|
||||||
if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId) {
|
if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId, forChatList: true) {
|
||||||
messageText = text
|
messageText = text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case _ as TelegramMediaExpiredContent:
|
case _ as TelegramMediaExpiredContent:
|
||||||
if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId) {
|
if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId, forChatList: true) {
|
||||||
messageText = text
|
messageText = text
|
||||||
}
|
}
|
||||||
case let poll as TelegramMediaPoll:
|
case let poll as TelegramMediaPoll:
|
||||||
|
@ -171,7 +171,7 @@ private final class MultipartUploadManager {
|
|||||||
self.bigParts = true
|
self.bigParts = true
|
||||||
} else if useLargerParts {
|
} else if useLargerParts {
|
||||||
self.bigParts = false
|
self.bigParts = false
|
||||||
self.defaultPartSize = 192 * 1024
|
self.defaultPartSize = 128 * 1024
|
||||||
self.bigTotalParts = nil
|
self.bigTotalParts = nil
|
||||||
} else {
|
} else {
|
||||||
self.bigParts = false
|
self.bigParts = false
|
||||||
@ -210,7 +210,7 @@ private final class MultipartUploadManager {
|
|||||||
} else {
|
} else {
|
||||||
self.bigParts = false
|
self.bigParts = false
|
||||||
if self.useLargerParts {
|
if self.useLargerParts {
|
||||||
self.defaultPartSize = 192 * 1024
|
self.defaultPartSize = 128 * 1024
|
||||||
} else {
|
} else {
|
||||||
self.defaultPartSize = 16 * 1024
|
self.defaultPartSize = 16 * 1024
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -163,7 +163,7 @@ public func mediaContentKind(_ media: Media, message: Message? = nil, strings: P
|
|||||||
}
|
}
|
||||||
case _ as TelegramMediaAction:
|
case _ as TelegramMediaAction:
|
||||||
if let message = message, let strings = strings, let nameDisplayOrder = nameDisplayOrder, let accountPeerId = accountPeerId {
|
if let message = message, let strings = strings, let nameDisplayOrder = nameDisplayOrder, let accountPeerId = accountPeerId {
|
||||||
return .text(plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId) ?? "")
|
return .text(plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId, forChatList: false) ?? "")
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,11 @@ private func peerMentionsAttributes(primaryTextColor: UIColor, peerIds: [(Int, P
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, message: Message, accountPeerId: PeerId) -> String? {
|
public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, message: Message, accountPeerId: PeerId, forChatList: Bool) -> String? {
|
||||||
return universalServiceMessageString(presentationData: nil, strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId)?.string
|
return universalServiceMessageString(presentationData: nil, strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId, forChatList: forChatList)?.string
|
||||||
}
|
}
|
||||||
|
|
||||||
public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, message: Message, accountPeerId: PeerId) -> NSAttributedString? {
|
public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, message: Message, accountPeerId: PeerId, forChatList: Bool) -> NSAttributedString? {
|
||||||
var attributedString: NSAttributedString?
|
var attributedString: NSAttributedString?
|
||||||
|
|
||||||
let primaryTextColor: UIColor
|
let primaryTextColor: UIColor
|
||||||
@ -56,9 +56,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
case let .groupCreated(title):
|
case let .groupCreated(title):
|
||||||
if isChannel {
|
if isChannel {
|
||||||
attributedString = NSAttributedString(string: strings.Notification_CreatedChannel, font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: strings.Notification_CreatedChannel, font: titleFont, textColor: primaryTextColor)
|
||||||
|
} else {
|
||||||
|
if forChatList {
|
||||||
|
attributedString = NSAttributedString(string: strings.Notification_CreatedGroup, font: titleFont, textColor: primaryTextColor)
|
||||||
} else {
|
} else {
|
||||||
attributedString = addAttributesToStringWithRanges(strings.Notification_CreatedChatWithTitle(authorName, title), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)]))
|
attributedString = addAttributesToStringWithRanges(strings.Notification_CreatedChatWithTitle(authorName, title), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)]))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case let .addedMembers(peerIds):
|
case let .addedMembers(peerIds):
|
||||||
if let peerId = peerIds.first, peerId == message.author?.id {
|
if let peerId = peerIds.first, peerId == message.author?.id {
|
||||||
if let peer = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = peer.info {
|
if let peer = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -19,7 +19,7 @@ import TelegramUniversalVideoContent
|
|||||||
import GalleryUI
|
import GalleryUI
|
||||||
|
|
||||||
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, message: Message, accountPeerId: PeerId) -> NSAttributedString? {
|
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, message: Message, accountPeerId: PeerId) -> NSAttributedString? {
|
||||||
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId)
|
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, message: message, accountPeerId: accountPeerId, forChatList: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
|
class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user