Reaction improvements

This commit is contained in:
Ali 2021-12-23 15:53:07 +04:00
parent 7c7626f6cc
commit b1a998b6cd
14 changed files with 92 additions and 64 deletions

View File

@ -7201,3 +7201,26 @@ Sorry for the inconvenience.";
"AccessDenied.QrCamera" = "Telegram needs access to your camera to scan QR codes.\n\nPlease go to Settings > Privacy > Camera and set Telegram to ON.";
"Share.ShareToInstagramStories" = "Share to Instagram Stories";
"PeerInfo.AllowedReactions.Title" = "Reactions";
"PeerInfo.AllowedReactions.AllowAllText" = "Allow Reactions";
"PeerInfo.AllowedReactions.AllowAllGroupInfo" = "Allow subscribers to react to group messages.";
"PeerInfo.AllowedReactions.AllowAllChannelInfo" = "Allow subscribers to react to channel posts.";
"PeerInfo.AllowedReactions.ReactionListHeader" = "AVAILABLE REACTIONS";
"PeerInfo.Reactions" = "Reactions";
"PeerInfo.ReactionsDisabled" = "Disabled";
"Settings.QuickReactionSetup.NavigationTitle" = "Quick Reaction";
"Settings.QuickReactionSetup.Title" = "Quick Reaction";
"Settings.QuickReactionSetup.DemoHeader" = "DOUBLE TAP ON MESSAGE TO REACT";
"Settings.QuickReactionSetup.DemoInfo" = "You can double tap on message for a quick reaction.";
"Settings.QuickReactionSetup.ReactionListHeader" = "QUICK REACTION";
"Settings.QuickReactionSetup.DemoMessageAuthor" = "Dino";
"Settings.QuickReactionSetup.DemoMessageText" = "I hope you're enjoying your day as much as I am.";
"Chat.ContextReactionCount_1" = "1 reaction";
"Chat.ContextReactionCount_any" = "%@ reactions";
"Chat.OutgoingContextReactionCount_1" = "1 reacted";
"Chat.OutgoingContextReactionCount_any" = "%@ reacted";
"Chat.OutgoingContextMixedReactionCount" = "%1$@/%2$@ reacted";

View File

