mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Statistics improvements
This commit is contained in:
parent
1fced74098
commit
13baadc3e7
@ -10498,7 +10498,13 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Stats.MessageReactionsTitle" = "REACTIONS";
|
||||
|
||||
"MediaEditor.RemoveVideo" = "Remove Video";
|
||||
|
||||
"Conversation.LaunchApp" = "LAUNCH APP";
|
||||
|
||||
"Message.AdSponsoredLabel" = "Sponsored";
|
||||
"Message.AdRecommendedLabel" = "Recommended";
|
||||
|
||||
"Stats.StoryTitle" = "Story Statistics";
|
||||
|
||||
"Channel.Info.Settings" = "Channel Settings";
|
||||
|
@ -213,7 +213,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
}
|
||||
|
||||
return ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: nameSortOrder,
|
||||
displayOrder: nameDisplayOrder,
|
||||
context: context,
|
||||
|
@ -355,7 +355,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
}
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListAdditionalCategoryItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
context: context,
|
||||
title: title,
|
||||
image: image,
|
||||
@ -569,7 +569,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -608,7 +608,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
let status: ContactsPeerItemStatus = .none
|
||||
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -670,7 +670,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
let peerContent: ContactsPeerItemPeer = .peer(peer: contactEntry.peer, chatPeer: contactEntry.peer)
|
||||
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -889,7 +889,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -928,7 +928,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
let status: ContactsPeerItemStatus = .none
|
||||
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -990,7 +990,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
let peerContent: ContactsPeerItemPeer = .peer(peer: contactEntry.peer, chatPeer: contactEntry.peer)
|
||||
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -1057,7 +1057,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
}
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListAdditionalCategoryItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat),
|
||||
context: context,
|
||||
title: title,
|
||||
image: image,
|
||||
|
@ -161,12 +161,14 @@ public final class ItemListPresentationData: Equatable {
|
||||
public let fontSize: PresentationFontSize
|
||||
public let strings: PresentationStrings
|
||||
public let nameDisplayOrder: PresentationPersonNameOrder
|
||||
public let dateTimeFormat: PresentationDateTimeFormat
|
||||
|
||||
public init(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) {
|
||||
public init(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat) {
|
||||
self.theme = theme
|
||||
self.fontSize = fontSize
|
||||
self.strings = strings
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
}
|
||||
|
||||
public static func ==(lhs: ItemListPresentationData, rhs: ItemListPresentationData) -> Bool {
|
||||
@ -182,6 +184,9 @@ public final class ItemListPresentationData: Equatable {
|
||||
if lhs.nameDisplayOrder != rhs.nameDisplayOrder {
|
||||
return false
|
||||
}
|
||||
if lhs.dateTimeFormat != rhs.dateTimeFormat {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -232,6 +237,6 @@ public extension PresentationFontSize {
|
||||
|
||||
public extension ItemListPresentationData {
|
||||
convenience init(_ presentationData: PresentationData) {
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder)
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat)
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ swift_library(
|
||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||
"//submodules/Display:Display",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/Postbox:Postbox",
|
||||
"//submodules/TelegramCore:TelegramCore",
|
||||
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||
@ -35,6 +36,7 @@ swift_library(
|
||||
"//submodules/PremiumUI:PremiumUI",
|
||||
"//submodules/InviteLinksUI:InviteLinksUI",
|
||||
"//submodules/ShareController:ShareController",
|
||||
"//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -27,7 +27,7 @@ private let initialBoostersDisplayedLimit: Int32 = 5
|
||||
private final class ChannelStatsControllerArguments {
|
||||
let context: AccountContext
|
||||
let loadDetailedGraph: (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>
|
||||
let openMessageStats: (MessageId) -> Void
|
||||
let openPostStats: (EnginePeer, StatsPostItem) -> Void
|
||||
let contextAction: (MessageId, ASDisplayNode, ContextGesture?) -> Void
|
||||
let copyBoostLink: (String) -> Void
|
||||
let shareBoostLink: (String) -> Void
|
||||
@ -37,10 +37,10 @@ private final class ChannelStatsControllerArguments {
|
||||
let createPrepaidGiveaway: (PrepaidGiveaway) -> Void
|
||||
let updateGiftsSelected: (Bool) -> Void
|
||||
|
||||
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openMessage: @escaping (MessageId) -> Void, contextAction: @escaping (MessageId, ASDisplayNode, ContextGesture?) -> Void, copyBoostLink: @escaping (String) -> Void, shareBoostLink: @escaping (String) -> Void, openBoost: @escaping (ChannelBoostersContext.State.Boost) -> Void, expandBoosters: @escaping () -> Void, openGifts: @escaping () -> Void, createPrepaidGiveaway: @escaping (PrepaidGiveaway) -> Void, updateGiftsSelected: @escaping (Bool) -> Void) {
|
||||
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openPostStats: @escaping (EnginePeer, StatsPostItem) -> Void, contextAction: @escaping (MessageId, ASDisplayNode, ContextGesture?) -> Void, copyBoostLink: @escaping (String) -> Void, shareBoostLink: @escaping (String) -> Void, openBoost: @escaping (ChannelBoostersContext.State.Boost) -> Void, expandBoosters: @escaping () -> Void, openGifts: @escaping () -> Void, createPrepaidGiveaway: @escaping (PrepaidGiveaway) -> Void, updateGiftsSelected: @escaping (Bool) -> Void) {
|
||||
self.context = context
|
||||
self.loadDetailedGraph = loadDetailedGraph
|
||||
self.openMessageStats = openMessage
|
||||
self.openPostStats = openPostStats
|
||||
self.contextAction = contextAction
|
||||
self.copyBoostLink = copyBoostLink
|
||||
self.shareBoostLink = shareBoostLink
|
||||
@ -75,6 +75,45 @@ private enum StatsSection: Int32 {
|
||||
case gifts
|
||||
}
|
||||
|
||||
enum StatsPostItem: Equatable {
|
||||
static func == (lhs: StatsPostItem, rhs: StatsPostItem) -> Bool {
|
||||
switch lhs {
|
||||
case let .message(lhsMessage):
|
||||
if case let .message(rhsMessage) = rhs {
|
||||
return lhsMessage.id == rhsMessage.id
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .story(lhsStory):
|
||||
if case let .story(rhsStory) = rhs, lhsStory == rhsStory {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case message(Message)
|
||||
case story(EngineStoryItem)
|
||||
|
||||
var isStory: Bool {
|
||||
if case .story = self {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var timestamp: Int32 {
|
||||
switch self {
|
||||
case let .message(message):
|
||||
return message.timestamp
|
||||
case let .story(story):
|
||||
return story.timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum StatsEntry: ItemListNodeEntry {
|
||||
case overviewTitle(PresentationTheme, String, String)
|
||||
case overview(PresentationTheme, ChannelStats)
|
||||
@ -116,7 +155,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
case instantPageInteractionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType)
|
||||
|
||||
case postsTitle(PresentationTheme, String)
|
||||
case post(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Message, ChannelStatsMessageInteractions)
|
||||
case post(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer, StatsPostItem, ChannelStatsMessageInteractions)
|
||||
|
||||
case boostLevel(PresentationTheme, Int32, Int32, CGFloat)
|
||||
|
||||
@ -242,7 +281,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
return 25
|
||||
case .postsTitle:
|
||||
return 26
|
||||
case let .post(index, _, _, _, _, _):
|
||||
case let .post(index, _, _, _, _, _, _):
|
||||
return 27 + index
|
||||
case .boostLevel:
|
||||
return 2000
|
||||
@ -445,8 +484,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .post(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsMessage, lhsInteractions):
|
||||
if case let .post(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsMessage, rhsInteractions) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsMessage.id == rhsMessage.id, lhsInteractions == rhsInteractions {
|
||||
case let .post(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsPost, lhsInteractions):
|
||||
if case let .post(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsPost, rhsInteractions) = rhs, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, arePeersEqual(lhsPeer, rhsPeer), lhsPost == rhsPost, lhsInteractions == rhsInteractions {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -610,12 +649,14 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
}
|
||||
})
|
||||
}, sectionId: self.section, style: .blocks)
|
||||
case let .post(_, _, _, _, message, interactions):
|
||||
return StatsMessageItem(context: arguments.context, presentationData: presentationData, message: message, views: interactions.views, forwards: interactions.forwards, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openMessageStats(message.id)
|
||||
}, contextAction: { node, gesture in
|
||||
case let .post(_, _, _, _, peer, post, interactions):
|
||||
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)
|
||||
}, contextAction: !post.isStory ? { node, gesture in
|
||||
if case let .message(message) = post {
|
||||
arguments.contextAction(message.id, node, gesture)
|
||||
})
|
||||
}
|
||||
} : nil)
|
||||
case let .boosterTabs(_, boostText, giftText, giftSelected):
|
||||
return BoostsTabsItem(theme: presentationData.theme, boostsText: boostText, giftsText: giftText, selectedTab: giftSelected ? .gifts : .boosts, sectionId: self.section, selectionUpdated: { tab in
|
||||
arguments.updateGiftsSelected(tab == .gifts)
|
||||
@ -775,7 +816,7 @@ private struct ChannelStatsControllerState: Equatable {
|
||||
}
|
||||
|
||||
|
||||
private func channelStatsControllerEntries(state: ChannelStatsControllerState, peer: EnginePeer?, data: ChannelStats?, messages: [Message]?, interactions: [MessageId: ChannelStatsMessageInteractions]?, boostData: ChannelBoostStatus?, boostersState: ChannelBoostersContext.State?, giftsState: ChannelBoostersContext.State?, presentationData: PresentationData, giveawayAvailable: Bool) -> [StatsEntry] {
|
||||
private func channelStatsControllerEntries(state: ChannelStatsControllerState, peer: EnginePeer?, data: ChannelStats?, messages: [Message]?, stories: PeerStoryListContext.State?, interactions: [MessageId: ChannelStatsMessageInteractions]?, boostData: ChannelBoostStatus?, boostersState: ChannelBoostersContext.State?, giftsState: ChannelBoostersContext.State?, presentationData: PresentationData, giveawayAvailable: Bool) -> [StatsEntry] {
|
||||
var entries: [StatsEntry] = []
|
||||
|
||||
switch state.section {
|
||||
@ -847,14 +888,35 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p
|
||||
entries.append(.storyReactionsByEmotionGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.storyReactionsByEmotionGraph, .bars))
|
||||
}
|
||||
|
||||
if let messages = messages, !messages.isEmpty, let interactions = interactions, !interactions.isEmpty {
|
||||
|
||||
var posts: [StatsPostItem] = []
|
||||
if let messages, let interactions {
|
||||
for message in messages {
|
||||
if let _ = interactions[message.id] {
|
||||
posts.append(.message(message))
|
||||
}
|
||||
}
|
||||
}
|
||||
if let stories {
|
||||
for story in stories.items {
|
||||
posts.append(.story(story))
|
||||
}
|
||||
}
|
||||
posts.sort(by: { $0.timestamp > $1.timestamp })
|
||||
|
||||
if !posts.isEmpty, let interactions, let peer = peer?._asPeer() {
|
||||
entries.append(.postsTitle(presentationData.theme, presentationData.strings.Stats_PostsTitle))
|
||||
var index: Int32 = 0
|
||||
for message in messages {
|
||||
for post in posts {
|
||||
switch post {
|
||||
case let .message(message):
|
||||
if let interactions = interactions[message.id] {
|
||||
entries.append(.post(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, message, interactions))
|
||||
index += 1
|
||||
entries.append(.post(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, post, interactions))
|
||||
}
|
||||
case let .story(story):
|
||||
entries.append(.post(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, post, ChannelStatsMessageInteractions(messageId: MessageId(peerId: PeerId(0), namespace: 0, id: 0), views: Int32(story.views?.seenCount ?? 0), forwards: Int32(story.views?.forwardCount ?? 0), reactions: Int32(story.views?.reactedCount ?? 0))))
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -979,13 +1041,15 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||
|
||||
var openMessageStatsImpl: ((MessageId) -> Void)?
|
||||
var openPostStatsImpl: ((EnginePeer, StatsPostItem) -> Void)?
|
||||
var contextActionImpl: ((MessageId, ASDisplayNode, ContextGesture?) -> Void)?
|
||||
|
||||
let actionsDisposable = DisposableSet()
|
||||
let dataPromise = Promise<ChannelStats?>(nil)
|
||||
let messagesPromise = Promise<MessageHistoryView?>(nil)
|
||||
|
||||
let storiesPromise = Promise<PeerStoryListContext.State?>()
|
||||
|
||||
let datacenterId: Int32 = statsDatacenterId ?? 0
|
||||
|
||||
let statsContext = ChannelStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, peerId: peerId)
|
||||
@ -1027,8 +1091,8 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
|
||||
let arguments = ChannelStatsControllerArguments(context: context, loadDetailedGraph: { graph, x -> Signal<StatsGraph?, NoError> in
|
||||
return statsContext.loadDetailedGraph(graph, x: x)
|
||||
}, openMessage: { messageId in
|
||||
openMessageStatsImpl?(messageId)
|
||||
}, openPostStats: { peer, item in
|
||||
openPostStatsImpl?(peer, item)
|
||||
}, contextAction: { messageId, node, gesture in
|
||||
contextActionImpl?(messageId, node, gesture)
|
||||
}, copyBoostLink: { link in
|
||||
@ -1138,6 +1202,16 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
}
|
||||
messagesPromise.set(.single(nil) |> then(messageView))
|
||||
|
||||
let storyList = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: false)
|
||||
storyList.loadMore()
|
||||
storiesPromise.set(
|
||||
.single(nil)
|
||||
|> then(
|
||||
storyList.state
|
||||
|> map(Optional.init)
|
||||
)
|
||||
)
|
||||
|
||||
let longLoadingSignal: Signal<Bool, NoError> = .single(false) |> then(.single(true) |> delay(2.0, queue: Queue.mainQueue()))
|
||||
|
||||
let previousData = Atomic<ChannelStats?>(value: nil)
|
||||
@ -1149,13 +1223,14 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)),
|
||||
dataPromise.get(),
|
||||
messagesPromise.get(),
|
||||
storiesPromise.get(),
|
||||
boostData,
|
||||
boostsContext.state,
|
||||
giftsContext.state,
|
||||
longLoadingSignal
|
||||
)
|
||||
|> deliverOnMainQueue
|
||||
|> map { presentationData, state, peer, data, messageView, boostData, boostersState, giftsState, longLoading -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
|> map { presentationData, state, peer, data, messageView, stories, boostData, boostersState, giftsState, longLoading -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let previous = previousData.swap(data)
|
||||
var emptyStateItem: ItemListControllerEmptyStateItem?
|
||||
switch state.section {
|
||||
@ -1183,13 +1258,14 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .sectionControl([presentationData.strings.Stats_Statistics, presentationData.strings.Stats_Boosts], state.section == .boosts ? 1 : 0), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelStatsControllerEntries(state: state, peer: peer, data: data, messages: messages, interactions: interactions, boostData: boostData, boostersState: boostersState, giftsState: giftsState, presentationData: presentationData, giveawayAvailable: premiumConfiguration.giveawayGiftsPurchaseAvailable), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelStatsControllerEntries(state: state, peer: peer, data: data, messages: messages, stories: stories, interactions: interactions, boostData: boostData, boostersState: boostersState, giftsState: giftsState, presentationData: presentationData, giveawayAvailable: premiumConfiguration.giveawayGiftsPurchaseAvailable), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|> afterDisposed {
|
||||
actionsDisposable.dispose()
|
||||
let _ = statsContext.state
|
||||
let _ = storyList.state
|
||||
}
|
||||
|
||||
let controller = ItemListController(context: context, state: signal)
|
||||
@ -1206,8 +1282,15 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
||||
controller.didDisappear = { [weak controller] _ in
|
||||
controller?.clearItemNodesHighlight(animated: true)
|
||||
}
|
||||
openMessageStatsImpl = { [weak controller] messageId in
|
||||
controller?.push(messageStatsController(context: context, messageId: messageId, statsDatacenterId: statsDatacenterId))
|
||||
openPostStatsImpl = { [weak controller] peer, post in
|
||||
let subject: StatsSubject
|
||||
switch post {
|
||||
case let .message(message):
|
||||
subject = .message(id: message.id)
|
||||
case let .story(story):
|
||||
subject = .story(peer: peer, storyItem: story)
|
||||
}
|
||||
controller?.push(messageStatsController(context: context, subject: subject, statsDatacenterId: statsDatacenterId))
|
||||
}
|
||||
contextActionImpl = { [weak controller] messageId, sourceNode, gesture in
|
||||
guard let controller = controller, let sourceNode = sourceNode as? ContextExtractedContentContainingNode else {
|
||||
|
@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
@ -35,7 +36,7 @@ private enum StatsSection: Int32 {
|
||||
|
||||
private enum StatsEntry: ItemListNodeEntry {
|
||||
case overviewTitle(PresentationTheme, String)
|
||||
case overview(PresentationTheme, MessageStats, Int32?)
|
||||
case overview(PresentationTheme, PostStats, Int32?)
|
||||
|
||||
case interactionsTitle(PresentationTheme, String)
|
||||
case interactionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType)
|
||||
@ -89,8 +90,14 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
return false
|
||||
}
|
||||
case let .overview(lhsTheme, lhsStats, lhsPublicShares):
|
||||
if case let .overview(rhsTheme, rhsStats, rhsPublicShares) = rhs, lhsTheme === rhsTheme, lhsStats == rhsStats, lhsPublicShares == rhsPublicShares {
|
||||
return true
|
||||
if case let .overview(rhsTheme, rhsStats, rhsPublicShares) = rhs, lhsTheme === rhsTheme, lhsPublicShares == rhsPublicShares {
|
||||
if let lhsMessageStats = lhsStats as? MessageStats, let rhsMessageStats = rhsStats as? MessageStats {
|
||||
return lhsMessageStats == rhsMessageStats
|
||||
} else if let lhsStoryStats = lhsStats as? StoryStats, let rhsStoryStats = rhsStats as? StoryStats {
|
||||
return lhsStoryStats == rhsStoryStats
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@ -172,7 +179,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
private func messageStatsControllerEntries(data: MessageStats?, messages: SearchMessagesResult?, presentationData: PresentationData) -> [StatsEntry] {
|
||||
private func messageStatsControllerEntries(data: PostStats?, messages: SearchMessagesResult?, presentationData: PresentationData) -> [StatsEntry] {
|
||||
var entries: [StatsEntry] = []
|
||||
|
||||
if let data = data {
|
||||
@ -212,33 +219,76 @@ private func messageStatsControllerEntries(data: MessageStats?, messages: Search
|
||||
return entries
|
||||
}
|
||||
|
||||
public func messageStatsController(context: AccountContext, messageId: EngineMessage.Id, statsDatacenterId: Int32?) -> ViewController {
|
||||
public enum StatsSubject {
|
||||
case message(id: EngineMessage.Id)
|
||||
case story(peer: EnginePeer, storyItem: EngineStoryItem)
|
||||
}
|
||||
|
||||
protocol PostStats {
|
||||
var views: Int { get }
|
||||
var forwards: Int { get }
|
||||
var interactionsGraph: StatsGraph { get }
|
||||
var interactionsGraphDelta: Int64 { get }
|
||||
var reactionsGraph: StatsGraph { get }
|
||||
}
|
||||
|
||||
extension MessageStats: PostStats {
|
||||
|
||||
}
|
||||
|
||||
extension StoryStats: PostStats {
|
||||
|
||||
}
|
||||
|
||||
public func messageStatsController(context: AccountContext, subject: StatsSubject, statsDatacenterId: Int32?) -> ViewController {
|
||||
var navigateToMessageImpl: ((EngineMessage.Id) -> Void)?
|
||||
|
||||
let actionsDisposable = DisposableSet()
|
||||
let dataPromise = Promise<MessageStats?>(nil)
|
||||
let dataPromise = Promise<PostStats?>(nil)
|
||||
let messagesPromise = Promise<(SearchMessagesResult, SearchMessagesState)?>(nil)
|
||||
|
||||
let datacenterId: Int32 = statsDatacenterId ?? 0
|
||||
|
||||
let statsContext = MessageStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, messageId: messageId)
|
||||
let dataSignal: Signal<MessageStats?, NoError> = statsContext.state
|
||||
let anyStatsContext: Any
|
||||
let dataSignal: Signal<PostStats?, NoError>
|
||||
var loadDetailedGraphImpl: ((StatsGraph, Int64) -> Signal<StatsGraph?, NoError>)?
|
||||
switch subject {
|
||||
case let .message(id):
|
||||
let statsContext = MessageStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, messageId: id)
|
||||
loadDetailedGraphImpl = { [weak statsContext] graph, x in
|
||||
return statsContext?.loadDetailedGraph(graph, x: x) ?? .single(nil)
|
||||
}
|
||||
dataSignal = statsContext.state
|
||||
|> map { state in
|
||||
return state.stats
|
||||
}
|
||||
dataPromise.set(.single(nil) |> then(dataSignal))
|
||||
anyStatsContext = statsContext
|
||||
case let .story(peer, storyItem):
|
||||
let statsContext = StoryStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, peerId: peer.id, storyId: storyItem.id)
|
||||
loadDetailedGraphImpl = { [weak statsContext] graph, x in
|
||||
return statsContext?.loadDetailedGraph(graph, x: x) ?? .single(nil)
|
||||
}
|
||||
dataSignal = statsContext.state
|
||||
|> map { state in
|
||||
return state.stats
|
||||
}
|
||||
dataPromise.set(.single(nil) |> then(dataSignal))
|
||||
anyStatsContext = statsContext
|
||||
}
|
||||
|
||||
let arguments = MessageStatsControllerArguments(context: context, loadDetailedGraph: { graph, x -> Signal<StatsGraph?, NoError> in
|
||||
return statsContext.loadDetailedGraph(graph, x: x)
|
||||
return loadDetailedGraphImpl?(graph, x) ?? .single(nil)
|
||||
}, openMessage: { messageId in
|
||||
navigateToMessageImpl?(messageId)
|
||||
})
|
||||
|
||||
let longLoadingSignal: Signal<Bool, NoError> = .single(false) |> then(.single(true) |> delay(2.0, queue: Queue.mainQueue()))
|
||||
|
||||
let previousData = Atomic<MessageStats?>(value: nil)
|
||||
let previousData = Atomic<PostStats?>(value: nil)
|
||||
|
||||
let searchSignal = context.engine.messages.searchMessages(location: .publicForwards(messageId: messageId, datacenterId: Int(datacenterId)), query: "", state: nil)
|
||||
if case let .message(id) = subject {
|
||||
let searchSignal = context.engine.messages.searchMessages(location: .publicForwards(messageId: id, datacenterId: Int(datacenterId)), query: "", state: nil)
|
||||
|> map(Optional.init)
|
||||
|> afterNext { result in
|
||||
if let result = result {
|
||||
@ -250,6 +300,17 @@ public func messageStatsController(context: AccountContext, messageId: EngineMes
|
||||
}
|
||||
}
|
||||
messagesPromise.set(.single(nil) |> then(searchSignal))
|
||||
} else {
|
||||
messagesPromise.set(.single(nil))
|
||||
}
|
||||
|
||||
let iconNode: ASDisplayNode?
|
||||
if case let .story(peer, storyItem) = subject {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
iconNode = StoryIconNode(context: context, theme: presentationData.theme, peer: peer._asPeer(), storyItem: storyItem)
|
||||
} else {
|
||||
iconNode = nil
|
||||
}
|
||||
|
||||
let signal = combineLatest(context.sharedContext.presentationData, dataPromise.get(), messagesPromise.get(), longLoadingSignal)
|
||||
|> deliverOnMainQueue
|
||||
@ -264,14 +325,22 @@ public func messageStatsController(context: AccountContext, messageId: EngineMes
|
||||
}
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Stats_MessageTitle), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let title: String
|
||||
switch subject {
|
||||
case .message:
|
||||
title = presentationData.strings.Stats_MessageTitle
|
||||
case .story:
|
||||
title = presentationData.strings.Stats_StoryTitle
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: iconNode.flatMap { ItemListNavigationButton(content: .node($0), style: .regular, enabled: true, action: { }) }, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: messageStatsControllerEntries(data: data, messages: search?.0, presentationData: presentationData), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|> afterDisposed {
|
||||
actionsDisposable.dispose()
|
||||
let _ = statsContext.state
|
||||
let _ = anyStatsContext
|
||||
}
|
||||
|
||||
let controller = ItemListController(context: context, state: signal)
|
||||
@ -282,6 +351,12 @@ public func messageStatsController(context: AccountContext, messageId: EngineMes
|
||||
}
|
||||
})
|
||||
}
|
||||
// controller.visibleBottomContentOffsetChanged = { offset in
|
||||
// let state = stateValue.with { $0 }
|
||||
// if case let .known(value) = offset, value < 100.0, case .boosts = state.section, state.boostersExpanded {
|
||||
// boostsContext.loadMore()
|
||||
// }
|
||||
// }
|
||||
controller.didDisappear = { [weak controller] _ in
|
||||
controller?.clearItemNodesHighlight(animated: true)
|
||||
}
|
||||
|
@ -10,12 +10,12 @@ import PresentationDataUtils
|
||||
|
||||
class MessageStatsOverviewItem: ListViewItem, ItemListItem {
|
||||
let presentationData: ItemListPresentationData
|
||||
let stats: MessageStats
|
||||
let stats: PostStats
|
||||
let publicShares: Int32?
|
||||
let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
|
||||
init(presentationData: ItemListPresentationData, stats: MessageStats, publicShares: Int32?, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
init(presentationData: ItemListPresentationData, stats: PostStats, publicShares: Int32?, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
self.presentationData = presentationData
|
||||
self.stats = stats
|
||||
self.publicShares = publicShares
|
||||
|
@ -2,6 +2,7 @@ import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import ComponentFlow
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
@ -11,23 +12,28 @@ import TelegramStringFormatting
|
||||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import PhotoResources
|
||||
import AvatarStoryIndicatorComponent
|
||||
|
||||
public class StatsMessageItem: ListViewItem, ItemListItem {
|
||||
let context: AccountContext
|
||||
let presentationData: ItemListPresentationData
|
||||
let message: Message
|
||||
let peer: Peer
|
||||
let item: StatsPostItem
|
||||
let views: Int32
|
||||
let reactions: Int32
|
||||
let forwards: Int32
|
||||
public let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
let action: (() -> Void)?
|
||||
let contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?
|
||||
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, message: Message, views: Int32, forwards: Int32, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||
init(context: AccountContext, presentationData: ItemListPresentationData, peer: Peer, item: StatsPostItem, views: Int32, reactions: Int32, forwards: Int32, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)?, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)?) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.message = message
|
||||
self.peer = peer
|
||||
self.item = item
|
||||
self.views = views
|
||||
self.reactions = reactions
|
||||
self.forwards = forwards
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
@ -79,7 +85,7 @@ public class StatsMessageItem: ListViewItem, ItemListItem {
|
||||
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
|
||||
public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
@ -96,9 +102,14 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private var nonExtractedRect: CGRect?
|
||||
|
||||
let contentImageNode: TransformImageNode
|
||||
var storyIndicator: ComponentView<Empty>?
|
||||
let titleNode: TextNode
|
||||
let labelNode: TextNode
|
||||
let viewsNode: TextNode
|
||||
|
||||
let reactionsIconNode: ASImageNode
|
||||
let reactionsNode: TextNode
|
||||
let forwardsIconNode: ASImageNode
|
||||
let forwardsNode: TextNode
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
@ -152,6 +163,15 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.forwardsNode = TextNode()
|
||||
self.forwardsNode.isUserInteractionEnabled = false
|
||||
|
||||
self.forwardsIconNode = ASImageNode()
|
||||
self.forwardsIconNode.displaysAsynchronously = false
|
||||
|
||||
self.reactionsNode = TextNode()
|
||||
self.reactionsNode.isUserInteractionEnabled = false
|
||||
|
||||
self.reactionsIconNode = ASImageNode()
|
||||
self.reactionsIconNode.displaysAsynchronously = false
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
@ -172,6 +192,9 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
self.offsetContainerNode.addSubnode(self.labelNode)
|
||||
self.countersContainerNode.addSubnode(self.viewsNode)
|
||||
self.countersContainerNode.addSubnode(self.forwardsNode)
|
||||
self.countersContainerNode.addSubnode(self.forwardsIconNode)
|
||||
self.countersContainerNode.addSubnode(self.reactionsNode)
|
||||
self.countersContainerNode.addSubnode(self.reactionsIconNode)
|
||||
self.containerNode.targetNodeForActivationProgress = self.contextSourceNode.contentNode
|
||||
|
||||
self.addSubnode(self.activateArea)
|
||||
@ -200,8 +223,8 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
transition.updateAlpha(node: strongSelf.countersContainerNode, alpha: isExtracted ? 0.0 : 1.0)
|
||||
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.countersContainerNode.layer, offset: CGPoint(x: isExtracted ? -24.0 : 0.0, y: 0.0))
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.offsetContainerNode.layer, offset: CGPoint(x: isExtracted ? 12.0 : 0.0, y: 0.0))
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.countersContainerNode.layer, offset: CGPoint(x: isExtracted ? -16.0 : 0.0, y: 0.0))
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.offsetContainerNode.layer, offset: CGPoint(x: isExtracted ? 16.0 : 0.0, y: 0.0))
|
||||
|
||||
transition.updateAlpha(node: strongSelf.extractedBackgroundImageNode, alpha: isExtracted ? 1.0 : 0.0, completion: { _ in
|
||||
if !isExtracted {
|
||||
@ -215,6 +238,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||
let makeViewsLayout = TextNode.asyncLayout(self.viewsNode)
|
||||
let makeReactionsLayout = TextNode.asyncLayout(self.reactionsNode)
|
||||
let makeForwardsLayout = TextNode.asyncLayout(self.forwardsNode)
|
||||
|
||||
let currentItem = self.item
|
||||
@ -236,17 +260,23 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let leftInset = 16.0 + params.leftInset
|
||||
let rightInset = 16.0 + params.rightInset
|
||||
var totalLeftInset = leftInset
|
||||
let additionalRightInset: CGFloat = 128.0
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let titleFont = Font.semibold(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let labelFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
|
||||
let presentationData = item.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(item.message), strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId)
|
||||
var text = !item.message.text.isEmpty ? item.message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0.string
|
||||
text = foldLineBreaks(text)
|
||||
|
||||
var text: String
|
||||
var contentImageMedia: Media?
|
||||
for media in item.message.media {
|
||||
let timestamp: Int32
|
||||
|
||||
switch item.item {
|
||||
case let .message(message):
|
||||
let contentKind: MessageContentKind
|
||||
contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId)
|
||||
text = !message.text.isEmpty ? message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0.string
|
||||
|
||||
for media in message.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
contentImageMedia = image
|
||||
break
|
||||
@ -267,36 +297,63 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
timestamp = message.timestamp
|
||||
case let .story(story):
|
||||
text = item.presentationData.strings.Message_Story
|
||||
timestamp = story.timestamp
|
||||
if let image = story.media._asMedia() as? TelegramMediaImage {
|
||||
contentImageMedia = image
|
||||
break
|
||||
} else if let file = story.media._asMedia() as? TelegramMediaFile {
|
||||
contentImageMedia = file
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
text = foldLineBreaks(text)
|
||||
|
||||
if let _ = contentImageMedia {
|
||||
totalLeftInset += 48.0
|
||||
totalLeftInset += 46.0
|
||||
}
|
||||
|
||||
var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
if let contentImageMedia = contentImageMedia {
|
||||
if let currentContentImageMedia = currentContentImageMedia, contentImageMedia.isSemanticallyEqual(to: currentContentImageMedia) {
|
||||
} else {
|
||||
switch item.item {
|
||||
case let .message(message):
|
||||
if let image = contentImageMedia as? TelegramMediaImage {
|
||||
updateImageSignal = mediaGridMessagePhoto(account: item.context.account, userLocation: .peer(item.message.id.peerId), photoReference: .message(message: MessageReference(item.message), media: image))
|
||||
updateImageSignal = mediaGridMessagePhoto(account: item.context.account, userLocation: .peer(message.id.peerId), photoReference: .message(message: MessageReference(message), media: image))
|
||||
} else if let file = contentImageMedia as? TelegramMediaFile {
|
||||
updateImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(item.message.id.peerId), videoReference: .message(message: MessageReference(item.message), media: file), autoFetchFullSizeThumbnail: true)
|
||||
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):
|
||||
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))
|
||||
} else if let file = contentImageMedia as? TelegramMediaFile {
|
||||
updateImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(item.peer.id), videoReference: .story(peer: peerReference, id: story.id, media: file), autoFetchFullSizeThumbnail: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let labelFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
|
||||
let label = stringForMediumDate(timestamp: item.message.timestamp, strings: item.presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
|
||||
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: label, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (viewsLayout, viewsApply) = makeViewsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stats_MessageViews(item.views), font: labelFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (forwardsLayout, forwardsApply) = makeForwardsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stats_MessageForwards(item.forwards), font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
let reactions = item.reactions > 0 ? compactNumericCountString(Int(item.reactions), decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator) : ""
|
||||
let (reactionsLayout, reactionsApply) = makeReactionsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: reactions, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let verticalInset: CGFloat = 11.0
|
||||
let forwards = item.forwards > 0 ? compactNumericCountString(Int(item.forwards), decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator) : ""
|
||||
let (forwardsLayout, forwardsApply) = makeForwardsLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: forwards, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 128.0, height: CGFloat.greatestFiniteMagnitude), alignment: .right, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let additionalRightInset = max(viewsLayout.size.width, reactionsLayout.size.width + forwardsLayout.size.width + 36.0) + 8.0
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let label = stringForMediumDate(timestamp: timestamp, strings: item.presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: label, font: labelFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - totalLeftInset - rightInset - additionalRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let verticalInset: CGFloat = 10.0
|
||||
let titleSpacing: CGFloat = 3.0
|
||||
|
||||
let height: CGFloat = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + labelLayout.size.height
|
||||
@ -318,8 +375,14 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
return (ListViewItemNodeLayout(contentSize: contentSize, insets: insets), { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let themeUpdated = strongSelf.item?.presentationData.theme !== item.presentationData.theme
|
||||
strongSelf.item = item
|
||||
|
||||
if themeUpdated {
|
||||
strongSelf.forwardsIconNode.image = PresentationResourcesItemList.statsForwardsIcon(item.presentationData.theme)
|
||||
strongSelf.reactionsIconNode.image = PresentationResourcesItemList.statsReactionsIcon(item.presentationData.theme)
|
||||
}
|
||||
|
||||
let nonExtractedRect = CGRect(origin: CGPoint(), size: CGSize(width: layout.contentSize.width - 16.0, height: layout.contentSize.height))
|
||||
let extractedRect = CGRect(origin: CGPoint(), size: layout.contentSize).insetBy(dx: 16.0 + params.leftInset, dy: 0.0)
|
||||
strongSelf.extractedRect = extractedRect
|
||||
@ -357,13 +420,21 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
dimensions = contentImageMedia.dimensions?.cgSize
|
||||
}
|
||||
|
||||
let contentImageSize = CGSize(width: 40.0, height: 40.0)
|
||||
|
||||
var contentImageSize = CGSize(width: 40.0, height: 40.0)
|
||||
var contentImageInset = leftInset - 6.0
|
||||
if let dimensions = dimensions {
|
||||
let makeImageLayout = strongSelf.contentImageNode.asyncLayout()
|
||||
let imageSize = contentImageSize
|
||||
|
||||
let applyImageLayout = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: 4.0), imageSize: dimensions.aspectFilled(imageSize), boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
let cornerRadius: CGFloat
|
||||
if case .story = item.item {
|
||||
contentImageInset += 3.0
|
||||
contentImageSize = CGSize(width: 34.0, height: 34.0)
|
||||
cornerRadius = contentImageSize.width / 2.0
|
||||
} else {
|
||||
cornerRadius = 6.0
|
||||
}
|
||||
|
||||
let applyImageLayout = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: cornerRadius), imageSize: dimensions.aspectFilled(contentImageSize), boundingSize: contentImageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
applyImageLayout()
|
||||
|
||||
if let updateImageSignal = updateImageSignal {
|
||||
@ -384,6 +455,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let _ = labelApply()
|
||||
let _ = viewsApply()
|
||||
let _ = forwardsApply()
|
||||
let _ = reactionsApply()
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
@ -427,7 +499,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let bottomStripeInset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset
|
||||
bottomStripeInset = totalLeftInset
|
||||
strongSelf.bottomStripeNode.isHidden = false
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
@ -443,22 +515,106 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
||||
}
|
||||
|
||||
let contentImageFrame = CGRect(origin: CGPoint(x: leftInset, y: floorToScreenPixels((height - contentImageSize.height) / 2.0)), size: contentImageSize)
|
||||
let contentImageFrame = CGRect(origin: CGPoint(x: contentImageInset, y: floorToScreenPixels((height - contentImageSize.height) / 2.0)), size: contentImageSize)
|
||||
strongSelf.contentImageNode.frame = contentImageFrame
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: 11.0), size: titleLayout.size)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: 9.0), size: titleLayout.size)
|
||||
strongSelf.titleNode.frame = titleFrame
|
||||
|
||||
let labelFrame = CGRect(origin: CGPoint(x: totalLeftInset, y: titleFrame.maxY + titleSpacing), size: labelLayout.size)
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
|
||||
let viewsFrame = CGRect(origin: CGPoint(x: params.width - rightInset - viewsLayout.size.width, y: 15.0), size: viewsLayout.size)
|
||||
let viewsFrame = CGRect(origin: CGPoint(x: params.width - rightInset - viewsLayout.size.width, y: 13.0), size: viewsLayout.size)
|
||||
strongSelf.viewsNode.frame = viewsFrame
|
||||
|
||||
let forwardsFrame = CGRect(origin: CGPoint(x: params.width - rightInset - forwardsLayout.size.width, y: titleFrame.maxY + titleSpacing), size: forwardsLayout.size)
|
||||
let iconSpacing: CGFloat = 3.0 - UIScreenPixel
|
||||
|
||||
var rightContentInset: CGFloat = rightInset
|
||||
if forwardsLayout.size.width > 0.0 {
|
||||
strongSelf.forwardsIconNode.isHidden = false
|
||||
strongSelf.forwardsNode.isHidden = false
|
||||
|
||||
let forwardsFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - forwardsLayout.size.width, y: titleFrame.maxY + titleSpacing), size: forwardsLayout.size)
|
||||
strongSelf.forwardsNode.frame = forwardsFrame
|
||||
|
||||
if let icon = strongSelf.forwardsIconNode.image {
|
||||
let forwardsIconFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - forwardsLayout.size.width - icon.size.width - iconSpacing, y: titleFrame.maxY + titleSpacing - 2.0 + UIScreenPixel), size: icon.size)
|
||||
strongSelf.forwardsIconNode.frame = forwardsIconFrame
|
||||
|
||||
rightContentInset += forwardsIconFrame.width + forwardsFrame.width + iconSpacing
|
||||
}
|
||||
rightContentInset += 10.0
|
||||
} else {
|
||||
strongSelf.forwardsIconNode.isHidden = true
|
||||
strongSelf.forwardsNode.isHidden = true
|
||||
}
|
||||
|
||||
if reactionsLayout.size.width > 0.0 {
|
||||
strongSelf.reactionsIconNode.isHidden = false
|
||||
strongSelf.reactionsNode.isHidden = false
|
||||
|
||||
let reactionsFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - reactionsLayout.size.width, y: titleFrame.maxY + titleSpacing), size: reactionsLayout.size)
|
||||
strongSelf.reactionsNode.frame = reactionsFrame
|
||||
|
||||
if let icon = strongSelf.reactionsIconNode.image {
|
||||
let reactionsIconFrame = CGRect(origin: CGPoint(x: params.width - rightContentInset - reactionsLayout.size.width - icon.size.width - iconSpacing, y: titleFrame.maxY + titleSpacing - 2.0 + UIScreenPixel), size: icon.size)
|
||||
strongSelf.reactionsIconNode.frame = reactionsIconFrame
|
||||
|
||||
rightContentInset += reactionsIconFrame.width + reactionsFrame.width + iconSpacing
|
||||
}
|
||||
} else {
|
||||
strongSelf.reactionsIconNode.isHidden = true
|
||||
strongSelf.reactionsNode.isHidden = true
|
||||
}
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: height + UIScreenPixel))
|
||||
|
||||
if case .story = item.item {
|
||||
let lineWidth: CGFloat = 1.5
|
||||
let imageSize = CGSize(width: contentImageFrame.width + 6.0, height: contentImageFrame.height + 6.0)
|
||||
let indicatorSize = CGSize(width: imageSize.width - lineWidth * 4.0, height: imageSize.height - lineWidth * 4.0)
|
||||
|
||||
let storyIndicator: ComponentView<Empty>
|
||||
let indicatorTransition: Transition = .immediate
|
||||
if let current = strongSelf.storyIndicator {
|
||||
storyIndicator = current
|
||||
} else {
|
||||
storyIndicator = ComponentView()
|
||||
strongSelf.storyIndicator = storyIndicator
|
||||
}
|
||||
let _ = storyIndicator.update(
|
||||
transition: indicatorTransition,
|
||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||
hasUnseen: true,
|
||||
hasUnseenCloseFriendsItems: false,
|
||||
colors: AvatarStoryIndicatorComponent.Colors(
|
||||
unseenColors: item.presentationData.theme.chatList.storyUnseenColors.array,
|
||||
unseenCloseFriendsColors: item.presentationData.theme.chatList.storyUnseenPrivateColors.array,
|
||||
seenColors: item.presentationData.theme.chatList.storySeenColors.array
|
||||
),
|
||||
activeLineWidth: lineWidth,
|
||||
inactiveLineWidth: lineWidth,
|
||||
counters: AvatarStoryIndicatorComponent.Counters(
|
||||
totalCount: 1,
|
||||
unseenCount: 1
|
||||
),
|
||||
progress: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: indicatorSize
|
||||
)
|
||||
if let storyIndicatorView = storyIndicator.view {
|
||||
if storyIndicatorView.superview == nil {
|
||||
strongSelf.offsetContainerNode.view.addSubview(storyIndicatorView)
|
||||
}
|
||||
indicatorTransition.setFrame(view: storyIndicatorView, frame: CGRect(origin: CGPoint(x: contentImageFrame.midX - indicatorSize.width / 2.0, y: contentImageFrame.midY - indicatorSize.height / 2.0), size: indicatorSize))
|
||||
}
|
||||
} else if let storyIndicator = strongSelf.storyIndicator {
|
||||
if let storyIndicatorView = storyIndicator.view {
|
||||
storyIndicatorView.removeFromSuperview()
|
||||
}
|
||||
strongSelf.storyIndicator = nil
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
106
submodules/StatisticsUI/Sources/StoryIconNode.swift
Normal file
106
submodules/StatisticsUI/Sources/StoryIconNode.swift
Normal file
@ -0,0 +1,106 @@
|
||||
import Foundation
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import ComponentFlow
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import PhotoResources
|
||||
import AvatarStoryIndicatorComponent
|
||||
import AccountContext
|
||||
import TelegramPresentationData
|
||||
|
||||
final class StoryIconNode: ASDisplayNode {
|
||||
private let imageNode = TransformImageNode()
|
||||
private let storyIndicator = ComponentView<Empty>()
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, peer: Peer, storyItem: EngineStoryItem) {
|
||||
self.imageNode.displaysAsynchronously = false
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.imageNode)
|
||||
|
||||
let imageSize = CGSize(width: 30.0, height: 30.0)
|
||||
let size = CGSize(width: 36.0, height: 36.0)
|
||||
let bounds = CGRect(origin: .zero, size: size)
|
||||
|
||||
self.imageNode.frame = bounds.insetBy(dx: 3.0, dy: 3.0)
|
||||
self.frame = bounds
|
||||
|
||||
let media: Media?
|
||||
switch storyItem.media {
|
||||
case let .image(image):
|
||||
media = image
|
||||
case let .file(file):
|
||||
media = file
|
||||
default:
|
||||
media = nil
|
||||
}
|
||||
|
||||
var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
var dimensions: CGSize?
|
||||
if let peerReference = PeerReference(peer), let media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
updateImageSignal = mediaGridMessagePhoto(account: context.account, userLocation: .peer(peer.id), photoReference: .story(peer: peerReference, id: storyItem.id, media: image))
|
||||
dimensions = largestRepresentationForPhoto(image)?.dimensions.cgSize
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
updateImageSignal = mediaGridMessageVideo(postbox: context.account.postbox, userLocation: .peer(peer.id), videoReference: .story(peer: peerReference, id: storyItem.id, media: file), autoFetchFullSizeThumbnail: true)
|
||||
dimensions = file.dimensions?.cgSize
|
||||
}
|
||||
}
|
||||
|
||||
if let updateImageSignal {
|
||||
self.imageNode.setSignal(updateImageSignal)
|
||||
}
|
||||
|
||||
if let dimensions {
|
||||
let cornerRadius = imageSize.width / 2.0
|
||||
let makeImageLayout = self.imageNode.asyncLayout()
|
||||
let applyImageLayout = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: cornerRadius), imageSize: dimensions.aspectFilled(imageSize), boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))
|
||||
applyImageLayout()
|
||||
}
|
||||
|
||||
let lineWidth: CGFloat = 1.5
|
||||
let indicatorSize = CGSize(width: size.width - lineWidth * 4.0, height: size.height - lineWidth * 4.0)
|
||||
|
||||
let _ = self.storyIndicator.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(AvatarStoryIndicatorComponent(
|
||||
hasUnseen: true,
|
||||
hasUnseenCloseFriendsItems: false,
|
||||
colors: AvatarStoryIndicatorComponent.Colors(
|
||||
unseenColors: theme.chatList.storyUnseenColors.array,
|
||||
unseenCloseFriendsColors: theme.chatList.storyUnseenPrivateColors.array,
|
||||
seenColors: theme.chatList.storySeenColors.array
|
||||
),
|
||||
activeLineWidth: lineWidth,
|
||||
inactiveLineWidth: lineWidth,
|
||||
counters: AvatarStoryIndicatorComponent.Counters(
|
||||
totalCount: 1,
|
||||
unseenCount: 1
|
||||
),
|
||||
progress: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: indicatorSize
|
||||
)
|
||||
if let storyIndicatorView = self.storyIndicator.view {
|
||||
storyIndicatorView.frame = CGRect(origin: CGPoint(x: bounds.midX - indicatorSize.width / 2.0, y: bounds.midY - indicatorSize.height / 2.0), size: indicatorSize)
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
if let storyIndicatorView = self.storyIndicator.view {
|
||||
if storyIndicatorView.superview == nil {
|
||||
self.view.addSubview(storyIndicatorView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
return CGSize(width: 36.0, height: 36.0)
|
||||
}
|
||||
}
|
@ -52,6 +52,14 @@ public struct ChannelStatsMessageInteractions: Equatable {
|
||||
public let messageId: MessageId
|
||||
public let views: Int32
|
||||
public let forwards: Int32
|
||||
public let reactions: Int32
|
||||
|
||||
public init(messageId: MessageId, views: Int32, forwards: Int32, reactions: Int32) {
|
||||
self.messageId = messageId
|
||||
self.views = views
|
||||
self.forwards = forwards
|
||||
self.reactions = reactions
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChannelStats: Equatable {
|
||||
@ -1143,7 +1151,7 @@ extension ChannelStatsMessageInteractions {
|
||||
init(apiMessageInteractionCounters: Api.MessageInteractionCounters, peerId: PeerId) {
|
||||
switch apiMessageInteractionCounters {
|
||||
case let .messageInteractionCounters(msgId, views, forwards):
|
||||
self = ChannelStatsMessageInteractions(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: msgId), views: views, forwards: forwards)
|
||||
self = ChannelStatsMessageInteractions(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: msgId), views: views, forwards: forwards, reactions: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,10 @@ public final class PresentationThemeGradientColors {
|
||||
return (self.topColor, self.bottomColor)
|
||||
}
|
||||
|
||||
public var array: [UIColor] {
|
||||
return [self.topColor, self.bottomColor]
|
||||
}
|
||||
|
||||
public func withUpdated(topColor: UIColor? = nil, bottomColor: UIColor? = nil) -> PresentationThemeGradientColors {
|
||||
return PresentationThemeGradientColors(topColor: topColor ?? self.topColor, bottomColor: bottomColor ?? self.bottomColor)
|
||||
}
|
||||
|
@ -72,6 +72,9 @@ public enum PresentationResourceKey: Int32 {
|
||||
case itemListTopicArrowIcon
|
||||
case itemListAddBoostsIcon
|
||||
|
||||
case statsReactionsIcon
|
||||
case statsForwardsIcon
|
||||
|
||||
case itemListVoiceCallIcon
|
||||
case itemListVideoCallIcon
|
||||
|
||||
|
@ -329,4 +329,16 @@ public struct PresentationResourcesItemList {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/TopicArrowIcon"), color: theme.list.itemSecondaryTextColor)
|
||||
})
|
||||
}
|
||||
|
||||
public static func statsReactionsIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.statsReactionsIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chart/Reactions"), color: theme.list.itemSecondaryTextColor)
|
||||
})
|
||||
}
|
||||
|
||||
public static func statsForwardsIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.statsForwardsIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chart/Forwards"), color: theme.list.itemSecondaryTextColor)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1123,7 +1123,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
||||
component: MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: durationString, font: Font.with(size: 21.0, design: .camera), textColor: controlsTintColor)),
|
||||
horizontalAlignment: .center,
|
||||
textShadowColor: UIColor(rgb: 0x000000, alpha: 0.2)
|
||||
textShadowColor: controlsTintColor == .black ? .clear : UIColor(rgb: 0x000000, alpha: 0.2)
|
||||
),
|
||||
availableSize: context.availableSize,
|
||||
transition: context.transition
|
||||
|
@ -31,6 +31,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||
"//submodules/TelegramUI/Components/Utils/RoundedRectWithTailPath",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/Components/BundleIconComponent",
|
||||
"//submodules/ChatMessageBackground",
|
||||
],
|
||||
visibility = [
|
||||
|
@ -561,6 +561,7 @@ private final class PeerInfoInteraction {
|
||||
let displayTopicsLimited: (TopicsLimitedReason) -> Void
|
||||
let openPeerMention: (String, ChatControllerInteractionNavigateToPeer) -> Void
|
||||
let openBotApp: (AttachMenuBot) -> Void
|
||||
let openEditing: () -> Void
|
||||
|
||||
init(
|
||||
openUsername: @escaping (String) -> Void,
|
||||
@ -614,7 +615,8 @@ private final class PeerInfoInteraction {
|
||||
toggleForumTopics: @escaping (Bool) -> Void,
|
||||
displayTopicsLimited: @escaping (TopicsLimitedReason) -> Void,
|
||||
openPeerMention: @escaping (String, ChatControllerInteractionNavigateToPeer) -> Void,
|
||||
openBotApp: @escaping (AttachMenuBot) -> Void
|
||||
openBotApp: @escaping (AttachMenuBot) -> Void,
|
||||
openEditing: @escaping () -> Void
|
||||
) {
|
||||
self.openUsername = openUsername
|
||||
self.openPhone = openPhone
|
||||
@ -668,6 +670,7 @@ private final class PeerInfoInteraction {
|
||||
self.displayTopicsLimited = displayTopicsLimited
|
||||
self.openPeerMention = openPeerMention
|
||||
self.openBotApp = openBotApp
|
||||
self.openEditing = openEditing
|
||||
}
|
||||
}
|
||||
|
||||
@ -1208,6 +1211,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
||||
let ItemAdmins = 6
|
||||
let ItemMembers = 7
|
||||
let ItemMemberRequests = 8
|
||||
let ItemEdit = 9
|
||||
|
||||
if let _ = data.threadData {
|
||||
let mainUsername: String
|
||||
@ -1358,6 +1362,10 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
||||
interaction.openParticipantsSection(.memberRequests)
|
||||
}))
|
||||
}
|
||||
|
||||
items[.peerMembers]!.append(PeerInfoScreenDisclosureItem(id: ItemEdit, label: .none, text: presentationData.strings.Channel_Info_Settings, icon: UIImage(bundleImageName: "Chat/Info/SettingsIcon"), action: {
|
||||
interaction.openEditing()
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2425,6 +2433,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
},
|
||||
openBotApp: { [weak self] bot in
|
||||
self?.openBotApp(bot)
|
||||
},
|
||||
openEditing: { [weak self] in
|
||||
self?.headerNode.navigationButtonContainer.performAction?(.edit, nil, nil)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"provides-namespace" : true
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Chart/Forwards.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chart/Forwards.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "arrowshape_18.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
148
submodules/TelegramUI/Images.xcassets/Chart/Forwards.imageset/arrowshape_18.pdf
vendored
Normal file
148
submodules/TelegramUI/Images.xcassets/Chart/Forwards.imageset/arrowshape_18.pdf
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 1.809143 2.532226 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
1.381874 3.080939 m
|
||||
1.812524 5.409000 3.194212 8.717773 7.569556 8.717773 c
|
||||
7.569556 9.917774 l
|
||||
7.569556 10.446452 l
|
||||
7.569556 10.480809 l
|
||||
7.569556 10.707834 l
|
||||
7.569556 11.144928 7.569556 11.363475 7.657061 11.467960 c
|
||||
7.733040 11.558682 7.847383 11.608219 7.965533 11.601600 c
|
||||
8.101606 11.593976 8.261045 11.444503 8.579921 11.145556 c
|
||||
8.745543 10.990285 l
|
||||
8.770609 10.966786 l
|
||||
13.102652 6.905496 l
|
||||
13.265036 6.753260 13.346226 6.677144 13.376384 6.588246 c
|
||||
13.402888 6.510118 13.402888 6.425430 13.376384 6.347302 c
|
||||
13.346226 6.258403 13.265034 6.182286 13.102651 6.030052 c
|
||||
8.770609 1.968762 l
|
||||
8.745543 1.945263 l
|
||||
8.579920 1.789990 l
|
||||
8.261045 1.491045 8.101606 1.341572 7.965533 1.333949 c
|
||||
7.847383 1.327330 7.733040 1.376866 7.657061 1.467588 c
|
||||
7.569556 1.572074 7.569556 1.790621 7.569556 2.227714 c
|
||||
7.569556 2.454739 l
|
||||
7.569556 2.489097 l
|
||||
7.569556 3.017775 l
|
||||
7.569556 4.217774 l
|
||||
7.144288 4.217774 6.744702 4.192091 6.369556 4.145205 c
|
||||
4.554104 3.918311 3.310977 3.194876 2.499113 2.482739 c
|
||||
2.362022 2.362489 2.237234 2.242566 2.124057 2.125404 c
|
||||
2.050126 2.048869 1.981147 1.973513 1.916941 1.900021 c
|
||||
1.888999 1.868037 1.861959 1.836406 1.835807 1.805183 c
|
||||
1.802983 1.765995 1.771556 1.727451 1.741497 1.689663 c
|
||||
1.527425 1.420543 1.420391 1.285985 1.360707 1.277870 c
|
||||
1.306377 1.270482 1.259393 1.288921 1.224590 1.331290 c
|
||||
1.186357 1.377833 1.198391 1.535853 1.222459 1.851893 c
|
||||
1.228173 1.926921 1.234867 2.005210 1.242695 2.086436 c
|
||||
1.243798 2.097883 1.244923 2.109387 1.246072 2.120950 c
|
||||
1.257281 2.233779 1.270675 2.352077 1.286657 2.475003 c
|
||||
1.311591 2.666784 1.342823 2.869831 1.381874 3.080939 c
|
||||
h
|
||||
0.592504 2.179043 m
|
||||
0.592526 2.179102 0.593651 2.180346 0.595821 2.182594 c
|
||||
0.593566 2.180108 0.592482 2.178984 0.592504 2.179043 c
|
||||
h
|
||||
6.369556 2.934145 m
|
||||
6.369556 2.227714 l
|
||||
6.369556 2.216033 6.369552 2.204231 6.369547 2.192325 c
|
||||
6.369482 2.005756 6.369406 1.793388 6.385262 1.616055 c
|
||||
6.399108 1.461200 6.439729 1.052163 6.737077 0.697114 c
|
||||
7.056188 0.316081 7.536427 0.108026 8.032658 0.135827 c
|
||||
8.495048 0.161733 8.821238 0.411856 8.943680 0.507667 c
|
||||
9.083900 0.617389 9.238787 0.762698 9.374854 0.890351 c
|
||||
9.383532 0.898493 9.392133 0.906562 9.400649 0.914546 c
|
||||
13.923381 5.154607 l
|
||||
13.928342 5.159257 13.933517 5.164101 13.938882 5.169123 c
|
||||
14.005202 5.231203 14.100604 5.320504 14.180048 5.408552 c
|
||||
14.274767 5.513531 14.422819 5.696626 14.512774 5.961792 c
|
||||
14.624091 6.289929 14.624091 6.645618 14.512774 6.973756 c
|
||||
14.422819 7.238921 14.274767 7.422017 14.180048 7.526996 c
|
||||
14.100601 7.615047 14.005195 7.704352 13.938873 7.766432 c
|
||||
13.933511 7.771451 13.928339 7.776292 13.923381 7.780941 c
|
||||
9.400650 12.021002 l
|
||||
9.392125 12.028994 9.383514 12.037071 9.374827 12.045221 c
|
||||
9.238766 12.172870 9.083892 12.318167 8.943680 12.427882 c
|
||||
8.821238 12.523692 8.495049 12.773815 8.032658 12.799721 c
|
||||
7.536427 12.827522 7.056188 12.619467 6.737077 12.238434 c
|
||||
6.439729 11.883385 6.399108 11.474348 6.385262 11.319493 c
|
||||
6.369406 11.142159 6.369482 10.929791 6.369547 10.743222 c
|
||||
6.369552 10.731316 6.369556 10.719515 6.369556 10.707834 c
|
||||
6.369556 9.839663 l
|
||||
3.993418 9.518946 2.436784 8.247826 1.476669 6.720201 c
|
||||
0.412234 5.026595 0.112609 3.081284 0.025924 1.943016 c
|
||||
0.025268 1.934407 0.024604 1.925713 0.023934 1.916945 c
|
||||
0.013668 1.782581 0.002083 1.630936 0.000289 1.508040 c
|
||||
-0.000665 1.442641 -0.000246 1.333831 0.017544 1.213016 c
|
||||
0.030832 1.122771 0.076845 0.837997 0.297327 0.569592 c
|
||||
0.596399 0.205513 1.055517 0.025331 1.522386 0.088812 c
|
||||
1.882774 0.137815 2.117930 0.331811 2.178427 0.381719 c
|
||||
2.178911 0.382119 l
|
||||
2.270915 0.458017 2.344114 0.537148 2.388324 0.586662 c
|
||||
2.472725 0.681190 2.571892 0.805902 2.664181 0.921966 c
|
||||
2.680620 0.942637 l
|
||||
3.203021 1.599372 4.310469 2.634761 6.369556 2.934145 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
3854
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 18.000000 18.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000003944 00000 n
|
||||
0000003967 00000 n
|
||||
0000004140 00000 n
|
||||
0000004214 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
4273
|
||||
%%EOF
|
12
submodules/TelegramUI/Images.xcassets/Chart/Reactions.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chart/Reactions.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "heart_18.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
95
submodules/TelegramUI/Images.xcassets/Chart/Reactions.imageset/heart_18.pdf
vendored
Normal file
95
submodules/TelegramUI/Images.xcassets/Chart/Reactions.imageset/heart_18.pdf
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 2.024963 2.215471 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 8.477227 m
|
||||
0.000000 11.090064 1.837903 13.009529 4.216708 13.009529 c
|
||||
5.378695 13.009529 6.314748 12.504827 6.976930 11.731193 c
|
||||
7.642573 12.506644 8.575254 13.009529 9.739605 13.009529 c
|
||||
12.119733 13.009529 13.950001 11.088655 13.950001 8.477227 c
|
||||
13.950001 5.445473 11.442898 2.625515 7.886870 0.335408 c
|
||||
7.883046 0.332945 l
|
||||
7.883036 0.332960 l
|
||||
7.773217 0.263408 7.639669 0.186707 7.499969 0.125453 c
|
||||
7.373253 0.069893 7.182288 0.000000 6.975000 0.000000 c
|
||||
6.768435 0.000000 6.577350 0.071704 6.454765 0.125453 c
|
||||
6.317346 0.185706 6.184213 0.261022 6.074458 0.328291 c
|
||||
6.063049 0.335283 l
|
||||
6.063130 0.335408 l
|
||||
2.507103 2.625515 0.000000 5.445473 0.000000 8.477227 c
|
||||
h
|
||||
4.216708 11.809529 m
|
||||
2.568532 11.809529 1.200000 10.497311 1.200000 8.477227 c
|
||||
1.200000 6.107325 3.209978 3.601517 6.707050 1.348038 c
|
||||
6.790931 1.296850 6.870368 1.253510 6.936634 1.224454 c
|
||||
6.952608 1.217450 6.966116 1.212033 6.977225 1.207909 c
|
||||
6.988396 1.211988 7.002014 1.217401 7.018100 1.224454 c
|
||||
7.083025 1.252921 7.160221 1.295694 7.239110 1.345563 c
|
||||
10.738551 3.599682 12.750001 6.106457 12.750001 8.477227 c
|
||||
12.750001 10.498720 11.386456 11.809529 9.739605 11.809529 c
|
||||
8.743175 11.809529 7.985357 11.273088 7.501738 10.386451 c
|
||||
7.396244 10.193047 7.193245 10.073009 6.972942 10.073765 c
|
||||
6.752639 10.074521 6.550468 10.195948 6.446304 10.390072 c
|
||||
5.975964 11.266614 5.213501 11.809529 4.216708 11.809529 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
1521
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 18.000000 18.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000001611 00000 n
|
||||
0000001634 00000 n
|
||||
0000001807 00000 n
|
||||
0000001881 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
1940
|
||||
%%EOF
|
12
submodules/TelegramUI/Images.xcassets/Chat/Info/SettingsIcon.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Info/SettingsIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "settings_30.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
290
submodules/TelegramUI/Images.xcassets/Chat/Info/SettingsIcon.imageset/settings_30.pdf
vendored
Normal file
290
submodules/TelegramUI/Images.xcassets/Chat/Info/SettingsIcon.imageset/settings_30.pdf
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
1.000000 0.584314 0.000000 scn
|
||||
0.000000 18.799999 m
|
||||
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
|
||||
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
|
||||
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
|
||||
18.799999 30.000000 l
|
||||
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
|
||||
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
|
||||
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
|
||||
30.000000 11.200001 l
|
||||
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
|
||||
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
|
||||
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
|
||||
11.200000 0.000000 l
|
||||
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
|
||||
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
|
||||
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
|
||||
0.000000 18.799999 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 6.000000 9.000000 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
17.000078 10.000000 m
|
||||
17.552362 10.000000 18.000078 10.447716 18.000078 11.000000 c
|
||||
18.000078 11.552285 17.552362 12.000000 17.000078 12.000000 c
|
||||
1.000078 12.000000 l
|
||||
0.447794 12.000000 0.000078 11.552285 0.000078 11.000000 c
|
||||
0.000078 10.447716 0.447794 10.000000 1.000078 10.000000 c
|
||||
17.000078 10.000000 l
|
||||
h
|
||||
17.000000 0.000078 m
|
||||
17.552284 0.000078 18.000000 0.447793 18.000000 1.000078 c
|
||||
18.000000 1.552363 17.552284 2.000078 17.000000 2.000078 c
|
||||
1.000000 2.000078 l
|
||||
0.447716 2.000078 0.000000 1.552363 0.000000 1.000078 c
|
||||
0.000000 0.447793 0.447716 0.000078 1.000000 0.000078 c
|
||||
17.000000 0.000078 l
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 6.000000 16.000000 cm
|
||||
1.000000 0.584314 0.000000 scn
|
||||
8.000000 4.000000 m
|
||||
8.000000 1.790861 6.209139 0.000000 4.000000 0.000000 c
|
||||
1.790861 0.000000 0.000000 1.790861 0.000000 4.000000 c
|
||||
0.000000 6.209139 1.790861 8.000000 4.000000 8.000000 c
|
||||
6.209139 8.000000 8.000000 6.209139 8.000000 4.000000 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
14.000000 20.000000 m
|
||||
14.000000 17.790861 12.209139 16.000000 10.000000 16.000000 c
|
||||
7.790861 16.000000 6.000000 17.790861 6.000000 20.000000 c
|
||||
6.000000 22.209139 7.790861 24.000000 10.000000 24.000000 c
|
||||
12.209139 24.000000 14.000000 22.209139 14.000000 20.000000 c
|
||||
h
|
||||
W*
|
||||
n
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 6.000000 16.000000 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
6.000000 4.000000 m
|
||||
6.000000 2.895431 5.104569 2.000000 4.000000 2.000000 c
|
||||
4.000000 -2.000000 l
|
||||
7.313708 -2.000000 10.000000 0.686292 10.000000 4.000000 c
|
||||
6.000000 4.000000 l
|
||||
h
|
||||
4.000000 2.000000 m
|
||||
2.895431 2.000000 2.000000 2.895431 2.000000 4.000000 c
|
||||
-2.000000 4.000000 l
|
||||
-2.000000 0.686292 0.686292 -2.000000 4.000000 -2.000000 c
|
||||
4.000000 2.000000 l
|
||||
h
|
||||
2.000000 4.000000 m
|
||||
2.000000 5.104569 2.895431 6.000000 4.000000 6.000000 c
|
||||
4.000000 10.000000 l
|
||||
0.686292 10.000000 -2.000000 7.313708 -2.000000 4.000000 c
|
||||
2.000000 4.000000 l
|
||||
h
|
||||
4.000000 6.000000 m
|
||||
5.104569 6.000000 6.000000 5.104569 6.000000 4.000000 c
|
||||
10.000000 4.000000 l
|
||||
10.000000 7.313708 7.313708 10.000000 4.000000 10.000000 c
|
||||
4.000000 6.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
Q
|
||||
q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 16.000000 6.000000 cm
|
||||
1.000000 0.584314 0.000000 scn
|
||||
8.000000 4.000000 m
|
||||
8.000000 1.790861 6.209139 0.000000 4.000000 0.000000 c
|
||||
1.790861 0.000000 0.000000 1.790861 0.000000 4.000000 c
|
||||
0.000000 6.209139 1.790861 8.000000 4.000000 8.000000 c
|
||||
6.209139 8.000000 8.000000 6.209139 8.000000 4.000000 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
24.000000 10.000000 m
|
||||
24.000000 7.790861 22.209139 6.000000 20.000000 6.000000 c
|
||||
17.790861 6.000000 16.000000 7.790861 16.000000 10.000000 c
|
||||
16.000000 12.209139 17.790861 14.000000 20.000000 14.000000 c
|
||||
22.209139 14.000000 24.000000 12.209139 24.000000 10.000000 c
|
||||
h
|
||||
W*
|
||||
n
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 16.000000 6.000000 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
6.000000 4.000000 m
|
||||
6.000000 2.895431 5.104569 2.000000 4.000000 2.000000 c
|
||||
4.000000 -2.000000 l
|
||||
7.313708 -2.000000 10.000000 0.686292 10.000000 4.000000 c
|
||||
6.000000 4.000000 l
|
||||
h
|
||||
4.000000 2.000000 m
|
||||
2.895431 2.000000 2.000000 2.895431 2.000000 4.000000 c
|
||||
-2.000000 4.000000 l
|
||||
-2.000000 0.686292 0.686292 -2.000000 4.000000 -2.000000 c
|
||||
4.000000 2.000000 l
|
||||
h
|
||||
2.000000 4.000000 m
|
||||
2.000000 5.104569 2.895431 6.000000 4.000000 6.000000 c
|
||||
4.000000 10.000000 l
|
||||
0.686292 10.000000 -2.000000 7.313708 -2.000000 4.000000 c
|
||||
2.000000 4.000000 l
|
||||
h
|
||||
4.000000 6.000000 m
|
||||
5.104569 6.000000 6.000000 5.104569 6.000000 4.000000 c
|
||||
10.000000 4.000000 l
|
||||
10.000000 7.313708 7.313708 10.000000 4.000000 10.000000 c
|
||||
4.000000 6.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
4505
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /Type /XObject
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Subtype /Form
|
||||
/Resources << >>
|
||||
/BBox [ 0.000000 0.000000 30.000000 30.000000 ]
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 18.799999 m
|
||||
0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c
|
||||
1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c
|
||||
5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c
|
||||
18.799999 30.000000 l
|
||||
22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c
|
||||
27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c
|
||||
30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c
|
||||
30.000000 11.200001 l
|
||||
30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c
|
||||
28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c
|
||||
24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c
|
||||
11.200000 0.000000 l
|
||||
7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c
|
||||
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
|
||||
0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c
|
||||
0.000000 18.799999 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
944
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /XObject << /X1 1 0 R >>
|
||||
/ExtGState << /E1 << /SMask << /Type /Mask
|
||||
/G 3 0 R
|
||||
/S /Alpha
|
||||
>>
|
||||
/Type /ExtGState
|
||||
>> >>
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Length 7 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
/E1 gs
|
||||
/X1 Do
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
46
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
|
||||
/Resources 5 0 R
|
||||
/Contents 6 0 R
|
||||
/Parent 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<< /Kids [ 8 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<< /Pages 9 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000004763 00000 n
|
||||
0000004786 00000 n
|
||||
0000005978 00000 n
|
||||
0000006000 00000 n
|
||||
0000006298 00000 n
|
||||
0000006400 00000 n
|
||||
0000006421 00000 n
|
||||
0000006594 00000 n
|
||||
0000006668 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
6728
|
||||
%%EOF
|
12
submodules/TelegramUI/Images.xcassets/Chat/Message/Subscriber.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Message/Subscriber.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "person_6.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
78
submodules/TelegramUI/Images.xcassets/Chat/Message/Subscriber.imageset/person_6.pdf
vendored
Normal file
78
submodules/TelegramUI/Images.xcassets/Chat/Message/Subscriber.imageset/person_6.pdf
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.018066 0.500000 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
2.980786 3.972965 m
|
||||
3.816679 3.972965 4.494304 4.650590 4.494304 5.486483 c
|
||||
4.494304 6.322375 3.816679 7.000000 2.980786 7.000000 c
|
||||
2.144894 7.000000 1.467269 6.322375 1.467269 5.486483 c
|
||||
1.467269 4.650590 2.144894 3.972965 2.980786 3.972965 c
|
||||
h
|
||||
5.734580 1.858224 m
|
||||
5.255256 2.484169 4.423840 3.027039 2.981694 3.027039 c
|
||||
1.539547 3.027039 0.708129 2.484169 0.228806 1.858224 c
|
||||
-0.442749 0.981247 0.471706 0.000003 1.576275 0.000003 c
|
||||
4.387107 0.000003 l
|
||||
5.491676 0.000003 6.406134 0.981247 5.734580 1.858224 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
639
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 6.000000 8.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000000729 00000 n
|
||||
0000000751 00000 n
|
||||
0000000922 00000 n
|
||||
0000000996 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
1055
|
||||
%%EOF
|
15
submodules/TelegramUI/Images.xcassets/Chat/Message/TranscriptionLocked.imageset/Contents.json
vendored
Normal file
15
submodules/TelegramUI/Images.xcassets/Chat/Message/TranscriptionLocked.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "lockedaudiototext.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 3.834961 10.247070 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
14.784782 9.993996 m
|
||||
14.685381 10.249602 14.439255 10.417969 14.165000 10.417969 c
|
||||
13.890745 10.417969 13.644619 10.249602 13.545217 9.993996 c
|
||||
10.045217 0.993996 l
|
||||
9.912102 0.651699 10.081676 0.266301 10.423973 0.133185 c
|
||||
10.766270 0.000071 11.151668 0.169645 11.284783 0.511942 c
|
||||
12.286572 3.087969 l
|
||||
15.680867 3.087969 l
|
||||
15.758190 3.902153 16.114431 4.635052 16.652981 5.190056 c
|
||||
16.534782 5.493996 l
|
||||
14.784782 9.993996 l
|
||||
h
|
||||
15.526207 4.417969 m
|
||||
12.803794 4.417969 l
|
||||
14.165000 7.918214 l
|
||||
15.295218 5.011942 l
|
||||
15.526207 4.417969 l
|
||||
h
|
||||
3.694774 8.723195 m
|
||||
3.954473 8.982893 4.375527 8.982893 4.635226 8.723195 c
|
||||
8.135226 5.223195 l
|
||||
8.394924 4.963496 8.394924 4.542441 8.135226 4.282743 c
|
||||
4.635226 0.782743 l
|
||||
4.375527 0.523045 3.954473 0.523045 3.694774 0.782743 c
|
||||
3.435075 1.042441 3.435075 1.463496 3.694774 1.723194 c
|
||||
6.059548 4.087969 l
|
||||
0.665000 4.087969 l
|
||||
0.297731 4.087969 0.000000 4.385699 0.000000 4.752969 c
|
||||
0.000000 5.120238 0.297731 5.417969 0.665000 5.417969 c
|
||||
6.059548 5.417969 l
|
||||
3.694774 7.782743 l
|
||||
3.435075 8.042441 3.435075 8.463496 3.694774 8.723195 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 21.000000 7.669922 cm
|
||||
0.898039 0.949020 1.000000 scn
|
||||
3.335000 1.330078 m
|
||||
3.335000 0.962809 3.632731 0.665078 4.000000 0.665078 c
|
||||
4.367270 0.665078 4.665000 0.962809 4.665000 1.330078 c
|
||||
3.335000 1.330078 l
|
||||
h
|
||||
-0.665000 1.330078 m
|
||||
-0.665000 0.962809 -0.367269 0.665078 0.000000 0.665078 c
|
||||
0.367269 0.665078 0.665000 0.962809 0.665000 1.330078 c
|
||||
-0.665000 1.330078 l
|
||||
h
|
||||
3.335000 5.330078 m
|
||||
3.335000 1.330078 l
|
||||
4.665000 1.330078 l
|
||||
4.665000 5.330078 l
|
||||
3.335000 5.330078 l
|
||||
h
|
||||
0.665000 1.330078 m
|
||||
0.665000 5.330078 l
|
||||
-0.665000 5.330078 l
|
||||
-0.665000 1.330078 l
|
||||
0.665000 1.330078 l
|
||||
h
|
||||
2.000000 6.665078 m
|
||||
2.737300 6.665078 3.335000 6.067378 3.335000 5.330078 c
|
||||
4.665000 5.330078 l
|
||||
4.665000 6.801917 3.471839 7.995078 2.000000 7.995078 c
|
||||
2.000000 6.665078 l
|
||||
h
|
||||
2.000000 7.995078 m
|
||||
0.528161 7.995078 -0.665000 6.801917 -0.665000 5.330078 c
|
||||
0.665000 5.330078 l
|
||||
0.665000 6.067378 1.262700 6.665078 2.000000 6.665078 c
|
||||
2.000000 7.995078 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 21.000000 7.669922 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
3.335000 1.330078 m
|
||||
3.335000 0.962809 3.632731 0.665078 4.000000 0.665078 c
|
||||
4.367270 0.665078 4.665000 0.962809 4.665000 1.330078 c
|
||||
3.335000 1.330078 l
|
||||
h
|
||||
-0.665000 1.330078 m
|
||||
-0.665000 0.962809 -0.367269 0.665078 0.000000 0.665078 c
|
||||
0.367269 0.665078 0.665000 0.962809 0.665000 1.330078 c
|
||||
-0.665000 1.330078 l
|
||||
h
|
||||
3.335000 5.330078 m
|
||||
3.335000 1.330078 l
|
||||
4.665000 1.330078 l
|
||||
4.665000 5.330078 l
|
||||
3.335000 5.330078 l
|
||||
h
|
||||
0.665000 1.330078 m
|
||||
0.665000 5.330078 l
|
||||
-0.665000 5.330078 l
|
||||
-0.665000 1.330078 l
|
||||
0.665000 1.330078 l
|
||||
h
|
||||
2.000000 6.665078 m
|
||||
2.737300 6.665078 3.335000 6.067378 3.335000 5.330078 c
|
||||
4.665000 5.330078 l
|
||||
4.665000 6.801917 3.471839 7.995078 2.000000 7.995078 c
|
||||
2.000000 6.665078 l
|
||||
h
|
||||
2.000000 7.995078 m
|
||||
0.528161 7.995078 -0.665000 6.801917 -0.665000 5.330078 c
|
||||
0.665000 5.330078 l
|
||||
0.665000 6.067378 1.262700 6.665078 2.000000 6.665078 c
|
||||
2.000000 7.995078 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 19.500000 6.000000 cm
|
||||
0.000000 0.000000 0.000000 scn
|
||||
0.000000 3.000000 m
|
||||
0.000000 3.931883 0.000000 4.397825 0.152241 4.765367 c
|
||||
0.355229 5.255423 0.744577 5.644771 1.234633 5.847759 c
|
||||
1.602175 6.000000 2.068117 6.000000 3.000000 6.000000 c
|
||||
4.000000 6.000000 l
|
||||
4.931883 6.000000 5.397825 6.000000 5.765367 5.847759 c
|
||||
6.255423 5.644771 6.644771 5.255423 6.847759 4.765367 c
|
||||
7.000000 4.397825 7.000000 3.931883 7.000000 3.000000 c
|
||||
7.000000 3.000000 l
|
||||
7.000000 2.068117 7.000000 1.602175 6.847759 1.234633 c
|
||||
6.644771 0.744577 6.255423 0.355228 5.765367 0.152241 c
|
||||
5.397825 0.000000 4.931883 0.000000 4.000000 0.000000 c
|
||||
3.000000 0.000000 l
|
||||
2.068117 0.000000 1.602175 0.000000 1.234633 0.152241 c
|
||||
0.744577 0.355228 0.355229 0.744577 0.152241 1.234633 c
|
||||
0.000000 1.602175 0.000000 2.068117 0.000000 3.000000 c
|
||||
0.000000 3.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
3999
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000004089 00000 n
|
||||
0000004112 00000 n
|
||||
0000004285 00000 n
|
||||
0000004359 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
4418
|
||||
%%EOF
|
@ -3694,7 +3694,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self, let (id, statsDatacenterId) = messageIdAndStatsDatacenterId, let statsDatacenterId = statsDatacenterId else {
|
||||
return
|
||||
}
|
||||
strongSelf.push(messageStatsController(context: context, messageId: id, statsDatacenterId: statsDatacenterId))
|
||||
strongSelf.push(messageStatsController(context: context, subject: .message(id: id), statsDatacenterId: statsDatacenterId))
|
||||
})
|
||||
}, delay: true)
|
||||
}, editMessageMedia: { [weak self] messageId, draw in
|
||||
|
Loading…
x
Reference in New Issue
Block a user