mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Reaction improvements
This commit is contained in:
parent
ccffdb6bac
commit
af01ec906f
@ -7195,3 +7195,6 @@ Sorry for the inconvenience.";
|
|||||||
"Localization.InterfaceLanguage" = "Interface Language";
|
"Localization.InterfaceLanguage" = "Interface Language";
|
||||||
|
|
||||||
"DoNotTranslate.Title" = "Do Not Translate";
|
"DoNotTranslate.Title" = "Do Not Translate";
|
||||||
|
|
||||||
|
"Channel.AdminLog.AllowedReactionsUpdated" = "%1$@ updated the list of allowed reactions to: %2$@";
|
||||||
|
"Channel.AdminLog.ReactionsDisabled" = "%1$@ disabled reactions";
|
||||||
|
@ -532,13 +532,28 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
public var updateDistractionFreeMode: ((Bool) -> Void)?
|
public var updateDistractionFreeMode: ((Bool) -> Void)?
|
||||||
public var requestDismiss: (() -> Void)*/
|
public var requestDismiss: (() -> Void)*/
|
||||||
case let .animateOut(result, completion):
|
case let .animateOut(result, completion):
|
||||||
let duration: Double = self.reactionContextNodeIsAnimatingOut ? 0.25 : 0.2
|
let duration: Double
|
||||||
|
let timingFunction: String
|
||||||
|
switch result {
|
||||||
|
case .default, .dismissWithoutContent:
|
||||||
|
duration = self.reactionContextNodeIsAnimatingOut ? 0.25 : 0.2
|
||||||
|
timingFunction = CAMediaTimingFunctionName.easeInEaseOut.rawValue
|
||||||
|
case let .custom(customTransition):
|
||||||
|
switch customTransition {
|
||||||
|
case let .animated(customDuration, curve):
|
||||||
|
duration = customDuration
|
||||||
|
timingFunction = curve.timingFunction
|
||||||
|
case .immediate:
|
||||||
|
duration = self.reactionContextNodeIsAnimatingOut ? 0.25 : 0.2
|
||||||
|
timingFunction = CAMediaTimingFunctionName.easeInEaseOut.rawValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let putBackInfo = self.source.putBack()
|
let putBackInfo = self.source.putBack()
|
||||||
|
|
||||||
if let putBackInfo = putBackInfo {
|
if let putBackInfo = putBackInfo {
|
||||||
self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(), size: layout.size), to: CGRect(origin: CGPoint(x: 0.0, y: putBackInfo.contentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: putBackInfo.contentAreaInScreenSpace.height)), duration: duration, removeOnCompletion: false)
|
self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(), size: layout.size), to: CGRect(origin: CGPoint(x: 0.0, y: putBackInfo.contentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: putBackInfo.contentAreaInScreenSpace.height)), duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
|
||||||
self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: putBackInfo.contentAreaInScreenSpace.minY, duration: duration, removeOnCompletion: false)
|
self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: putBackInfo.contentAreaInScreenSpace.minY, duration: duration, timingFunction: timingFunction, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentContentScreenFrame = convertFrame(contentNode.containingNode.contentRect, from: contentNode.containingNode.view, to: self.view)
|
let currentContentScreenFrame = convertFrame(contentNode.containingNode.contentRect, from: contentNode.containingNode.view, to: self.view)
|
||||||
@ -574,7 +589,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
from: animationInContentDistance as NSNumber,
|
from: animationInContentDistance as NSNumber,
|
||||||
to: 0.0 as NSNumber,
|
to: 0.0 as NSNumber,
|
||||||
keyPath: "position.y",
|
keyPath: "position.y",
|
||||||
timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue,
|
timingFunction: timingFunction,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
delay: 0.0,
|
delay: 0.0,
|
||||||
additive: true,
|
additive: true,
|
||||||
@ -597,7 +612,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
from: 1.0 as NSNumber,
|
from: 1.0 as NSNumber,
|
||||||
to: 0.01 as NSNumber,
|
to: 0.01 as NSNumber,
|
||||||
keyPath: "transform.scale",
|
keyPath: "transform.scale",
|
||||||
timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue,
|
timingFunction: timingFunction,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
delay: 0.0,
|
delay: 0.0,
|
||||||
removeOnCompletion: false
|
removeOnCompletion: false
|
||||||
@ -611,7 +626,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
from: NSValue(cgPoint: CGPoint()),
|
from: NSValue(cgPoint: CGPoint()),
|
||||||
to: NSValue(cgPoint: CGPoint(x: actionsPositionDeltaXDistance, y: actionsPositionDeltaYDistance)),
|
to: NSValue(cgPoint: CGPoint(x: actionsPositionDeltaXDistance, y: actionsPositionDeltaYDistance)),
|
||||||
keyPath: "position",
|
keyPath: "position",
|
||||||
timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue,
|
timingFunction: timingFunction,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
delay: 0.0,
|
delay: 0.0,
|
||||||
removeOnCompletion: false,
|
removeOnCompletion: false,
|
||||||
|
@ -162,6 +162,9 @@ private func peerAllowedReactionListControllerEntries(
|
|||||||
entries.append(.itemsHeader("AVAILABLE REACTIONS"))
|
entries.append(.itemsHeader("AVAILABLE REACTIONS"))
|
||||||
var index = 0
|
var index = 0
|
||||||
for availableReaction in availableReactions.reactions {
|
for availableReaction in availableReactions.reactions {
|
||||||
|
if !availableReaction.isEnabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
entries.append(.item(index: index, value: availableReaction.value, file: availableReaction.staticIcon, text: availableReaction.title, isEnabled: allowedReactions.contains(availableReaction.value)))
|
entries.append(.item(index: index, value: availableReaction.value, file: availableReaction.staticIcon, text: availableReaction.title, isEnabled: allowedReactions.contains(availableReaction.value)))
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
@ -217,6 +220,9 @@ public func peerAllowedReactionListController(
|
|||||||
if var updatedAllowedReactions = state.updatedAllowedReactions {
|
if var updatedAllowedReactions = state.updatedAllowedReactions {
|
||||||
if updatedAllowedReactions.isEmpty {
|
if updatedAllowedReactions.isEmpty {
|
||||||
for availableReaction in availableReactions.reactions {
|
for availableReaction in availableReactions.reactions {
|
||||||
|
if !availableReaction.isEnabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
updatedAllowedReactions.insert(availableReaction.value)
|
updatedAllowedReactions.insert(availableReaction.value)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -194,13 +194,17 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
let itemOffsetY: CGFloat = -1.0
|
let itemOffsetY: CGFloat = -1.0
|
||||||
|
|
||||||
let itemFrame = CGRect(origin: CGPoint(x: sideInset + column * (itemSize + itemSpacing), y: verticalInset + floor((rowHeight - itemSize) / 2.0) + itemOffsetY), size: CGSize(width: itemSize, height: itemSize))
|
let baseItemFrame = CGRect(origin: CGPoint(x: sideInset + column * (itemSize + itemSpacing), y: verticalInset + floor((rowHeight - itemSize) / 2.0) + itemOffsetY), size: CGSize(width: itemSize, height: itemSize))
|
||||||
/*if self.highlightedReaction == self.items[i].reaction {
|
if visibleBounds.intersects(baseItemFrame) {
|
||||||
itemFrame = itemFrame.insetBy(dx: -6.0, dy: -6.0)
|
|
||||||
}*/
|
|
||||||
if visibleBounds.intersects(itemFrame) {
|
|
||||||
validIndices.insert(i)
|
validIndices.insert(i)
|
||||||
|
|
||||||
|
var itemFrame = baseItemFrame
|
||||||
|
var isPreviewing = false
|
||||||
|
if self.highlightedReaction == self.items[i].reaction {
|
||||||
|
itemFrame = itemFrame.insetBy(dx: -6.0, dy: -6.0)
|
||||||
|
isPreviewing = true
|
||||||
|
}
|
||||||
|
|
||||||
var animateIn = false
|
var animateIn = false
|
||||||
|
|
||||||
let itemNode: ReactionNode
|
let itemNode: ReactionNode
|
||||||
@ -216,7 +220,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
if !itemNode.isExtracted {
|
if !itemNode.isExtracted {
|
||||||
transition.updateFrame(node: itemNode, frame: itemFrame, beginWithCurrentState: true)
|
transition.updateFrame(node: itemNode, frame: itemFrame, beginWithCurrentState: true)
|
||||||
itemNode.updateLayout(size: itemFrame.size, isExpanded: false, transition: transition)
|
itemNode.updateLayout(size: itemFrame.size, isExpanded: false, isPreviewing: isPreviewing, transition: transition)
|
||||||
|
|
||||||
if animateIn {
|
if animateIn {
|
||||||
itemNode.animateIn()
|
itemNode.animateIn()
|
||||||
@ -433,7 +437,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
//itemNode.position = selfSourceRect.center
|
//itemNode.position = selfSourceRect.center
|
||||||
itemNode.position = expandedFrame.center
|
itemNode.position = expandedFrame.center
|
||||||
transition.updateBounds(node: itemNode, bounds: CGRect(origin: CGPoint(), size: expandedFrame.size))
|
transition.updateBounds(node: itemNode, bounds: CGRect(origin: CGPoint(), size: expandedFrame.size))
|
||||||
itemNode.updateLayout(size: expandedFrame.size, isExpanded: true, transition: transition)
|
itemNode.updateLayout(size: expandedFrame.size, isExpanded: true, isPreviewing: false, transition: transition)
|
||||||
|
|
||||||
transition.animatePositionWithKeyframes(node: itemNode, keyframes: generateParabollicMotionKeyframes(from: selfSourceRect.center, to: expandedFrame.center, elevation: 30.0))
|
transition.animatePositionWithKeyframes(node: itemNode, keyframes: generateParabollicMotionKeyframes(from: selfSourceRect.center, to: expandedFrame.center, elevation: 30.0))
|
||||||
|
|
||||||
@ -632,7 +636,7 @@ public final class StandaloneReactionAnimation: ASDisplayNode {
|
|||||||
|
|
||||||
self.addSubnode(itemNode)
|
self.addSubnode(itemNode)
|
||||||
itemNode.frame = expandedFrame
|
itemNode.frame = expandedFrame
|
||||||
itemNode.updateLayout(size: expandedFrame.size, isExpanded: true, transition: .immediate)
|
itemNode.updateLayout(size: expandedFrame.size, isExpanded: true, isPreviewing: false, transition: .immediate)
|
||||||
|
|
||||||
itemNode.layer.animateSpring(from: (selfTargetRect.width / expandedFrame.width) as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
|
itemNode.layer.animateSpring(from: (selfTargetRect.width / expandedFrame.width) as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
|
||||||
itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.04)
|
itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.04)
|
||||||
|
@ -61,7 +61,6 @@ final class ReactionNode: ASDisplayNode {
|
|||||||
self.staticAnimationNode.isHidden = true
|
self.staticAnimationNode.isHidden = true
|
||||||
|
|
||||||
self.animateInAnimationNode = AnimatedStickerNode()
|
self.animateInAnimationNode = AnimatedStickerNode()
|
||||||
self.stillAnimationNode = AnimatedStickerNode()
|
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -105,7 +104,7 @@ final class ReactionNode: ASDisplayNode {
|
|||||||
self.animateInAnimationNode?.visibility = true
|
self.animateInAnimationNode?.visibility = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(size: CGSize, isExpanded: Bool, transition: ContainedViewLayoutTransition) {
|
func updateLayout(size: CGSize, isExpanded: Bool, isPreviewing: Bool, transition: ContainedViewLayoutTransition) {
|
||||||
let intrinsicSize = size
|
let intrinsicSize = size
|
||||||
|
|
||||||
let animationSize = self.item.stillAnimation.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
|
let animationSize = self.item.stillAnimation.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
|
||||||
@ -186,27 +185,50 @@ final class ReactionNode: ASDisplayNode {
|
|||||||
self.validSize = size
|
self.validSize = size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*if isPreviewing {
|
||||||
|
if self.stillAnimationNode == nil {
|
||||||
|
let stillAnimationNode = AnimatedStickerNode()
|
||||||
|
self.stillAnimationNode = stillAnimationNode
|
||||||
|
self.addSubnode(stillAnimationNode)
|
||||||
|
|
||||||
|
stillAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id)))
|
||||||
|
stillAnimationNode.position = animationFrame.center
|
||||||
|
stillAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size)
|
||||||
|
stillAnimationNode.updateLayout(size: animationFrame.size)
|
||||||
|
stillAnimationNode.started = { [weak self] in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = strongSelf
|
||||||
|
}
|
||||||
|
stillAnimationNode.visibility = true
|
||||||
|
} else {
|
||||||
|
if let stillAnimationNode = self.stillAnimationNode {
|
||||||
|
transition.updatePosition(node: stillAnimationNode, position: animationFrame.center, beginWithCurrentState: true)
|
||||||
|
transition.updateTransformScale(node: stillAnimationNode, scale: animationFrame.size.width / stillAnimationNode.bounds.width, beginWithCurrentState: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let stillAnimationNode = self.stillAnimationNode {
|
||||||
|
self.stillAnimationNode = nil
|
||||||
|
stillAnimationNode.removeFromSupernode()
|
||||||
|
}*/
|
||||||
|
|
||||||
if !self.didSetupStillAnimation {
|
if !self.didSetupStillAnimation {
|
||||||
if self.animationNode == nil {
|
if self.animationNode == nil {
|
||||||
self.didSetupStillAnimation = true
|
self.didSetupStillAnimation = true
|
||||||
|
|
||||||
self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id)))
|
self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id)))
|
||||||
self.staticAnimationNode.position = animationFrame.center
|
self.staticAnimationNode.position = animationFrame.center
|
||||||
self.staticAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size)
|
self.staticAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size)
|
||||||
self.staticAnimationNode.updateLayout(size: animationFrame.size)
|
self.staticAnimationNode.updateLayout(size: animationFrame.size)
|
||||||
self.staticAnimationNode.visibility = true
|
self.staticAnimationNode.visibility = true
|
||||||
|
|
||||||
if let animateInAnimationNode = self.animateInAnimationNode {
|
if let animateInAnimationNode = self.animateInAnimationNode {
|
||||||
animateInAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.appearAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.appearAnimation.resource.id)))
|
animateInAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.appearAnimation.resource), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.appearAnimation.resource.id)))
|
||||||
animateInAnimationNode.position = animationFrame.center
|
animateInAnimationNode.position = animationFrame.center
|
||||||
animateInAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size)
|
animateInAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size)
|
||||||
animateInAnimationNode.updateLayout(size: animationFrame.size)
|
animateInAnimationNode.updateLayout(size: animationFrame.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*self.stillAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id)))
|
|
||||||
self.stillAnimationNode.position = animationFrame.center
|
|
||||||
self.stillAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size)
|
|
||||||
self.stillAnimationNode.updateLayout(size: animationFrame.size)*/
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
transition.updatePosition(node: self.staticAnimationNode, position: animationFrame.center, beginWithCurrentState: true)
|
transition.updatePosition(node: self.staticAnimationNode, position: animationFrame.center, beginWithCurrentState: true)
|
||||||
@ -216,11 +238,6 @@ final class ReactionNode: ASDisplayNode {
|
|||||||
transition.updatePosition(node: animateInAnimationNode, position: animationFrame.center, beginWithCurrentState: true)
|
transition.updatePosition(node: animateInAnimationNode, position: animationFrame.center, beginWithCurrentState: true)
|
||||||
transition.updateTransformScale(node: animateInAnimationNode, scale: animationFrame.size.width / animateInAnimationNode.bounds.width, beginWithCurrentState: true)
|
transition.updateTransformScale(node: animateInAnimationNode, scale: animationFrame.size.width / animateInAnimationNode.bounds.width, beginWithCurrentState: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let stillAnimationNode = self.stillAnimationNode {
|
|
||||||
transition.updatePosition(node: stillAnimationNode, position: animationFrame.center, beginWithCurrentState: true)
|
|
||||||
transition.updateTransformScale(node: stillAnimationNode, scale: animationFrame.size.width / stillAnimationNode.bounds.width, beginWithCurrentState: true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,10 @@ private func quickReactionSetupControllerEntries(
|
|||||||
entries.append(.itemsHeader("QUICK REACTION"))
|
entries.append(.itemsHeader("QUICK REACTION"))
|
||||||
var index = 0
|
var index = 0
|
||||||
for availableReaction in availableReactions.reactions {
|
for availableReaction in availableReactions.reactions {
|
||||||
|
if !availableReaction.isEnabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
entries.append(.item(
|
entries.append(.item(
|
||||||
index: index,
|
index: index,
|
||||||
value: availableReaction.value,
|
value: availableReaction.value,
|
||||||
@ -227,11 +231,7 @@ public func quickReactionSetupController(
|
|||||||
let arguments = QuickReactionSetupControllerArguments(
|
let arguments = QuickReactionSetupControllerArguments(
|
||||||
context: context,
|
context: context,
|
||||||
selectItem: { reaction in
|
selectItem: { reaction in
|
||||||
let _ = updateReactionSettingsInteractively(postbox: context.account.postbox, { settings in
|
let _ = context.engine.stickers.updateQuickReaction(reaction: reaction).start()
|
||||||
var settings = settings
|
|
||||||
settings.quickReaction = reaction
|
|
||||||
return settings
|
|
||||||
}).start()
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -252,6 +252,10 @@ public func quickReactionSetupController(
|
|||||||
|
|
||||||
if let availableReactions = availableReactions {
|
if let availableReactions = availableReactions {
|
||||||
for availableReaction in availableReactions.reactions {
|
for availableReaction in availableReactions.reactions {
|
||||||
|
if !availableReaction.isEnabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
let signal: Signal<(String, UIImage?), NoError> = context.account.postbox.mediaBox.resourceData(availableReaction.staticIcon.resource)
|
let signal: Signal<(String, UIImage?), NoError> = context.account.postbox.mediaBox.resourceData(availableReaction.staticIcon.resource)
|
||||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||||
return lhs.complete == rhs.complete
|
return lhs.complete == rhs.complete
|
||||||
|
@ -480,6 +480,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1347021750] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantJoinByRequest($0) }
|
dict[-1347021750] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantJoinByRequest($0) }
|
||||||
dict[-886388890] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleNoForwards($0) }
|
dict[-886388890] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionToggleNoForwards($0) }
|
||||||
dict[663693416] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionSendMessage($0) }
|
dict[663693416] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionSendMessage($0) }
|
||||||
|
dict[-1661470870] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeAvailableReactions($0) }
|
||||||
dict[-1271602504] = { return Api.auth.ExportedAuthorization.parse_exportedAuthorization($0) }
|
dict[-1271602504] = { return Api.auth.ExportedAuthorization.parse_exportedAuthorization($0) }
|
||||||
dict[2103482845] = { return Api.SecurePlainData.parse_securePlainPhone($0) }
|
dict[2103482845] = { return Api.SecurePlainData.parse_securePlainPhone($0) }
|
||||||
dict[569137759] = { return Api.SecurePlainData.parse_securePlainEmail($0) }
|
dict[569137759] = { return Api.SecurePlainData.parse_securePlainEmail($0) }
|
||||||
@ -791,7 +792,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[594408994] = { return Api.EmojiKeyword.parse_emojiKeywordDeleted($0) }
|
dict[594408994] = { return Api.EmojiKeyword.parse_emojiKeywordDeleted($0) }
|
||||||
dict[-290921362] = { return Api.upload.CdnFile.parse_cdnFileReuploadNeeded($0) }
|
dict[-290921362] = { return Api.upload.CdnFile.parse_cdnFileReuploadNeeded($0) }
|
||||||
dict[-1449145777] = { return Api.upload.CdnFile.parse_cdnFile($0) }
|
dict[-1449145777] = { return Api.upload.CdnFile.parse_cdnFile($0) }
|
||||||
dict[1424116867] = { return Api.AvailableReaction.parse_availableReaction($0) }
|
dict[35486795] = { return Api.AvailableReaction.parse_availableReaction($0) }
|
||||||
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
||||||
dict[-1826077446] = { return Api.MessageUserReaction.parse_messageUserReaction($0) }
|
dict[-1826077446] = { return Api.MessageUserReaction.parse_messageUserReaction($0) }
|
||||||
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
||||||
|
@ -11695,6 +11695,7 @@ public extension Api {
|
|||||||
case channelAdminLogEventActionParticipantJoinByRequest(invite: Api.ExportedChatInvite, approvedBy: Int64)
|
case channelAdminLogEventActionParticipantJoinByRequest(invite: Api.ExportedChatInvite, approvedBy: Int64)
|
||||||
case channelAdminLogEventActionToggleNoForwards(newValue: Api.Bool)
|
case channelAdminLogEventActionToggleNoForwards(newValue: Api.Bool)
|
||||||
case channelAdminLogEventActionSendMessage(message: Api.Message)
|
case channelAdminLogEventActionSendMessage(message: Api.Message)
|
||||||
|
case channelAdminLogEventActionChangeAvailableReactions(prevValue: [String], newValue: [String])
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -11923,6 +11924,21 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
message.serialize(buffer, true)
|
message.serialize(buffer, true)
|
||||||
break
|
break
|
||||||
|
case .channelAdminLogEventActionChangeAvailableReactions(let prevValue, let newValue):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1661470870)
|
||||||
|
}
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(prevValue.count))
|
||||||
|
for item in prevValue {
|
||||||
|
serializeString(item, buffer: buffer, boxed: false)
|
||||||
|
}
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(newValue.count))
|
||||||
|
for item in newValue {
|
||||||
|
serializeString(item, buffer: buffer, boxed: false)
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11998,6 +12014,8 @@ public extension Api {
|
|||||||
return ("channelAdminLogEventActionToggleNoForwards", [("newValue", newValue)])
|
return ("channelAdminLogEventActionToggleNoForwards", [("newValue", newValue)])
|
||||||
case .channelAdminLogEventActionSendMessage(let message):
|
case .channelAdminLogEventActionSendMessage(let message):
|
||||||
return ("channelAdminLogEventActionSendMessage", [("message", message)])
|
return ("channelAdminLogEventActionSendMessage", [("message", message)])
|
||||||
|
case .channelAdminLogEventActionChangeAvailableReactions(let prevValue, let newValue):
|
||||||
|
return ("channelAdminLogEventActionChangeAvailableReactions", [("prevValue", prevValue), ("newValue", newValue)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12485,6 +12503,24 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_channelAdminLogEventActionChangeAvailableReactions(_ reader: BufferReader) -> ChannelAdminLogEventAction? {
|
||||||
|
var _1: [String]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_1 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
|
||||||
|
}
|
||||||
|
var _2: [String]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
if _c1 && _c2 {
|
||||||
|
return Api.ChannelAdminLogEventAction.channelAdminLogEventActionChangeAvailableReactions(prevValue: _1!, newValue: _2!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum SecurePlainData: TypeConstructorDescription {
|
public enum SecurePlainData: TypeConstructorDescription {
|
||||||
@ -20200,14 +20236,15 @@ public extension Api {
|
|||||||
|
|
||||||
}
|
}
|
||||||
public enum AvailableReaction: TypeConstructorDescription {
|
public enum AvailableReaction: TypeConstructorDescription {
|
||||||
case availableReaction(reaction: String, title: String, staticIcon: Api.Document, appearAnimation: Api.Document, selectAnimation: Api.Document, activateAnimation: Api.Document, effectAnimation: Api.Document)
|
case availableReaction(flags: Int32, reaction: String, title: String, staticIcon: Api.Document, appearAnimation: Api.Document, selectAnimation: Api.Document, activateAnimation: Api.Document, effectAnimation: Api.Document)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .availableReaction(let reaction, let title, let staticIcon, let appearAnimation, let selectAnimation, let activateAnimation, let effectAnimation):
|
case .availableReaction(let flags, let reaction, let title, let staticIcon, let appearAnimation, let selectAnimation, let activateAnimation, let effectAnimation):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1424116867)
|
buffer.appendInt32(35486795)
|
||||||
}
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeString(reaction, buffer: buffer, boxed: false)
|
serializeString(reaction, buffer: buffer, boxed: false)
|
||||||
serializeString(title, buffer: buffer, boxed: false)
|
serializeString(title, buffer: buffer, boxed: false)
|
||||||
staticIcon.serialize(buffer, true)
|
staticIcon.serialize(buffer, true)
|
||||||
@ -20221,20 +20258,18 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .availableReaction(let reaction, let title, let staticIcon, let appearAnimation, let selectAnimation, let activateAnimation, let effectAnimation):
|
case .availableReaction(let flags, let reaction, let title, let staticIcon, let appearAnimation, let selectAnimation, let activateAnimation, let effectAnimation):
|
||||||
return ("availableReaction", [("reaction", reaction), ("title", title), ("staticIcon", staticIcon), ("appearAnimation", appearAnimation), ("selectAnimation", selectAnimation), ("activateAnimation", activateAnimation), ("effectAnimation", effectAnimation)])
|
return ("availableReaction", [("flags", flags), ("reaction", reaction), ("title", title), ("staticIcon", staticIcon), ("appearAnimation", appearAnimation), ("selectAnimation", selectAnimation), ("activateAnimation", activateAnimation), ("effectAnimation", effectAnimation)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func parse_availableReaction(_ reader: BufferReader) -> AvailableReaction? {
|
public static func parse_availableReaction(_ reader: BufferReader) -> AvailableReaction? {
|
||||||
var _1: String?
|
var _1: Int32?
|
||||||
_1 = parseString(reader)
|
_1 = reader.readInt32()
|
||||||
var _2: String?
|
var _2: String?
|
||||||
_2 = parseString(reader)
|
_2 = parseString(reader)
|
||||||
var _3: Api.Document?
|
var _3: String?
|
||||||
if let signature = reader.readInt32() {
|
_3 = parseString(reader)
|
||||||
_3 = Api.parse(reader, signature: signature) as? Api.Document
|
|
||||||
}
|
|
||||||
var _4: Api.Document?
|
var _4: Api.Document?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
_4 = Api.parse(reader, signature: signature) as? Api.Document
|
_4 = Api.parse(reader, signature: signature) as? Api.Document
|
||||||
@ -20251,6 +20286,10 @@ public extension Api {
|
|||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
_7 = Api.parse(reader, signature: signature) as? Api.Document
|
_7 = Api.parse(reader, signature: signature) as? Api.Document
|
||||||
}
|
}
|
||||||
|
var _8: Api.Document?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_8 = Api.parse(reader, signature: signature) as? Api.Document
|
||||||
|
}
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
@ -20258,8 +20297,9 @@ public extension Api {
|
|||||||
let _c5 = _5 != nil
|
let _c5 = _5 != nil
|
||||||
let _c6 = _6 != nil
|
let _c6 = _6 != nil
|
||||||
let _c7 = _7 != nil
|
let _c7 = _7 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
let _c8 = _8 != nil
|
||||||
return Api.AvailableReaction.availableReaction(reaction: _1!, title: _2!, staticIcon: _3!, appearAnimation: _4!, selectAnimation: _5!, activateAnimation: _6!, effectAnimation: _7!)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
|
||||||
|
return Api.AvailableReaction.availableReaction(flags: _1!, reaction: _2!, title: _3!, staticIcon: _4!, appearAnimation: _5!, selectAnimation: _6!, activateAnimation: _7!, effectAnimation: _8!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -11,13 +11,17 @@ public struct ReactionSettings: Equatable, Codable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateReactionSettings(transaction: Transaction, _ f: (ReactionSettings) -> ReactionSettings) {
|
||||||
|
transaction.updatePreferencesEntry(key: PreferencesKeys.reactionSettings, { current in
|
||||||
|
let previous = current?.get(ReactionSettings.self) ?? ReactionSettings.default
|
||||||
|
let updated = f(previous)
|
||||||
|
return PreferencesEntry(updated)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
public func updateReactionSettingsInteractively(postbox: Postbox, _ f: @escaping (ReactionSettings) -> ReactionSettings) -> Signal<Never, NoError> {
|
public func updateReactionSettingsInteractively(postbox: Postbox, _ f: @escaping (ReactionSettings) -> ReactionSettings) -> Signal<Never, NoError> {
|
||||||
return postbox.transaction { transaction -> Void in
|
return postbox.transaction { transaction -> Void in
|
||||||
transaction.updatePreferencesEntry(key: PreferencesKeys.reactionSettings, { current in
|
updateReactionSettings(transaction: transaction, f)
|
||||||
let previous = current?.get(ReactionSettings.self) ?? ReactionSettings.default
|
|
||||||
let updated = f(previous)
|
|
||||||
return PreferencesEntry(updated)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import SwiftSignalKit
|
|||||||
public final class AvailableReactions: Equatable, Codable {
|
public final class AvailableReactions: Equatable, Codable {
|
||||||
public final class Reaction: Equatable, Codable {
|
public final class Reaction: Equatable, Codable {
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
|
case isEnabled
|
||||||
case value
|
case value
|
||||||
case title
|
case title
|
||||||
case staticIcon
|
case staticIcon
|
||||||
@ -15,6 +16,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
case effectAnimation
|
case effectAnimation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public let isEnabled: Bool
|
||||||
public let value: String
|
public let value: String
|
||||||
public let title: String
|
public let title: String
|
||||||
public let staticIcon: TelegramMediaFile
|
public let staticIcon: TelegramMediaFile
|
||||||
@ -24,6 +26,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
public let effectAnimation: TelegramMediaFile
|
public let effectAnimation: TelegramMediaFile
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
isEnabled: Bool,
|
||||||
value: String,
|
value: String,
|
||||||
title: String,
|
title: String,
|
||||||
staticIcon: TelegramMediaFile,
|
staticIcon: TelegramMediaFile,
|
||||||
@ -32,6 +35,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
activateAnimation: TelegramMediaFile,
|
activateAnimation: TelegramMediaFile,
|
||||||
effectAnimation: TelegramMediaFile
|
effectAnimation: TelegramMediaFile
|
||||||
) {
|
) {
|
||||||
|
self.isEnabled = isEnabled
|
||||||
self.value = value
|
self.value = value
|
||||||
self.title = title
|
self.title = title
|
||||||
self.staticIcon = staticIcon
|
self.staticIcon = staticIcon
|
||||||
@ -42,6 +46,9 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Reaction, rhs: Reaction) -> Bool {
|
public static func ==(lhs: Reaction, rhs: Reaction) -> Bool {
|
||||||
|
if lhs.isEnabled != rhs.isEnabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.value != rhs.value {
|
if lhs.value != rhs.value {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -69,6 +76,8 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.isEnabled = try container.decode(Bool.self, forKey: .isEnabled)
|
||||||
|
|
||||||
self.value = try container.decode(String.self, forKey: .value)
|
self.value = try container.decode(String.self, forKey: .value)
|
||||||
self.title = try container.decode(String.self, forKey: .title)
|
self.title = try container.decode(String.self, forKey: .title)
|
||||||
|
|
||||||
@ -91,6 +100,8 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.isEnabled, forKey: .isEnabled)
|
||||||
|
|
||||||
try container.encode(self.value, forKey: .value)
|
try container.encode(self.value, forKey: .value)
|
||||||
try container.encode(self.title, forKey: .title)
|
try container.encode(self.title, forKey: .title)
|
||||||
|
|
||||||
@ -146,7 +157,7 @@ public final class AvailableReactions: Equatable, Codable {
|
|||||||
private extension AvailableReactions.Reaction {
|
private extension AvailableReactions.Reaction {
|
||||||
convenience init?(apiReaction: Api.AvailableReaction) {
|
convenience init?(apiReaction: Api.AvailableReaction) {
|
||||||
switch apiReaction {
|
switch apiReaction {
|
||||||
case let .availableReaction(reaction, title, staticIcon, appearAnimation, selectAnimation, activateAnimation, effectAnimation):
|
case let .availableReaction(flags, reaction, title, staticIcon, appearAnimation, selectAnimation, activateAnimation, effectAnimation):
|
||||||
guard let staticIconFile = telegramMediaFileFromApiDocument(staticIcon) else {
|
guard let staticIconFile = telegramMediaFileFromApiDocument(staticIcon) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -162,7 +173,9 @@ private extension AvailableReactions.Reaction {
|
|||||||
guard let effectAnimationFile = telegramMediaFileFromApiDocument(effectAnimation) else {
|
guard let effectAnimationFile = telegramMediaFileFromApiDocument(effectAnimation) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
let isEnabled = (flags & (1 << 0)) == 0
|
||||||
self.init(
|
self.init(
|
||||||
|
isEnabled: isEnabled,
|
||||||
value: reaction,
|
value: reaction,
|
||||||
title: title,
|
title: title,
|
||||||
staticIcon: staticIconFile,
|
staticIcon: staticIconFile,
|
||||||
|
@ -17,6 +17,14 @@ func updateAppConfigurationOnce(postbox: Postbox, network: Network) -> Signal<Vo
|
|||||||
}
|
}
|
||||||
return postbox.transaction { transaction -> Void in
|
return postbox.transaction { transaction -> Void in
|
||||||
if let data = JSON(apiJson: result) {
|
if let data = JSON(apiJson: result) {
|
||||||
|
if let value = data["reactions_default"] as? String {
|
||||||
|
updateReactionSettings(transaction: transaction, { settings in
|
||||||
|
var settings = settings
|
||||||
|
settings.quickReaction = value
|
||||||
|
return settings
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
updateAppConfiguration(transaction: transaction, { configuration -> AppConfiguration in
|
updateAppConfiguration(transaction: transaction, { configuration -> AppConfiguration in
|
||||||
var configuration = configuration
|
var configuration = configuration
|
||||||
configuration.data = data
|
configuration.data = data
|
||||||
|
@ -499,3 +499,11 @@ func _internal_updatePeerAllowedReactions(account: Account, peerId: PeerId, allo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_updateDefaultReaction(account: Account, reaction: String) -> Signal<Never, NoError> {
|
||||||
|
return account.network.request(Api.functions.messages.setDefaultReaction(emoji: reaction))
|
||||||
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
|
return .single(.boolFalse)
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
@ -67,6 +67,7 @@ public enum AdminLogEventAction {
|
|||||||
case participantJoinByRequest(invitation: ExportedInvitation, approvedBy: PeerId)
|
case participantJoinByRequest(invitation: ExportedInvitation, approvedBy: PeerId)
|
||||||
case toggleCopyProtection(Bool)
|
case toggleCopyProtection(Bool)
|
||||||
case sendMessage(Message)
|
case sendMessage(Message)
|
||||||
|
case changeAvailableReactions(previousValue: [String], updatedValue: [String])
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ChannelAdminLogEventError {
|
public enum ChannelAdminLogEventError {
|
||||||
@ -262,6 +263,8 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m
|
|||||||
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||||
action = .sendMessage(rendered)
|
action = .sendMessage(rendered)
|
||||||
}
|
}
|
||||||
|
case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue):
|
||||||
|
action = .changeAvailableReactions(previousValue: prevValue, updatedValue: newValue)
|
||||||
}
|
}
|
||||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
|
||||||
if let action = action {
|
if let action = action {
|
||||||
|
@ -99,5 +99,14 @@ public extension TelegramEngine {
|
|||||||
public func availableReactions() -> Signal<AvailableReactions?, NoError> {
|
public func availableReactions() -> Signal<AvailableReactions?, NoError> {
|
||||||
return _internal_cachedAvailableReactions(postbox: self.account.postbox)
|
return _internal_cachedAvailableReactions(postbox: self.account.postbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func updateQuickReaction(reaction: String) -> Signal<Never, NoError> {
|
||||||
|
let _ = updateReactionSettingsInteractively(postbox: self.account.postbox, { settings in
|
||||||
|
var settings = settings
|
||||||
|
settings.quickReaction = reaction
|
||||||
|
return settings
|
||||||
|
}).start()
|
||||||
|
return _internal_updateDefaultReaction(account: self.account, reaction: reaction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1005,6 +1005,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
if canAddMessageReactions(message: topMessage), let availableReactions = availableReactions, let allowedReactions = allowedReactions {
|
if canAddMessageReactions(message: topMessage), let availableReactions = availableReactions, let allowedReactions = allowedReactions {
|
||||||
filterReactions: for reaction in availableReactions.reactions {
|
filterReactions: for reaction in availableReactions.reactions {
|
||||||
|
if !reaction.isEnabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
switch allowedReactions {
|
switch allowedReactions {
|
||||||
case let .set(set):
|
case let .set(set):
|
||||||
if !set.contains(reaction.value) {
|
if !set.contains(reaction.value) {
|
||||||
|
@ -1397,6 +1397,38 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
|
|
||||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||||
|
|
||||||
|
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||||
|
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||||
|
case let .changeAvailableReactions(_, updatedValue):
|
||||||
|
var peers = SimpleDictionary<PeerId, Peer>()
|
||||||
|
var author: Peer?
|
||||||
|
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||||
|
author = peer
|
||||||
|
peers[peer.id] = peer
|
||||||
|
}
|
||||||
|
|
||||||
|
var text: String = ""
|
||||||
|
var entities: [MessageTextEntity] = []
|
||||||
|
|
||||||
|
let rawText: PresentationStrings.FormattedString
|
||||||
|
if !updatedValue.isEmpty {
|
||||||
|
let emojiString = updatedValue.joined(separator: ", ")
|
||||||
|
rawText = self.presentationData.strings.Channel_AdminLog_AllowedReactionsUpdated(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", emojiString)
|
||||||
|
} else {
|
||||||
|
rawText = self.presentationData.strings.Channel_AdminLog_ReactionsDisabled(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
|
appendAttributedText(text: rawText, generateEntities: { index in
|
||||||
|
if index == 0, let author = author {
|
||||||
|
return [.TextMention(peerId: author.id)]
|
||||||
|
} else if index == 1 {
|
||||||
|
return [.Bold]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}, to: &text, entities: &entities)
|
||||||
|
|
||||||
|
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||||
|
|
||||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [])
|
||||||
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||||
case let .changeTheme(_, updatedValue):
|
case let .changeTheme(_, updatedValue):
|
||||||
|
@ -193,7 +193,11 @@ private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode {
|
|||||||
self.activateArea.accessibilityValue = item.label.text
|
self.activateArea.accessibilityValue = item.label.text
|
||||||
|
|
||||||
transition.updateFrame(node: self.labelBadgeNode, frame: labelBadgeNodeFrame)
|
transition.updateFrame(node: self.labelBadgeNode, frame: labelBadgeNodeFrame)
|
||||||
transition.updateFrame(node: self.labelNode, frame: labelFrame)
|
if self.labelNode.bounds.size != labelFrame.size {
|
||||||
|
self.labelNode.frame = labelFrame
|
||||||
|
} else {
|
||||||
|
transition.updateFrame(node: self.labelNode, frame: labelFrame)
|
||||||
|
}
|
||||||
transition.updateFrame(node: self.textNode, frame: textFrame)
|
transition.updateFrame(node: self.textNode, frame: textFrame)
|
||||||
|
|
||||||
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
|
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user