@ -150,16 +150,23 @@ private struct PeerAllowedReactionListControllerState: Equatable {
private func peerAllowedReactionListControllerEntries(
presentationData: PresentationData,
availableReactions: AvailableReactions?,
peer: Peer?,
cachedData: CachedPeerData?,
state: PeerAllowedReactionListControllerState
) -> [PeerAllowedReactionListControllerEntry] {
var entries: [PeerAllowedReactionListControllerEntry] = []
if let availableReactions = availableReactions, let allowedReactions = state.updatedAllowedReactions {
entries.append(.allowAll(text: "Allow Reactions", isEnabled: !allowedReactions.isEmpty))
entries.append(.allowAllInfo("Allow subscribers to reacts to channel posts."))
entries.append(.allowAll(text: presentationData.strings.PeerInfo_AllowedReactions_AllowAllText, isEnabled: !allowedReactions.isEmpty))
let allInfoText: String
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
allInfoText = presentationData.strings.PeerInfo_AllowedReactions_AllowAllChannelInfo
} else {
allInfoText = presentationData.strings.PeerInfo_AllowedReactions_AllowAllGroupInfo
}
entries.append(.allowAllInfo(allInfoText))
entries.append(.itemsHeader("AVAILABLE REACTIONS"))
entries.append(.itemsHeader(presentationData.strings.PeerInfo_AllowedReactions_ReactionListHeader))
var index = 0
for availableReaction in availableReactions.reactions {
if !availableReaction.isEnabled {
@ -262,12 +269,12 @@ public func peerAllowedReactionListController(
)
|> deliverOnMainQueue
|> map { presentationData, state, availableReactions, peerView -> (ItemListControllerState, (ItemListNodeState, Any)) in
//TODO:localize
let title: String = "Reactions"
let title: String = presentationData.strings.PeerInfo_AllowedReactions_Title
let entries = peerAllowedReactionListControllerEntries(
presentationData: presentationData,
availableReactions: availableReactions,
peer: peerView.peers[peerId],
cachedData: peerView.cachedData,
state: state
)

View File

@ -177,8 +177,7 @@ private func quickReactionSetupControllerEntries(
var entries: [QuickReactionSetupControllerEntry] = []
if let availableReactions = availableReactions {
//TODO:localize
entries.append(.demoHeader("DOUBLE TAP ON MESSAGE TO REACT"))
entries.append(.demoHeader(presentationData.strings.Settings_QuickReactionSetup_DemoHeader))
entries.append(.demoMessage(
wallpaper: presentationData.chatWallpaper,
fontSize: presentationData.chatFontSize,
@ -188,9 +187,9 @@ private func quickReactionSetupControllerEntries(
availableReactions: availableReactions,
reaction: reactionSettings.quickReaction
))
entries.append(.demoDescription("You can double tap on message for a quick reaction."))
entries.append(.demoDescription(presentationData.strings.Settings_QuickReactionSetup_DemoInfo))
entries.append(.itemsHeader("QUICK REACTION"))
entries.append(.itemsHeader(presentationData.strings.Settings_QuickReactionSetup_ReactionListHeader))
var index = 0
for availableReaction in availableReactions.reactions {
if !availableReaction.isEnabled {
@ -298,8 +297,7 @@ public func quickReactionSetupController(
)
|> deliverOnMainQueue
|> map { presentationData, _, availableReactions, settings, images -> (ItemListControllerState, (ItemListNodeState, Any)) in
//TODO:localize
let title: String = "Quick Reaction"
let title: String = presentationData.strings.Settings_QuickReactionSetup_Title
let entries = quickReactionSetupControllerEntries(
presentationData: presentationData,

View File

@ -197,15 +197,13 @@ class ReactionChatPreviewItemNode: ListViewItemNode {
let messages = SimpleDictionary<MessageId, Message>()
peers[chatPeerId] = TelegramGroup(id: chatPeerId, title: "Chat", photo: [], participantCount: 1, role: .member, membership: .Member, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 1, version: 1)
//TODO:localize
peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: "Dino", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: item.strings.Settings_QuickReactionSetup_DemoMessageAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
//TODO:localize
let messageText = "I hope you're enjoying your day as much as I am."
let messageText = item.strings.Settings_QuickReactionSetup_DemoMessageText
var attributes: [MessageAttribute] = []
if let reaction = item.reaction {
attributes.append(ReactionsMessageAttribute(reactions: [MessageReaction(value: reaction, count: 1, isSelected: true)], recentPeers: []))
attributes.append(ReactionsMessageAttribute(canViewList: false, reactions: [MessageReaction(value: reaction, count: 1, isSelected: true)], recentPeers: []))
}
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions)

View File

@ -543,8 +543,7 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
}
entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title))
//TODO:localize
entries.append(.quickReaction("Quick Reaction", quickReactionImage))
entries.append(.quickReaction(presentationData.strings.Settings_QuickReactionSetup_NavigationTitle, quickReactionImage))
entries.append(.animatedStickers(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickers, stickerSettings.loopAnimatedStickers))
entries.append(.animatedStickersInfo(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickersInfo))

View File

@ -7,6 +7,7 @@ extension ReactionsMessageAttribute {
switch reactions {
case let .messageReactions(flags, results, recentReactions):
let min = (flags & (1 << 0)) != 0
let canViewList = (flags & (1 << 2)) != 0
var reactions = results.map { result -> MessageReaction in
switch result {
case let .reactionCount(flags, reaction, count):
@ -41,7 +42,7 @@ extension ReactionsMessageAttribute {
}
}
}
return ReactionsMessageAttribute(reactions: reactions, recentPeers: parsedRecentReactions)
return ReactionsMessageAttribute(canViewList: canViewList, reactions: reactions, recentPeers: parsedRecentReactions)
}
}
}
@ -116,7 +117,7 @@ public func mergedMessageReactions(attributes: [MessageAttribute]) -> ReactionsM
}
}
if !reactions.isEmpty {
return ReactionsMessageAttribute(reactions: reactions, recentPeers: recentPeers)
return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, reactions: reactions, recentPeers: recentPeers)
} else {
return nil
}
@ -130,7 +131,8 @@ public func mergedMessageReactions(attributes: [MessageAttribute]) -> ReactionsM
extension ReactionsMessageAttribute {
convenience init(apiReactions: Api.MessageReactions) {
switch apiReactions {
case let .messageReactions(_, results, recentReactions):
case let .messageReactions(flags, results, recentReactions):
let canViewList = (flags & (1 << 2)) != 0
let parsedRecentReactions: [ReactionsMessageAttribute.RecentPeer]
if let recentReactions = recentReactions {
parsedRecentReactions = recentReactions.map { recentReaction -> ReactionsMessageAttribute.RecentPeer in
@ -144,6 +146,7 @@ extension ReactionsMessageAttribute {
}
self.init(
canViewList: canViewList,
reactions: results.map { result in
switch result {
case let .reactionCount(flags, reaction, count):

View File

@ -51,6 +51,7 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
}
}
public let canViewList: Bool
public let reactions: [MessageReaction]
public let recentPeers: [RecentPeer]
@ -58,22 +59,28 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
return self.recentPeers.map(\.peerId)
}
public init(reactions: [MessageReaction], recentPeers: [RecentPeer]) {
public init(canViewList: Bool, reactions: [MessageReaction], recentPeers: [RecentPeer]) {
self.canViewList = canViewList
self.reactions = reactions
self.recentPeers = recentPeers
}
required public init(decoder: PostboxDecoder) {
self.canViewList = decoder.decodeBoolForKey("vl", orElse: true)
self.reactions = decoder.decodeObjectArrayWithDecoderForKey("r")
self.recentPeers = decoder.decodeObjectArrayWithDecoderForKey("rp")
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeBool(self.canViewList, forKey: "vl")
encoder.encodeObjectArray(self.reactions, forKey: "r")
encoder.encodeObjectArray(self.recentPeers, forKey: "rp")
}
public static func ==(lhs: ReactionsMessageAttribute, rhs: ReactionsMessageAttribute) -> Bool {
if lhs.canViewList != rhs.canViewList {
return false
}
if lhs.reactions != rhs.reactions {
return false
}

View File

@ -1978,13 +1978,7 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
if let currentStats = self.currentStats {
if currentStats.peers.isEmpty {
if reactionCount != 0 {
//TODO:localize
let text: String
if reactionCount == 1 {
text = "1 reaction"
} else {
text = "\(reactionCount) reactions"
}
let text: String = self.presentationData.strings.Chat_ContextReactionCount(Int32(reactionCount))
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {
var text = self.presentationData.strings.Conversation_ContextMenuNoViews
@ -2002,29 +1996,18 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
}
} else if currentStats.peers.count == 1 {
if reactionCount != 0 {
//TODO:localize
let text: String
if reactionCount == 1 {
text = "1 reacted"
} else {
text = "\(reactionCount) reacted"
}
let text: String = self.presentationData.strings.Chat_OutgoingContextReactionCount(Int32(reactionCount))
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {
self.textNode.attributedText = NSAttributedString(string: currentStats.peers[0].displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
}
} else {
if reactionCount != 0 {
//TODO:localize
let text: String
if reactionCount >= currentStats.peers.count {
if reactionCount == 1 {
text = "1 reacted"
} else {
text = "\(reactionCount) reacted"
}
text = self.presentationData.strings.Chat_OutgoingContextReactionCount(Int32(reactionCount))
} else {
text = "\(reactionCount)/\(currentStats.peers.count) reacted"
text = self.presentationData.strings.Chat_OutgoingContextMixedReactionCount("\(reactionCount)", "\(currentStats.peers.count)").string
}
self.textNode.attributedText = NSAttributedString(string: text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor)
} else {

View File

@ -1111,9 +1111,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
let reactions: ReactionsMessageAttribute
if shouldDisplayInlineDateReactions(message: item.message) {
reactions = ReactionsMessageAttribute(reactions: [], recentPeers: [])
reactions = ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
} else {
reactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(reactions: [], recentPeers: [])
reactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
}
var reactionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageReactionButtonsNode))?
if !reactions.reactions.isEmpty {

View File

@ -1435,9 +1435,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let bubbleReactions: ReactionsMessageAttribute
if needReactions {
bubbleReactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(reactions: [], recentPeers: [])
bubbleReactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
} else {
bubbleReactions = ReactionsMessageAttribute(reactions: [], recentPeers: [])
bubbleReactions = ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
}
if !bubbleReactions.reactions.isEmpty {
bottomNodeMergeStatus = .Both

View File

@ -549,9 +549,9 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
let reactions: ReactionsMessageAttribute
if shouldDisplayInlineDateReactions(message: item.message) {
reactions = ReactionsMessageAttribute(reactions: [], recentPeers: [])
reactions = ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
} else {
reactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(reactions: [], recentPeers: [])
reactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
}
var reactionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageReactionButtonsNode))?

View File

@ -14,6 +14,20 @@ import AccountContext
import WallpaperBackgroundNode
func canViewMessageReactionList(message: Message) -> Bool {
var found = false
for attribute in message.attributes {
if let attribute = attribute as? ReactionsMessageAttribute {
if !attribute.canViewList {
return false
}
found = true
}
}
if !found {
return false
}
if let peer = message.peers[message.id.peerId] {
if let channel = peer as? TelegramChannel {
if case .broadcast = channel.info {
@ -487,7 +501,7 @@ final class ChatMessageReactionsFooterContentNode: ChatMessageBubbleContentNode
}
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(reactions: [], recentPeers: [])
let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
let buttonsUpdate = buttonsNode.prepareUpdate(
context: item.context,
presentationData: item.presentationData,

View File

@ -655,9 +655,9 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
let reactions: ReactionsMessageAttribute
if shouldDisplayInlineDateReactions(message: item.message) {
reactions = ReactionsMessageAttribute(reactions: [], recentPeers: [])
reactions = ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
} else {
reactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(reactions: [], recentPeers: [])
reactions = mergedMessageReactions(attributes: item.message.attributes) ?? ReactionsMessageAttribute(canViewList: false, reactions: [], recentPeers: [])
}
var reactionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageReactionButtonsNode))?

View File

@ -1181,18 +1181,17 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
}
if isCreator || (channel.adminRights?.rights.contains(.canChangeInfo) == true) {
//TODO:localize
let label: String
if let cachedData = data.cachedData as? CachedChannelData, let allowedReactions = cachedData.allowedReactions {
if allowedReactions.isEmpty {
label = "Disabled"
label = presentationData.strings.PeerInfo_ReactionsDisabled
} else {
label = "\(allowedReactions.count)"
}
} else {
label = ""
}
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: "Reactions", icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: presentationData.strings.PeerInfo_Reactions, icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
interaction.editingOpenReactionsSetup()
}))
}
@ -1306,18 +1305,17 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
}
if isCreator || (channel.adminRights?.rights.contains(.canChangeInfo) == true) {
//TODO:localize
let label: String
if let cachedData = data.cachedData as? CachedChannelData, let allowedReactions = cachedData.allowedReactions {
if allowedReactions.isEmpty {
label = "Disabled"
label = presentationData.strings.PeerInfo_ReactionsDisabled
} else {
label = "\(allowedReactions.count)"
}
} else {
label = ""
}
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: "Reactions", icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: presentationData.strings.PeerInfo_Reactions, icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
interaction.editingOpenReactionsSetup()
}))
}
@ -1329,18 +1327,17 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
}
} else {
if isCreator || (channel.adminRights?.rights.contains(.canChangeInfo) == true) {
//TODO:localize
let label: String
if let cachedData = data.cachedData as? CachedChannelData, let allowedReactions = cachedData.allowedReactions {
if allowedReactions.isEmpty {
label = "Disabled"
label = presentationData.strings.PeerInfo_ReactionsDisabled
} else {
label = "\(allowedReactions.count)"
}
} else {
label = ""
}
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: "Reactions", icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
items[.peerPublicSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: presentationData.strings.PeerInfo_Reactions, icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
interaction.editingOpenReactionsSetup()
}))
}
@ -1440,18 +1437,17 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
}))
do {
//TODO:localize
let label: String
if let cachedData = data.cachedData as? CachedGroupData, let allowedReactions = cachedData.allowedReactions {
if allowedReactions.isEmpty {
label = "Disabled"
label = presentationData.strings.PeerInfo_ReactionsDisabled
} else {
label = "\(allowedReactions.count)"
}
} else {
label = ""
}
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: "Reactions", icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemReactions, label: .text(label), text: presentationData.strings.PeerInfo_Reactions, icon: UIImage(bundleImageName: "Settings/Menu/Reactions"), action: {
interaction.editingOpenReactionsSetup()
}))
}