mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Merge commit 'adc3f4b44aa589826862cc379b577dab0dfe40f2'
This commit is contained in:
commit
23c518a933
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/VoiceHand_10.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/VoiceHand_10.tgs
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/VoiceHand_8.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/VoiceHand_8.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/VoiceHand_9.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/VoiceHand_9.tgs
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6340,7 +6340,8 @@ Sorry for the inconvenience.";
|
||||
"VoiceChat.PinVideo" = "Pin Video";
|
||||
"VoiceChat.UnpinVideo" = "Unpin Video";
|
||||
|
||||
"Notification.VoiceChatScheduled" = "Voice chat scheduled for %@";
|
||||
"Notification.VoiceChatScheduledChannel" = "Voice chat scheduled for %@";
|
||||
"Notification.VoiceChatScheduled" = "%1$@ Voice chat scheduled for %2$@";
|
||||
|
||||
"VoiceChat.StartsIn" = "Starts in";
|
||||
"VoiceChat.LateBy" = "Late by";
|
||||
|
@ -347,7 +347,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
||||
var title: String = ""
|
||||
var speakerSubtitle: String = ""
|
||||
|
||||
let textFont = Font.regular(13.0)
|
||||
let textFont = Font.with(size: 13.0, design: .regular, weight: .regular, traits: [.monospacedNumbers])
|
||||
let textColor = UIColor.white
|
||||
var segments: [AnimatedCountLabelNode.Segment] = []
|
||||
var displaySpeakerSubtitle = false
|
||||
@ -381,7 +381,22 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
||||
}
|
||||
displaySpeakerSubtitle = speakerSubtitle != title && !speakerSubtitle.isEmpty
|
||||
|
||||
if let membersCount = membersCount {
|
||||
var requiresTimer = false
|
||||
if let scheduleTime = self.currentGroupCallState?.info?.scheduleTimestamp {
|
||||
requiresTimer = true
|
||||
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
let elapsedTime = scheduleTime - currentTime
|
||||
let timerText: String
|
||||
if elapsedTime >= 86400 {
|
||||
timerText = timeIntervalString(strings: presentationData.strings, value: elapsedTime)
|
||||
} else if elapsedTime < 0 {
|
||||
timerText = presentationData.strings.VoiceChat_StatusLateBy(textForTimeout(value: abs(elapsedTime))).0
|
||||
} else {
|
||||
timerText = presentationData.strings.VoiceChat_StatusStartsIn(textForTimeout(value: elapsedTime)).0
|
||||
}
|
||||
segments.append(.text(0, NSAttributedString(string: timerText, font: textFont, textColor: textColor)))
|
||||
} else if let membersCount = membersCount {
|
||||
var membersPart = presentationData.strings.VoiceChat_Status_Members(membersCount)
|
||||
if membersPart.contains("[") && membersPart.contains("]") {
|
||||
if let startIndex = membersPart.firstIndex(of: "["), let endIndex = membersPart.firstIndex(of: "]") {
|
||||
@ -433,6 +448,19 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
||||
}
|
||||
|
||||
self.backgroundNode.connectingColor = color
|
||||
|
||||
if requiresTimer {
|
||||
if self.currentCallTimer == nil {
|
||||
let timer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: { [weak self] in
|
||||
self?.update()
|
||||
}, queue: Queue.mainQueue())
|
||||
timer.start()
|
||||
self.currentCallTimer = timer
|
||||
}
|
||||
} else if let currentCallTimer = self.currentCallTimer {
|
||||
self.currentCallTimer = nil
|
||||
currentCallTimer.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
if self.subtitleNode.segments != segments && !displaySpeakerSubtitle {
|
||||
|
@ -2068,7 +2068,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] myPeer in
|
||||
guard let strongSelf = self, let _ = myPeer else {
|
||||
guard let strongSelf = self, let myPeer = myPeer else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -2078,7 +2078,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
strongSelf.joinAsPeerId = peerId
|
||||
|
||||
if strongSelf.stateValue.scheduleTimestamp == nil {
|
||||
if strongSelf.stateValue.scheduleTimestamp != nil {
|
||||
strongSelf.stateValue.myPeerId = peerId
|
||||
strongSelf.reconnectedAsEventsPipe.putNext(myPeer)
|
||||
} else {
|
||||
strongSelf.reconnectingAsPeer = myPeer
|
||||
|
||||
if let participantsContext = strongSelf.participantsContext, let immediateState = participantsContext.immediateState {
|
||||
@ -2098,8 +2101,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
|
||||
strongSelf.requestCall(movingFromBroadcastToRtc: false)
|
||||
} else {
|
||||
strongSelf.stateValue.myPeerId = peerId
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -2224,7 +2225,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
self.isScheduledStarted = true
|
||||
self.stateValue.scheduleTimestamp = nil
|
||||
self.switchToTemporaryParticipantsContext(sourceContext: nil, oldMyPeerId: self.joinAsPeerId)
|
||||
|
||||
self.startDisposable.set((startScheduledGroupCall(account: self.account, peerId: self.peerId, callId: callInfo.id, accessHash: callInfo.accessHash)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] callInfo in
|
||||
@ -2447,7 +2447,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
|
||||
let account = self.account
|
||||
|
||||
let currentCall: Signal<GroupCallInfo?, CallError>
|
||||
if let initialCall = self.initialCall {
|
||||
currentCall = getCurrentGroupCall(account: account, callId: initialCall.id, accessHash: initialCall.accessHash)
|
||||
@ -2457,6 +2456,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|> map { summary -> GroupCallInfo? in
|
||||
return summary?.info
|
||||
}
|
||||
} else if case let .active(callInfo) = self.internalState {
|
||||
currentCall = getCurrentGroupCall(account: account, callId: callInfo.id, accessHash: callInfo.accessHash)
|
||||
|> mapError { _ -> CallError in
|
||||
return .generic
|
||||
}
|
||||
|> map { summary -> GroupCallInfo? in
|
||||
return summary?.info
|
||||
}
|
||||
} else {
|
||||
currentCall = .single(nil)
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
||||
let subtitleSize = self.subtitleLabel.updateLayout(CGSize(width: size.width, height: .greatestFiniteMagnitude))
|
||||
let totalHeight = titleSize.height + subtitleSize.height + 1.0
|
||||
|
||||
self.titleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: floor((size.height - totalHeight) / 2.0) + 88.0), size: titleSize)
|
||||
self.titleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: floor((size.height - totalHeight) / 2.0) + 84.0), size: titleSize)
|
||||
self.subtitleLabel.frame = CGRect(origin: CGPoint(x: floor((size.width - subtitleSize.width) / 2.0), y: self.titleLabel.frame.maxY + 1.0), size: subtitleSize)
|
||||
|
||||
self.bottomNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
@ -361,6 +361,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
||||
}
|
||||
|
||||
var backgroundState: VoiceChatActionButtonBackgroundNode.State
|
||||
var animated = true
|
||||
switch state {
|
||||
case let .button(text):
|
||||
backgroundState = .button
|
||||
@ -370,6 +371,9 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
||||
self.buttonTitleLabel.frame = CGRect(origin: CGPoint(x: floor((self.bounds.width - titleSize.width) / 2.0), y: floor((self.bounds.height - titleSize.height) / 2.0)), size: titleSize)
|
||||
case .scheduled:
|
||||
backgroundState = .disabled
|
||||
if previousState == .connecting {
|
||||
animated = false
|
||||
}
|
||||
case let .active(state):
|
||||
switch state {
|
||||
case .on:
|
||||
@ -385,7 +389,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
||||
self.applyIconParams()
|
||||
|
||||
self.backgroundNode.isDark = dark
|
||||
self.backgroundNode.update(state: backgroundState, animated: true)
|
||||
self.backgroundNode.update(state: backgroundState, animated: animated)
|
||||
|
||||
if case .active = state, let previousState = previousState, case .connecting = previousState, animated {
|
||||
self.activeDisposable.set((self.activePromise.get()
|
||||
@ -755,7 +759,7 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
||||
case muted
|
||||
}
|
||||
|
||||
func updateGlowAndGradientAnimations(type: Gradient, previousType: Gradient? = nil) {
|
||||
func updateGlowAndGradientAnimations(type: Gradient, previousType: Gradient? = nil, animated: Bool = true) {
|
||||
let effectivePreviousTyoe = previousType ?? .active
|
||||
|
||||
let scale: CGFloat
|
||||
@ -794,12 +798,14 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
||||
self.maskGradientLayer.transform = CATransform3DMakeScale(targetScale, targetScale, 1.0)
|
||||
if let _ = previousType {
|
||||
self.maskGradientLayer.animateScale(from: initialScale, to: targetScale, duration: 0.3)
|
||||
} else {
|
||||
} else if animated {
|
||||
self.maskGradientLayer.animateSpring(from: initialScale as NSNumber, to: targetScale as NSNumber, keyPath: "transform.scale", duration: 0.45)
|
||||
}
|
||||
|
||||
self.foregroundGradientLayer.colors = targetColors
|
||||
self.foregroundGradientLayer.animate(from: initialColors as AnyObject, to: targetColors as AnyObject, keyPath: "colors", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: 0.3)
|
||||
if animated {
|
||||
self.foregroundGradientLayer.animate(from: initialColors as AnyObject, to: targetColors as AnyObject, keyPath: "colors", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: 0.3)
|
||||
}
|
||||
}
|
||||
|
||||
private func playMuteAnimation() {
|
||||
@ -1081,6 +1087,16 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
||||
self.playMuteAnimation()
|
||||
}
|
||||
self.transition = nil
|
||||
} else {
|
||||
if self.maskBlobView.isHidden {
|
||||
self.updateGlowAndGradientAnimations(type: .muted, previousType: nil, animated: false)
|
||||
self.maskCircleLayer.isHidden = false
|
||||
self.maskProgressLayer.isHidden = true
|
||||
self.maskGradientLayer.isHidden = false
|
||||
self.maskBlobView.isHidden = false
|
||||
self.maskBlobView.startAnimating()
|
||||
self.maskBlobView.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.45)
|
||||
}
|
||||
}
|
||||
case .button:
|
||||
self.updatedActive?(true)
|
||||
@ -1537,7 +1553,6 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
|
||||
self.isColored = isColored
|
||||
super.init(size: CGSize(width: 100.0, height: 100.0))
|
||||
|
||||
self.scale = 0.8
|
||||
self.trackTo(item: ManagedAnimationItem(source: .local("VoiceUnmute"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.1))
|
||||
}
|
||||
|
||||
@ -1632,15 +1647,25 @@ final class VoiceChatActionButtonIconNode: ManagedAnimationNode {
|
||||
}
|
||||
|
||||
var useTiredAnimation = false
|
||||
var useAngryAnimation = false
|
||||
let val = Float.random(in: 0.0..<1.0)
|
||||
if val <= 0.01 {
|
||||
useTiredAnimation = true
|
||||
} else if val <= 0.05 {
|
||||
useAngryAnimation = true
|
||||
}
|
||||
|
||||
let normalAnimations = ["VoiceHand_1", "VoiceHand_2", "VoiceHand_3", "VoiceHand_4", "VoiceHand_7"]
|
||||
let normalAnimations = ["VoiceHand_1", "VoiceHand_2", "VoiceHand_3", "VoiceHand_4", "VoiceHand_7", "VoiceHand_8"]
|
||||
let tiredAnimations = ["VoiceHand_5", "VoiceHand_6"]
|
||||
let animations = useTiredAnimation ? tiredAnimations : normalAnimations
|
||||
|
||||
let angryAnimations = ["VoiceHand_9", "VoiceHand_10"]
|
||||
let animations: [String]
|
||||
if useTiredAnimation {
|
||||
animations = tiredAnimations
|
||||
} else if useAngryAnimation {
|
||||
animations = angryAnimations
|
||||
} else {
|
||||
animations = normalAnimations
|
||||
}
|
||||
if let animationName = animations.randomElement() {
|
||||
self.trackTo(item: ManagedAnimationItem(source: .local(animationName)))
|
||||
}
|
||||
|
@ -3220,7 +3220,7 @@ public final class VoiceChatController: ViewController {
|
||||
smallButtons = false
|
||||
firstButtonFrame = CGRect(origin: CGPoint(x: floor(leftButtonFrame.midX - cameraButtonSize.width / 2.0), y: leftButtonFrame.minY - upperButtonDistance - cameraButtonSize.height), size: cameraButtonSize)
|
||||
secondButtonFrame = leftButtonFrame
|
||||
thirdButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - centralButtonSize.width) / 2.0), y: floorToScreenPixels((self.effectiveBottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize)
|
||||
thirdButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - centralButtonSize.width) / 2.0), y: floor((self.effectiveBottomAreaHeight - centralButtonSize.height) / 2.0) - 3.0), size: centralButtonSize)
|
||||
forthButtonFrame = rightButtonFrame
|
||||
case let .fullscreen(controlsHidden):
|
||||
smallButtons = true
|
||||
@ -3910,8 +3910,9 @@ public final class VoiceChatController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: strongSelf.presentationData.strings.VoiceChat_EditTitleTitle, text: strongSelf.presentationData.strings.VoiceChat_EditTitleText, placeholder: chatPeer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), value: strongSelf.callState?.title, maxLength: 40, apply: { title in
|
||||
if let strongSelf = self, let title = title {
|
||||
let initialTitle = strongSelf.callState?.title ?? ""
|
||||
let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: strongSelf.presentationData.strings.VoiceChat_EditTitleTitle, text: strongSelf.presentationData.strings.VoiceChat_EditTitleText, placeholder: chatPeer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), value: initialTitle, maxLength: 40, apply: { title in
|
||||
if let strongSelf = self, let title = title, title != initialTitle {
|
||||
strongSelf.call.updateTitle(title)
|
||||
|
||||
strongSelf.presentUndoOverlay(content: .voiceChatFlag(text: title.isEmpty ? strongSelf.presentationData.strings.VoiceChat_EditTitleRemoveSuccess : strongSelf.presentationData.strings.VoiceChat_EditTitleSuccess(title).0), action: { _ in return false })
|
||||
|
@ -158,12 +158,12 @@ final class VoiceChatMicrophoneNode: ASDisplayNode {
|
||||
|
||||
context.setFillColor(parameters.color.cgColor)
|
||||
|
||||
var clearLineWidth: CGFloat = 4.0
|
||||
var clearLineWidth: CGFloat = 2.0
|
||||
var lineWidth: CGFloat = 1.0 + UIScreenPixel
|
||||
if bounds.size.width > 36.0 {
|
||||
context.scaleBy(x: 2.0, y: 2.0)
|
||||
} else if bounds.size.width < 30.0 {
|
||||
clearLineWidth = 3.0
|
||||
clearLineWidth = 2.0
|
||||
lineWidth = 1.0
|
||||
}
|
||||
|
||||
@ -207,18 +207,19 @@ final class VoiceChatMicrophoneNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
if parameters.reverse {
|
||||
startPoint = CGPoint(x: origin.x + length * (1.0 - parameters.transition), y: origin.y + length * (1.0 - parameters.transition))
|
||||
endPoint = CGPoint(x: origin.x + length, y: origin.y + length)
|
||||
startPoint = CGPoint(x: origin.x + length * (1.0 - parameters.transition), y: origin.y + length * (1.0 - parameters.transition)).offsetBy(dx: UIScreenPixel, dy: -UIScreenPixel)
|
||||
endPoint = CGPoint(x: origin.x + length, y: origin.y + length).offsetBy(dx: UIScreenPixel, dy: -UIScreenPixel)
|
||||
} else {
|
||||
startPoint = origin
|
||||
endPoint = CGPoint(x: origin.x + length * parameters.transition, y: origin.y + length * parameters.transition)
|
||||
startPoint = origin.offsetBy(dx: UIScreenPixel, dy: -UIScreenPixel)
|
||||
endPoint = CGPoint(x: origin.x + length * parameters.transition, y: origin.y + length * parameters.transition).offsetBy(dx: UIScreenPixel, dy: -UIScreenPixel)
|
||||
}
|
||||
|
||||
|
||||
context.setBlendMode(.clear)
|
||||
context.setLineWidth(clearLineWidth)
|
||||
|
||||
context.move(to: startPoint)
|
||||
context.addLine(to: endPoint)
|
||||
context.move(to: startPoint.offsetBy(dx: 0.0, dy: 1.0 + UIScreenPixel))
|
||||
context.addLine(to: endPoint.offsetBy(dx: 0.0, dy: 1.0 + UIScreenPixel))
|
||||
context.strokePath()
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
|
@ -169,7 +169,7 @@ public final class VoiceChatOverlayController: ViewController {
|
||||
|
||||
if reclaim {
|
||||
self.dismissed = true
|
||||
let targetPosition = CGPoint(x: layout.size.width / 2.0, y: layout.size.height - layout.intrinsicInsets.bottom - 205.0 / 2.0)
|
||||
let targetPosition = CGPoint(x: layout.size.width / 2.0, y: layout.size.height - layout.intrinsicInsets.bottom - 205.0 / 2.0 - 2.0)
|
||||
if self.isSlidOffscreen {
|
||||
self.isSlidOffscreen = false
|
||||
self.isButtonHidden = true
|
||||
|
@ -133,10 +133,8 @@ final class VoiceChatTimerNode: ASDisplayNode {
|
||||
let timerText: String
|
||||
if elapsedTime >= 86400 {
|
||||
timerText = timeIntervalString(strings: self.strings, value: elapsedTime)
|
||||
} else if elapsedTime < 0 {
|
||||
timerText = "\(textForTimeout(value: abs(elapsedTime)))"
|
||||
} else {
|
||||
timerText = textForTimeout(value: elapsedTime)
|
||||
timerText = textForTimeout(value: abs(elapsedTime))
|
||||
}
|
||||
|
||||
if self.updateTimer == nil {
|
||||
|
@ -79,7 +79,7 @@ public enum GetCurrentGroupCallError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
|
||||
public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
|
||||
return account.network.request(Api.functions.phone.getGroupCall(call: .inputGroupCall(id: callId, accessHash: accessHash)))
|
||||
|> mapError { _ -> GetCurrentGroupCallError in
|
||||
return .generic
|
||||
@ -92,6 +92,7 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
|
||||
@ -108,6 +109,17 @@ public func getCurrentGroupCall(account: Account, callId: Int64, accessHash: Int
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
if let peerId = peerId {
|
||||
transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in
|
||||
if let cachedData = current as? CachedChannelData {
|
||||
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall.init(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: cachedData.activeCall?.subscribedToScheduled ?? false))
|
||||
} else if let cachedData = current as? CachedGroupData {
|
||||
return cachedData.withUpdatedActiveCall(CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: cachedData.activeCall?.subscribedToScheduled ?? false))
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||
return updated
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -449,8 +449,14 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
case let .groupPhoneCall(_, _, scheduleDate, duration):
|
||||
if let scheduleDate = scheduleDate {
|
||||
let timeString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate)
|
||||
let titleString = strings.Notification_VoiceChatScheduled(timeString).0
|
||||
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
|
||||
if message.author?.id.namespace == Namespaces.Peer.CloudChannel {
|
||||
let titleString = strings.Notification_VoiceChatScheduledChannel(timeString).0
|
||||
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
|
||||
} else {
|
||||
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
|
||||
let titleString = strings.Notification_VoiceChatScheduled(authorName, timeString)
|
||||
attributedString = addAttributesToStringWithRanges(titleString, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||
}
|
||||
} else if let duration = duration {
|
||||
let titleString = strings.Notification_VoiceChatEnded(callDurationString(strings: strings, value: duration)).0
|
||||
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user