Various fixes

This commit is contained in:
Ilya Laktyushin 2023-11-27 19:30:11 +04:00
parent 31925248bd
commit 3cc5782dec
7 changed files with 151 additions and 82 deletions

View File

@ -10554,3 +10554,6 @@ Sorry for the inconvenience.";
"Chat.ChannelRecommendation.PremiumTooltip" = "Subcribe to [Telegram Premium]() to unlock up to **100** channels.";
"Story.ForwardAuthorHiddenTooltip" = "The account was hidden by the user";
"Premium.Limits.RecommendedChannels" = "Similar Channels";
"Premium.Limits.RecommendedChannelsInfo" = "View up to 100 similar channels.";

View File

@ -198,29 +198,32 @@ private enum Limit: CaseIterable {
case folders
case chatsPerFolder
case account
case recommendedChannels
func title(strings: PresentationStrings) -> String {
switch self {
case .groups:
return strings.Premium_Limits_GroupsAndChannels
case .pins:
return strings.Premium_Limits_PinnedChats
case .publicLinks:
return strings.Premium_Limits_PublicLinks
case .savedGifs:
return strings.Premium_Limits_SavedGifs
case .favedStickers:
return strings.Premium_Limits_FavedStickers
case .about:
return strings.Premium_Limits_Bio
case .captions:
return strings.Premium_Limits_Captions
case .folders:
return strings.Premium_Limits_Folders
case .chatsPerFolder:
return strings.Premium_Limits_ChatsPerFolder
case .account:
return strings.Premium_Limits_Accounts
case .groups:
return strings.Premium_Limits_GroupsAndChannels
case .pins:
return strings.Premium_Limits_PinnedChats
case .publicLinks:
return strings.Premium_Limits_PublicLinks
case .savedGifs:
return strings.Premium_Limits_SavedGifs
case .favedStickers:
return strings.Premium_Limits_FavedStickers
case .about:
return strings.Premium_Limits_Bio
case .captions:
return strings.Premium_Limits_Captions
case .folders:
return strings.Premium_Limits_Folders
case .chatsPerFolder:
return strings.Premium_Limits_ChatsPerFolder
case .account:
return strings.Premium_Limits_Accounts
case .recommendedChannels:
return strings.Premium_Limits_RecommendedChannels
}
}
@ -246,6 +249,8 @@ private enum Limit: CaseIterable {
return strings.Premium_Limits_ChatsPerFolderInfo
case .account:
return strings.Premium_Limits_AccountsInfo
case .recommendedChannels:
return strings.Premium_Limits_RecommendedChannelsInfo
}
}
@ -272,6 +277,8 @@ private enum Limit: CaseIterable {
value = configuration.maxFolderChatsCount
case .account:
value = isPremium ? 4 : 3
case .recommendedChannels:
value = configuration.maxChannelRecommendationsCount
}
return "\(value)"
}
@ -360,7 +367,8 @@ private final class LimitsListComponent: CombinedComponent {
UIColor(rgb: 0xdb5887),
UIColor(rgb: 0xdb496f),
UIColor(rgb: 0xe95d44),
UIColor(rgb: 0xf2822a)
UIColor(rgb: 0xf2822a),
UIColor(rgb: 0xfdb529)
]
let items: [AnyComponentWithIdentity<Empty>] = Limit.allCases.enumerated().map { index, value in

View File

@ -87,8 +87,8 @@ enum StatsPostItem: Equatable {
} else {
return false
}
case let .story(lhsStory):
if case let .story(rhsStory) = rhs, lhsStory == rhsStory {
case let .story(lhsPeer, lhsStory):
if case let .story(rhsPeer, rhsStory) = rhs, lhsPeer == rhsPeer, lhsStory == rhsStory {
return true
} else {
return false
@ -97,7 +97,7 @@ enum StatsPostItem: Equatable {
}
case message(Message)
case story(EngineStoryItem)
case story(EnginePeer, EngineStoryItem)
var isStory: Bool {
if case .story = self {
@ -111,7 +111,7 @@ enum StatsPostItem: Equatable {
switch self {
case let .message(message):
return message.timestamp
case let .story(story):
case let .story(_, story):
return story.timestamp
}
}
@ -656,7 +656,7 @@ private enum StatsEntry: ItemListNodeEntry {
return StatsMessageItem(context: arguments.context, presentationData: presentationData, peer: peer, item: post, views: interactions.views, reactions: interactions.reactions, forwards: interactions.forwards, sectionId: self.section, style: .blocks, action: {
arguments.openPostStats(EnginePeer(peer), post)
}, openStory: { sourceView in
if case let .story(story) = post {
if case let .story(_, story) = post {
arguments.openStory(story, sourceView)
}
}, contextAction: !post.isStory ? { node, gesture in
@ -908,7 +908,7 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p
if let stories {
for story in stories.items {
if let _ = interactions[.story(peerId: peer.id, id: story.id)] {
posts.append(.story(story))
posts.append(.story(peer, story))
}
}
}
@ -923,7 +923,7 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p
if let interactions = interactions[.message(id: message.id)] {
entries.append(.post(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer._asPeer(), post, interactions))
}
case let .story(story):
case let .story(_, story):
if let interactions = interactions[.story(peerId: peer.id, id: story.id)] {
entries.append(.post(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer._asPeer(), post, interactions))
}
@ -1313,7 +1313,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
switch post {
case let .message(message):
subject = .message(id: message.id)
case let .story(story):
case let .story(_, story):
subject = .story(peerId: peerId, id: story.id, item: story, fromStory: false)
}
controller?.push(messageStatsController(context: context, subject: subject))

View File

@ -21,11 +21,13 @@ private final class MessageStatsControllerArguments {
let context: AccountContext
let loadDetailedGraph: (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>
let openMessage: (EngineMessage.Id) -> Void
let openStory: (EnginePeer.Id, EngineStoryItem, UIView) -> Void
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openMessage: @escaping (EngineMessage.Id) -> Void) {
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openMessage: @escaping (EngineMessage.Id) -> Void, openStory: @escaping (EnginePeer.Id, EngineStoryItem, UIView) -> Void) {
self.context = context
self.loadDetailedGraph = loadDetailedGraph
self.openMessage = openMessage
self.openStory = openStory
}
}
@ -47,7 +49,7 @@ private enum StatsEntry: ItemListNodeEntry {
case reactionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType, Bool)
case publicForwardsTitle(PresentationTheme, String)
case publicForward(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, EngineMessage)
case publicForward(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsPostItem)
var section: ItemListSectionId {
switch self {
@ -133,8 +135,8 @@ private enum StatsEntry: ItemListNodeEntry {
} else {
return false
}
case let .publicForward(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsMessage):
if case let .publicForward(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsMessage) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsMessage.id == rhsMessage.id {
case let .publicForward(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPost):
if case let .publicForward(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPost) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsPost == rhsPost {
return true
} else {
return false
@ -164,38 +166,44 @@ private enum StatsEntry: ItemListNodeEntry {
}
})
}, sectionId: self.section, style: .blocks)
case let .publicForward(_, _, _, _, message):
case let .publicForward(_, _, _, _, item):
var views: Int32 = 0
var forwards: Int32 = 0
var reactions: Int32 = 0
for attribute in message.attributes {
if let viewsAttribute = attribute as? ViewCountMessageAttribute {
views = Int32(viewsAttribute.count)
} else if let forwardsAttribute = attribute as? ForwardCountMessageAttribute {
forwards = Int32(forwardsAttribute.count)
} else if let reactionsAttribute = attribute as? ReactionsMessageAttribute {
reactions = reactionsAttribute.reactions.reduce(0, { partialResult, reaction in
return partialResult + reaction.count
})
let peer: Peer
switch item {
case let .message(message):
peer = message.peers[message.id.peerId]!
for attribute in message.attributes {
if let viewsAttribute = attribute as? ViewCountMessageAttribute {
views = Int32(viewsAttribute.count)
} else if let forwardsAttribute = attribute as? ForwardCountMessageAttribute {
forwards = Int32(forwardsAttribute.count)
} else if let reactionsAttribute = attribute as? ReactionsMessageAttribute {
reactions = reactionsAttribute.reactions.reduce(0, { partialResult, reaction in
return partialResult + reaction.count
})
}
}
case let .story(peerValue, story):
peer = peerValue._asPeer()
views = Int32(story.views?.seenCount ?? 0)
forwards = Int32(story.views?.forwardCount ?? 0)
reactions = Int32(story.views?.reactedCount ?? 0)
}
let peer = message.peers[message.id.peerId]!
return StatsMessageItem(context: arguments.context, presentationData: presentationData, peer: peer, item: .message(message._asMessage()), views: views, reactions: reactions, forwards: forwards, isPeer: true, sectionId: self.section, style: .blocks, action: {
arguments.openMessage(message.id)
}, openStory: { _ in }, contextAction: nil)
// var views: Int32 = 0
// for attribute in message.attributes {
// if let viewsAttribute = attribute as? ViewCountMessageAttribute {
// views = Int32(viewsAttribute.count)
// break
// }
// }
//
//
// let text: String = presentationData.strings.Stats_MessageViews(views)
// return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: .firstLast, context: arguments.context, peer: EnginePeer(message.peers[message.id.peerId]!), height: .generic, aliasHandling: .standard, nameColor: .primary, nameStyle: .plain, presence: nil, text: .text(text, .secondary), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: nil), revealOptions: nil, switchValue: nil, enabled: true, highlighted: false, selectable: true, sectionId: self.section, action: {
// arguments.openMessage(message.id)
// }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: nil)
return StatsMessageItem(context: arguments.context, presentationData: presentationData, peer: peer, item: item, views: views, reactions: reactions, forwards: forwards, isPeer: true, sectionId: self.section, style: .blocks, action: {
switch item {
case let .message(message):
arguments.openMessage(message.id)
case .story:
break
}
}, openStory: { view in
if case let .story(peer, story) = item {
arguments.openStory(peer.id, story, view)
}
}, contextAction: nil)
}
}
}
@ -243,7 +251,7 @@ private func messageStatsControllerEntries(data: PostStats?, storyViews: EngineS
entries.append(.publicForwardsTitle(presentationData.theme, presentationData.strings.Stats_MessagePublicForwardsTitle.uppercased()))
var index: Int32 = 0
for message in messages.messages {
entries.append(.publicForward(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, EngineMessage(message)))
entries.append(.publicForward(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, .message(message)))
index += 1
}
}
@ -254,9 +262,9 @@ private func messageStatsControllerEntries(data: PostStats?, storyViews: EngineS
for forward in forwards.forwards {
switch forward {
case let .message(message):
entries.append(.publicForward(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, message))
case let .story(story):
let _ = story
entries.append(.publicForward(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, .message(message._asMessage())))
case let .story(peer, story):
entries.append(.publicForward(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, .story(peer, story)))
}
index += 1
}
@ -296,7 +304,7 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
let anyStatsContext: Any
let dataSignal: Signal<PostStats?, NoError>
var loadDetailedGraphImpl: ((StatsGraph, Int64) -> Signal<StatsGraph?, NoError>)?
var openStoryImpl: ((EngineStoryItem, UIView) -> Void)?
var openStoryImpl: ((EnginePeer.Id, EngineStoryItem, UIView) -> Void)?
var forwardsContext: StoryStatsPublicForwardsContext?
let peerId: EnginePeer.Id
@ -363,6 +371,8 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
return loadDetailedGraphImpl?(graph, x) ?? .single(nil)
}, openMessage: { messageId in
navigateToMessageImpl?(messageId)
}, openStory: { peerId, story, view in
openStoryImpl?(peerId, story, view)
})
let longLoadingSignal: Signal<Bool, NoError> = .single(false) |> then(.single(true) |> delay(2.0, queue: Queue.mainQueue()))
@ -422,7 +432,7 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: iconNode.flatMap { ItemListNavigationButton(content: .node($0), style: .regular, enabled: true, action: { [weak iconNode] in
if let iconNode, let storyItem {
openStoryImpl?(storyItem, iconNode.view)
openStoryImpl?(peerId, storyItem, iconNode.view)
}
}) }, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: messageStatsControllerEntries(data: data, storyViews: storyViews, messages: search?.0, forwards: forwards, presentationData: presentationData), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
@ -464,7 +474,7 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
}
})
}
openStoryImpl = { [weak controller] story, sourceView in
openStoryImpl = { [weak controller] peerId, story, sourceView in
let storyContent = SingleStoryContentContextImpl(context: context, storyId: StoryId(peerId: peerId, id: story.id), storyItem: story, readGlobally: false)
let _ = (storyContent.state
|> take(1)

View File

@ -13,6 +13,7 @@ import ItemListUI
import PresentationDataUtils
import PhotoResources
import AvatarStoryIndicatorComponent
import AvatarNode
public class StatsMessageItem: ListViewItem, ItemListItem {
let context: AccountContext
@ -82,7 +83,6 @@ public class StatsMessageItem: ListViewItem, ItemListItem {
public func selected(listView: ListView){
listView.clearHighlightAnimated(true)
self.action?()
}
}
@ -105,6 +105,7 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
private var extractedRect: CGRect?
private var nonExtractedRect: CGRect?
var avatarNode: AvatarNode?
let contentImageNode: TransformImageNode
var storyIndicator: ComponentView<Empty>?
var storyButton: HighlightTrackingButton?
@ -245,11 +246,30 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
return result
}
override func selected() {
guard let item = self.item else {
return
}
if item.isPeer {
if case .story = item.item {
self.storyPressed()
} else {
item.action?()
}
} else {
item.action?()
}
}
@objc private func storyPressed() {
guard let item = self.item else {
return
}
item.openStory(self.contentImageNode.view)
if let avatarNode = self.avatarNode {
item.openStory(avatarNode.view)
} else {
item.openStory(self.contentImageNode.view)
}
}
public func asyncLayout() -> (_ item: StatsMessageItem, _ params: ListViewItemLayoutParams, _ insets: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
@ -316,7 +336,7 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
}
}
timestamp = message.timestamp
case let .story(story):
case let .story(_, story):
text = item.presentationData.strings.Message_Story
timestamp = story.timestamp
if let image = story.media._asMedia() as? TelegramMediaImage {
@ -349,7 +369,7 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
} else if let file = contentImageMedia as? TelegramMediaFile {
updateImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(message.id.peerId), videoReference: .message(message: MessageReference(message), media: file), autoFetchFullSizeThumbnail: true)
}
case let .story(story):
case let .story(_, story):
if let peerReference = PeerReference(item.peer) {
if let image = contentImageMedia as? TelegramMediaImage {
updateImageSignal = mediaGridMessagePhoto(account: item.context.account, userLocation: .peer(item.peer.id), photoReference: .story(peer: peerReference, id: story.id, media: image))
@ -435,15 +455,36 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
}
var contentImageSize = CGSize(width: 40.0, height: 40.0)
var contentImageInset = leftInset - 6.0
var dimensions: CGSize?
if let contentImageMedia = contentImageMedia as? TelegramMediaImage {
dimensions = largestRepresentationForPhoto(contentImageMedia)?.dimensions.cgSize
} else if let contentImageMedia = contentImageMedia as? TelegramMediaFile {
dimensions = contentImageMedia.dimensions?.cgSize
if item.isPeer {
let avatarNode: AvatarNode
if let current = strongSelf.avatarNode {
avatarNode = current
} else {
avatarNode = AvatarNode(font: avatarPlaceholderFont(size: floor(40.0 * 16.0 / 37.0)))
strongSelf.offsetContainerNode.addSubnode(avatarNode)
strongSelf.avatarNode = avatarNode
}
avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: EnginePeer(item.peer))
if case .story = item.item {
contentImageInset += 3.0
contentImageSize = CGSize(width: 34.0, height: 34.0)
}
} else {
strongSelf.avatarNode?.removeFromSupernode()
strongSelf.avatarNode = nil
if let contentImageMedia = contentImageMedia as? TelegramMediaImage {
dimensions = largestRepresentationForPhoto(contentImageMedia)?.dimensions.cgSize
} else if let contentImageMedia = contentImageMedia as? TelegramMediaFile {
dimensions = contentImageMedia.dimensions?.cgSize
}
}
var contentImageSize = CGSize(width: 40.0, height: 40.0)
var contentImageInset = leftInset - 6.0
if let dimensions = dimensions {
let makeImageLayout = strongSelf.contentImageNode.asyncLayout()
@ -540,6 +581,10 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
let contentImageFrame = CGRect(origin: CGPoint(x: contentImageInset, y: floorToScreenPixels((height - contentImageSize.height) / 2.0)), size: contentImageSize)
strongSelf.contentImageNode.frame = contentImageFrame
if let avatarNode = strongSelf.avatarNode {
avatarNode.frame = contentImageFrame
}
let titleFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: 9.0), size: titleLayout.size)
strongSelf.titleNode.frame = titleFrame

View File

@ -281,7 +281,8 @@ private final class StoryStatsPublicForwardsContextImpl {
resultForwards.append(.message(EngineMessage(renderedMessage)))
}
case let .publicForwardStory(apiPeer, apiStory):
if let storedItem = Stories.StoredItem(apiStoryItem: apiStory, peerId: apiPeer.peerId, transaction: transaction), case let .item(item) = storedItem, let media = item.media {
if let storedItem = Stories.StoredItem(apiStoryItem: apiStory, peerId: apiPeer.peerId, transaction: transaction), case let .item(item) = storedItem, let media = item.media, let peer = peers[apiPeer.peerId] {
let mappedItem = EngineStoryItem(
id: item.id,
timestamp: item.timestamp,
@ -316,7 +317,7 @@ private final class StoryStatsPublicForwardsContextImpl {
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) }
)
resultForwards.append(.story(mappedItem))
resultForwards.append(.story(EnginePeer(peer), mappedItem))
}
}
}
@ -359,7 +360,7 @@ public final class StoryStatsPublicForwardsContext {
public struct State: Equatable {
public enum Forward: Equatable {
case message(EngineMessage)
case story(EngineStoryItem)
case story(EnginePeer, EngineStoryItem)
}
public var forwards: [Forward]
public var isLoadingMore: Bool

View File

@ -116,7 +116,9 @@ final class StoryAuthorInfoComponent: Component {
let timeString = stringForStoryActivityTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, preciseTime: true, relativeTimestamp: component.timestamp, relativeTo: timestamp, short: true)
let combinedString = NSMutableAttributedString()
combinedString.append(NSAttributedString(string: authorName, font: Font.medium(11.0), textColor: titleColor))
combinedString.append(NSAttributedString(string: "\(timeString)", font: Font.regular(11.0), textColor: subtitleColor))
if timeString.count < 6 {
combinedString.append(NSAttributedString(string: "\(timeString)", font: Font.regular(11.0), textColor: subtitleColor))
}
subtitle = combinedString
subtitleTruncationType = .middle
} else {