mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-29 11:25:38 +00:00
Update channel statistics
This commit is contained in:
parent
0b9a47aec0
commit
89738dbf28
@ -5363,3 +5363,6 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Stats.FollowersTitle" = "FOLLOWERS";
|
||||
"Stats.NotificationsTitle" = "NOTIFICATIONS";
|
||||
"Stats.InteractionsTitle" = "INTERACTIONS";
|
||||
"Stats.ViewsBySourceTitle" = "VIEWS BY SOURCE";
|
||||
"Stats.FollowersBySourceTitle" = "FOLLOWERS BY SOURCE";
|
||||
"Stats.LanguagesTitle" = "LANGUAGES";
|
||||
|
||||
@ -39,12 +39,18 @@ class ChartStackSection: UIView, ColorModeContainer {
|
||||
sectionContainerView.addSubview(rangeView)
|
||||
sectionContainerView.addSubview(visibilityView)
|
||||
sectionContainerView.addSubview(titleLabel)
|
||||
sectionContainerView.addSubview(backButton)
|
||||
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 14, weight: .bold)
|
||||
titleLabel.textAlignment = .center
|
||||
visibilityView.clipsToBounds = true
|
||||
backButton.isExclusiveTouch = true
|
||||
|
||||
|
||||
backButton.addTarget(self, action: #selector(self.didTapBackButton), for: .touchUpInside)
|
||||
backButton.setTitle("Zoom Out", for: .normal)
|
||||
backButton.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .regular)
|
||||
backButton.setTitleColor(UIColor(rgb: 0x007ee5), for: .normal)
|
||||
|
||||
backButton.setVisible(false, animated: false)
|
||||
}
|
||||
|
||||
@ -95,7 +101,7 @@ class ChartStackSection: UIView, ColorModeContainer {
|
||||
self.titleLabel.setTextColor(colorMode.chartTitleColor, animated: animated && titleLabel.isVisibleInWindow)
|
||||
}
|
||||
|
||||
@IBAction func didTapBackButton() {
|
||||
@objc private func didTapBackButton() {
|
||||
controller.didTapZoomOut()
|
||||
}
|
||||
|
||||
@ -127,11 +133,12 @@ class ChartStackSection: UIView, ColorModeContainer {
|
||||
super.layoutSubviews()
|
||||
|
||||
let bounds = self.bounds
|
||||
self.titleLabel.frame = CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: CGSize(width: bounds.width, height: 48.0))
|
||||
self.sectionContainerView.frame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: 350.0))
|
||||
self.titleLabel.frame = CGRect(origin: CGPoint(x: backButton.alpha > 0.0 ? 36.0 : 0.0, y: 5.0), size: CGSize(width: bounds.width, height: 28.0))
|
||||
self.sectionContainerView.frame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: 400.0))
|
||||
self.chartView.frame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: 250.0))
|
||||
self.rangeView.frame = CGRect(origin: CGPoint(x: 0.0, y: 250.0), size: CGSize(width: bounds.width, height: 48.0))
|
||||
self.visibilityView.frame = CGRect(origin: CGPoint(x: 0.0, y: 308.0), size: CGSize(width: bounds.width, height: 122.0))
|
||||
self.rangeView.frame = CGRect(origin: CGPoint(x: 0.0, y: 250.0), size: CGSize(width: bounds.width, height: 42.0))
|
||||
self.visibilityView.frame = CGRect(origin: CGPoint(x: 0.0, y: 308.0), size: CGSize(width: bounds.width, height: 222.0))
|
||||
self.backButton.frame = CGRect(x: 0.0, y: 0.0, width: 96.0, height: 38.0)
|
||||
}
|
||||
|
||||
func setup(controller: BaseChartController, title: String) {
|
||||
@ -164,6 +171,7 @@ class ChartStackSection: UIView, ColorModeContainer {
|
||||
self.titleLabel.setText(title, animated: animated)
|
||||
}
|
||||
controller.setBackButtonVisibilityClosure = { [unowned self] visible, animated in
|
||||
self.setNeedsLayout()
|
||||
self.setBackButtonVisible(visible, animated: animated)
|
||||
}
|
||||
controller.refreshChartToolsClosure = { [unowned self] animated in
|
||||
@ -193,9 +201,9 @@ class ChartStackSection: UIView, ColorModeContainer {
|
||||
controller.initializeChart()
|
||||
updateToolViews(animated: false)
|
||||
|
||||
TimeInterval.animationDurationMultipler = 0.0001
|
||||
rangeView.setRange(0.75...1.0, animated: false)
|
||||
controller.updateChartRange(0.75...1.0)
|
||||
rangeView.setRange(0.8...1.0, animated: false)
|
||||
TimeInterval.animationDurationMultipler = 0.00001
|
||||
controller.updateChartRange(0.8...1.0, animated: false)
|
||||
TimeInterval.animationDurationMultipler = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,13 @@ import Display
|
||||
import AsyncDisplayKit
|
||||
import AppBundle
|
||||
|
||||
public enum ChartType {
|
||||
case lines
|
||||
case twoAxis
|
||||
case pie
|
||||
case bars
|
||||
}
|
||||
|
||||
public final class ChartNode: ASDisplayNode {
|
||||
private var chartView: ChartStackSection {
|
||||
return self.view as! ChartStackSection
|
||||
@ -23,21 +30,32 @@ public final class ChartNode: ASDisplayNode {
|
||||
self.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
}
|
||||
|
||||
@objc private func nop() {
|
||||
}
|
||||
|
||||
public func setup(_ data: String, bar: Bool = false) {
|
||||
var bar = bar
|
||||
if data.contains("bar") {
|
||||
bar = true
|
||||
}
|
||||
public func setup(_ data: String, type: ChartType, getDetailsData: @escaping (Date, (String?) -> Void) -> Void) {
|
||||
if let data = data.data(using: .utf8) {
|
||||
ChartsDataManager().readChart(data: data, extraCopiesCount: 0, sync: true, success: { [weak self] collection in
|
||||
let controller: BaseChartController
|
||||
if bar {
|
||||
controller = TwoAxisLinesChartController(chartsCollection: collection)
|
||||
} else {
|
||||
controller = GeneralLinesChartController(chartsCollection: collection)
|
||||
switch type {
|
||||
case .lines:
|
||||
controller = GeneralLinesChartController(chartsCollection: collection)
|
||||
controller.getDetailsData = { date, completion in
|
||||
getDetailsData(date, { detailsData in
|
||||
if let detailsData = detailsData, let data = detailsData.data(using: .utf8) {
|
||||
ChartsDataManager().readChart(data: data, extraCopiesCount: 0, sync: true, success: { [weak self] collection in
|
||||
completion(collection)
|
||||
}) { error in
|
||||
completion(nil)
|
||||
}
|
||||
} else {
|
||||
completion(nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
case .twoAxis:
|
||||
controller = TwoAxisLinesChartController(chartsCollection: collection)
|
||||
case .pie:
|
||||
controller = PercentPieChartController(chartsCollection: collection)
|
||||
case .bars:
|
||||
controller = StackedBarsChartController(chartsCollection: collection)
|
||||
}
|
||||
if let strongSelf = self {
|
||||
strongSelf.chartView.setup(controller: controller, title: "")
|
||||
|
||||
@ -13,6 +13,7 @@ import PresentationDataUtils
|
||||
import AccountContext
|
||||
import PresentationDataUtils
|
||||
import AppBundle
|
||||
import Charts
|
||||
|
||||
private final class StatsArguments {
|
||||
init() {
|
||||
@ -36,28 +37,28 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
case overview(PresentationTheme, ChannelStats)
|
||||
|
||||
case growthTitle(PresentationTheme, String)
|
||||
case growthGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case growthGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case followersTitle(PresentationTheme, String)
|
||||
case followersGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case followersGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case notificationsTitle(PresentationTheme, String)
|
||||
case notificationsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case notificationsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case viewsByHourTitle(PresentationTheme, String)
|
||||
case viewsByHourGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case viewsByHourGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case postInteractionsTitle(PresentationTheme, String)
|
||||
case postInteractionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case postInteractionsGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case viewsBySourceTitle(PresentationTheme, String)
|
||||
case viewsBySourceGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case viewsBySourceGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case followersBySourceTitle(PresentationTheme, String)
|
||||
case followersBySourceGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case followersBySourceGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
case languagesTitle(PresentationTheme, String)
|
||||
case languagesGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph)
|
||||
case languagesGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, ChannelStatsGraph, ChartType)
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
@ -143,8 +144,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .growthGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .growthGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .growthGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .growthGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -155,8 +156,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .followersGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .followersGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .followersGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .followersGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -167,8 +168,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .notificationsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .notificationsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .notificationsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .notificationsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -179,8 +180,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .viewsByHourGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .viewsByHourGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .viewsByHourGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .viewsByHourGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -191,8 +192,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .postInteractionsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .postInteractionsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .postInteractionsGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .postInteractionsGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -203,8 +204,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .viewsBySourceGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .viewsBySourceGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .viewsBySourceGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .viewsBySourceGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -215,8 +216,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .followersBySourceGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .followersBySourceGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .followersBySourceGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .followersBySourceGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -227,8 +228,8 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .languagesGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph):
|
||||
if case let .languagesGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph {
|
||||
case let .languagesGraph(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsGraph, lhsType):
|
||||
if case let .languagesGraph(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsGraph, rhsType) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsDateTimeFormat == rhsDateTimeFormat, lhsGraph == rhsGraph, lhsType == rhsType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -254,15 +255,22 @@ private enum StatsEntry: ItemListNodeEntry {
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .overview(theme, stats):
|
||||
return StatsOverviewItem(presentationData: presentationData, stats: stats, sectionId: self.section, style: .blocks)
|
||||
case let .growthGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .followersGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .notificationsGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .viewsByHourGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .postInteractionsGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .viewsBySourceGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .followersBySourceGraph(theme, strings, dateTimeFormat, graph),
|
||||
let .languagesGraph(theme, strings, dateTimeFormat, graph):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, sectionId: self.section, style: .blocks)
|
||||
case let .growthGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .followersGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .notificationsGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .viewsByHourGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .postInteractionsGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, sectionId: self.section, style: .blocks)
|
||||
case let .viewsBySourceGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, height: 160.0, sectionId: self.section, style: .blocks)
|
||||
case let .followersBySourceGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, height: 160.0, sectionId: self.section, style: .blocks)
|
||||
case let .languagesGraph(theme, strings, dateTimeFormat, graph, type):
|
||||
return StatsGraphItem(presentationData: presentationData, graph: graph, type: type, height: 100.0, sectionId: self.section, style: .blocks)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -275,16 +283,25 @@ private func statsControllerEntries(data: ChannelStats?, presentationData: Prese
|
||||
entries.append(.overview(presentationData.theme, data))
|
||||
|
||||
entries.append(.growthTitle(presentationData.theme, presentationData.strings.Stats_GrowthTitle))
|
||||
entries.append(.growthGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.growthGraph))
|
||||
entries.append(.growthGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.growthGraph, .lines))
|
||||
|
||||
entries.append(.followersTitle(presentationData.theme, presentationData.strings.Stats_FollowersTitle))
|
||||
entries.append(.followersGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.followersGraph))
|
||||
entries.append(.followersGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.followersGraph, .lines))
|
||||
|
||||
entries.append(.notificationsTitle(presentationData.theme, presentationData.strings.Stats_NotificationsTitle))
|
||||
entries.append(.notificationsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.muteGraph))
|
||||
entries.append(.notificationsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.muteGraph, .lines))
|
||||
|
||||
entries.append(.postInteractionsTitle(presentationData.theme, presentationData.strings.Stats_InteractionsTitle))
|
||||
entries.append(.postInteractionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.interactionsGraph))
|
||||
entries.append(.postInteractionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.interactionsGraph, .twoAxis))
|
||||
|
||||
entries.append(.viewsBySourceTitle(presentationData.theme, presentationData.strings.Stats_ViewsBySourceTitle))
|
||||
entries.append(.viewsBySourceGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.viewsBySourceGraph, .bars))
|
||||
|
||||
entries.append(.followersBySourceTitle(presentationData.theme, presentationData.strings.Stats_FollowersBySourceTitle))
|
||||
entries.append(.followersBySourceGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.newFollowersBySourceGraph, .bars))
|
||||
|
||||
entries.append(.languagesTitle(presentationData.theme, presentationData.strings.Stats_LanguagesTitle))
|
||||
entries.append(.languagesGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.languagesGraph, .pie))
|
||||
}
|
||||
|
||||
return entries
|
||||
@ -306,7 +323,7 @@ public func channelStatsController(context: AccountContext, peer: Peer, cachedPe
|
||||
datacenterId = cachedData.statsDatacenterId
|
||||
}
|
||||
|
||||
let statsContext = ChannelStatsContext(network: context.account.network, datacenterId: datacenterId, peer: peer)
|
||||
let statsContext = ChannelStatsContext(postbox: context.account.postbox, network: context.account.network, datacenterId: datacenterId, peerId: peer.id)
|
||||
let dataSignal: Signal<ChannelStats?, NoError> = statsContext.state
|
||||
|> map { state in
|
||||
return state.stats
|
||||
@ -314,6 +331,9 @@ public func channelStatsController(context: AccountContext, peer: Peer, cachedPe
|
||||
if let w = statsContext, let a = a {
|
||||
if case .OnDemand = a.interactionsGraph {
|
||||
w.loadInteractionsGraph()
|
||||
w.loadNewFollowersBySourceGraph()
|
||||
w.loadViewsBySourceGraph()
|
||||
w.loadLanguagesGraph()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -13,12 +13,16 @@ import Charts
|
||||
class StatsGraphItem: ListViewItem, ItemListItem {
|
||||
let presentationData: ItemListPresentationData
|
||||
let graph: ChannelStatsGraph
|
||||
let type: ChartType
|
||||
let height: CGFloat
|
||||
let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
|
||||
init(presentationData: ItemListPresentationData, graph: ChannelStatsGraph, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
init(presentationData: ItemListPresentationData, graph: ChannelStatsGraph, type: ChartType, height: CGFloat = 0.0, sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
self.presentationData = presentationData
|
||||
self.graph = graph
|
||||
self.type = type
|
||||
self.height = height
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
}
|
||||
@ -115,12 +119,12 @@ class StatsGraphItemNode: ListViewItemNode {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 340.0)
|
||||
contentSize = CGSize(width: params.width, height: 350.0 + item.height)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 340.0)
|
||||
contentSize = CGSize(width: params.width, height: 350.0 + item.height)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
}
|
||||
|
||||
@ -173,7 +177,7 @@ class StatsGraphItemNode: ListViewItemNode {
|
||||
bottomStripeInset = 0.0
|
||||
}
|
||||
|
||||
strongSelf.chartNode.frame = CGRect(origin: CGPoint(x: leftInset, y: -10.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: 350.0))
|
||||
strongSelf.chartNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: 400.0))
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
|
||||
@ -182,7 +186,9 @@ class StatsGraphItemNode: ListViewItemNode {
|
||||
|
||||
if let updatedGraph = updatedGraph, case let .Loaded(data) = updatedGraph {
|
||||
var data = data.replacingOccurrences(of: "step", with: "bar")
|
||||
strongSelf.chartNode.setup(data)
|
||||
strongSelf.chartNode.setup(data, type: item.type, getDetailsData: { date, completion in
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -418,7 +418,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1269012015] = { return Api.messages.AffectedHistory.parse_affectedHistory($0) }
|
||||
dict[1244130093] = { return Api.StatsGraph.parse_statsGraphAsync($0) }
|
||||
dict[-1092839390] = { return Api.StatsGraph.parse_statsGraphError($0) }
|
||||
dict[-1057809608] = { return Api.StatsGraph.parse_statsGraph($0) }
|
||||
dict[-1901828938] = { return Api.StatsGraph.parse_statsGraph($0) }
|
||||
dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) }
|
||||
dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) }
|
||||
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
|
||||
@ -529,7 +529,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1837345356] = { return Api.InputChatPhoto.parse_inputChatUploadedPhoto($0) }
|
||||
dict[-1991004873] = { return Api.InputChatPhoto.parse_inputChatPhoto($0) }
|
||||
dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) }
|
||||
dict[205195937] = { return Api.stats.BroadcastStats.parse_broadcastStats($0) }
|
||||
dict[-1387279939] = { return Api.MessageInteractionCounters.parse_messageInteractionCounters($0) }
|
||||
dict[821185690] = { return Api.stats.BroadcastStats.parse_broadcastStats($0) }
|
||||
dict[-484987010] = { return Api.Updates.parse_updatesTooLong($0) }
|
||||
dict[-1857044719] = { return Api.Updates.parse_updateShortMessage($0) }
|
||||
dict[377562760] = { return Api.Updates.parse_updateShortChatMessage($0) }
|
||||
@ -775,7 +776,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[1041346555] = { return Api.updates.ChannelDifference.parse_channelDifferenceEmpty($0) }
|
||||
dict[543450958] = { return Api.updates.ChannelDifference.parse_channelDifference($0) }
|
||||
dict[-1531132162] = { return Api.updates.ChannelDifference.parse_channelDifferenceTooLong($0) }
|
||||
dict[-581804346] = { return Api.StatsRowAbsValueAndPrev.parse_statsRowAbsValueAndPrev($0) }
|
||||
dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) }
|
||||
dict[-264117680] = { return Api.ChatOnlines.parse_chatOnlines($0) }
|
||||
dict[488313413] = { return Api.InputAppEvent.parse_inputAppEvent($0) }
|
||||
@ -1225,6 +1225,8 @@ public struct Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.PaymentCharge:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.MessageInteractionCounters:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.stats.BroadcastStats:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.Updates:
|
||||
@ -1413,8 +1415,6 @@ public struct Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.updates.ChannelDifference:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.StatsRowAbsValueAndPrev:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.channels.AdminLogResults:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.ChatOnlines:
|
||||
|
||||
@ -12044,7 +12044,7 @@ public extension Api {
|
||||
public enum StatsGraph: TypeConstructorDescription {
|
||||
case statsGraphAsync(token: String)
|
||||
case statsGraphError(error: String)
|
||||
case statsGraph(json: Api.DataJSON)
|
||||
case statsGraph(flags: Int32, json: Api.DataJSON, zoomToken: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -12060,11 +12060,13 @@ public extension Api {
|
||||
}
|
||||
serializeString(error, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .statsGraph(let json):
|
||||
case .statsGraph(let flags, let json, let zoomToken):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1057809608)
|
||||
buffer.appendInt32(-1901828938)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
json.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(zoomToken!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -12075,8 +12077,8 @@ public extension Api {
|
||||
return ("statsGraphAsync", [("token", token)])
|
||||
case .statsGraphError(let error):
|
||||
return ("statsGraphError", [("error", error)])
|
||||
case .statsGraph(let json):
|
||||
return ("statsGraph", [("json", json)])
|
||||
case .statsGraph(let flags, let json, let zoomToken):
|
||||
return ("statsGraph", [("flags", flags), ("json", json), ("zoomToken", zoomToken)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -12103,13 +12105,19 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
public static func parse_statsGraph(_ reader: BufferReader) -> StatsGraph? {
|
||||
var _1: Api.DataJSON?
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.DataJSON?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.DataJSON
|
||||
}
|
||||
var _3: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.StatsGraph.statsGraph(json: _1!)
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.StatsGraph.statsGraph(flags: _1!, json: _2!, zoomToken: _3)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
@ -14978,6 +14986,48 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum MessageInteractionCounters: TypeConstructorDescription {
|
||||
case messageInteractionCounters(msgId: Int32, views: Int32, forwards: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageInteractionCounters(let msgId, let views, let forwards):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1387279939)
|
||||
}
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
serializeInt32(views, buffer: buffer, boxed: false)
|
||||
serializeInt32(forwards, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageInteractionCounters(let msgId, let views, let forwards):
|
||||
return ("messageInteractionCounters", [("msgId", msgId), ("views", views), ("forwards", forwards)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageInteractionCounters(_ reader: BufferReader) -> MessageInteractionCounters? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.MessageInteractionCounters.messageInteractionCounters(msgId: _1!, views: _2!, forwards: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum Updates: TypeConstructorDescription {
|
||||
case updatesTooLong
|
||||
@ -21264,54 +21314,6 @@ public extension Api {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum StatsRowAbsValueAndPrev: TypeConstructorDescription {
|
||||
case statsRowAbsValueAndPrev(id: String, title: String, shortTitle: String, values: Api.StatsAbsValueAndPrev)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .statsRowAbsValueAndPrev(let id, let title, let shortTitle, let values):
|
||||
if boxed {
|
||||
buffer.appendInt32(-581804346)
|
||||
}
|
||||
serializeString(id, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
serializeString(shortTitle, buffer: buffer, boxed: false)
|
||||
values.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .statsRowAbsValueAndPrev(let id, let title, let shortTitle, let values):
|
||||
return ("statsRowAbsValueAndPrev", [("id", id), ("title", title), ("shortTitle", shortTitle), ("values", values)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_statsRowAbsValueAndPrev(_ reader: BufferReader) -> StatsRowAbsValueAndPrev? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.StatsRowAbsValueAndPrev.statsRowAbsValueAndPrev(id: _1!, title: _2!, shortTitle: _3!, values: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum ChatOnlines: TypeConstructorDescription {
|
||||
case chatOnlines(onlines: Int32)
|
||||
|
||||
@ -539,47 +539,40 @@ public struct payments {
|
||||
public extension Api {
|
||||
public struct stats {
|
||||
public enum BroadcastStats: TypeConstructorDescription {
|
||||
case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, viewsBySource: [Api.StatsRowAbsValueAndPrev], newFollowersBySource: [Api.StatsRowAbsValueAndPrev], languages: [Api.StatsRowAbsValueAndPrev], growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph)
|
||||
case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, recentMessageInteractions: [Api.MessageInteractionCounters])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let viewsBySource, let newFollowersBySource, let languages, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph):
|
||||
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions):
|
||||
if boxed {
|
||||
buffer.appendInt32(205195937)
|
||||
buffer.appendInt32(821185690)
|
||||
}
|
||||
period.serialize(buffer, true)
|
||||
followers.serialize(buffer, true)
|
||||
viewsPerPost.serialize(buffer, true)
|
||||
sharesPerPost.serialize(buffer, true)
|
||||
enabledNotifications.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(viewsBySource.count))
|
||||
for item in viewsBySource {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(newFollowersBySource.count))
|
||||
for item in newFollowersBySource {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(languages.count))
|
||||
for item in languages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
growthGraph.serialize(buffer, true)
|
||||
followersGraph.serialize(buffer, true)
|
||||
muteGraph.serialize(buffer, true)
|
||||
topHoursGraph.serialize(buffer, true)
|
||||
interactionsGraph.serialize(buffer, true)
|
||||
viewsBySourceGraph.serialize(buffer, true)
|
||||
newFollowersBySourceGraph.serialize(buffer, true)
|
||||
languagesGraph.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(recentMessageInteractions.count))
|
||||
for item in recentMessageInteractions {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let viewsBySource, let newFollowersBySource, let languages, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph):
|
||||
return ("broadcastStats", [("period", period), ("followers", followers), ("viewsPerPost", viewsPerPost), ("sharesPerPost", sharesPerPost), ("enabledNotifications", enabledNotifications), ("viewsBySource", viewsBySource), ("newFollowersBySource", newFollowersBySource), ("languages", languages), ("growthGraph", growthGraph), ("followersGraph", followersGraph), ("muteGraph", muteGraph), ("topHoursGraph", topHoursGraph), ("interactionsGraph", interactionsGraph)])
|
||||
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions):
|
||||
return ("broadcastStats", [("period", period), ("followers", followers), ("viewsPerPost", viewsPerPost), ("sharesPerPost", sharesPerPost), ("enabledNotifications", enabledNotifications), ("growthGraph", growthGraph), ("followersGraph", followersGraph), ("muteGraph", muteGraph), ("topHoursGraph", topHoursGraph), ("interactionsGraph", interactionsGraph), ("viewsBySourceGraph", viewsBySourceGraph), ("newFollowersBySourceGraph", newFollowersBySourceGraph), ("languagesGraph", languagesGraph), ("recentMessageInteractions", recentMessageInteractions)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,17 +597,17 @@ public struct stats {
|
||||
if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue
|
||||
}
|
||||
var _6: [Api.StatsRowAbsValueAndPrev]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsRowAbsValueAndPrev.self)
|
||||
var _6: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _7: [Api.StatsRowAbsValueAndPrev]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsRowAbsValueAndPrev.self)
|
||||
var _7: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _8: [Api.StatsRowAbsValueAndPrev]?
|
||||
if let _ = reader.readInt32() {
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsRowAbsValueAndPrev.self)
|
||||
var _8: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _9: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -636,6 +629,10 @@ public struct stats {
|
||||
if let signature = reader.readInt32() {
|
||||
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _14: [Api.MessageInteractionCounters]?
|
||||
if let _ = reader.readInt32() {
|
||||
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageInteractionCounters.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
@ -649,8 +646,9 @@ public struct stats {
|
||||
let _c11 = _11 != nil
|
||||
let _c12 = _12 != nil
|
||||
let _c13 = _13 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 {
|
||||
return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, viewsBySource: _6!, newFollowersBySource: _7!, languages: _8!, growthGraph: _9!, followersGraph: _10!, muteGraph: _11!, topHoursGraph: _12!, interactionsGraph: _13!)
|
||||
let _c14 = _14 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
|
||||
return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, growthGraph: _6!, followersGraph: _7!, muteGraph: _8!, topHoursGraph: _9!, interactionsGraph: _10!, viewsBySourceGraph: _11!, newFollowersBySourceGraph: _12!, languagesGraph: _13!, recentMessageInteractions: _14!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
||||
@ -3964,11 +3964,13 @@ public extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
public static func loadAsyncGraph(token: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StatsGraph>) {
|
||||
public static func loadAsyncGraph(flags: Int32, token: String, x: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StatsGraph>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1749505346)
|
||||
buffer.appendInt32(1646092192)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(token, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "stats.loadAsyncGraph", parameters: [("token", token)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StatsGraph? in
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(x!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "stats.loadAsyncGraph", parameters: [("flags", flags), ("token", token), ("x", x)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StatsGraph? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
|
||||
@ -20,13 +20,6 @@ public struct ChannelStatsPercentValue: Equatable {
|
||||
public let total: Double
|
||||
}
|
||||
|
||||
public struct ChannelStatsNamedValue: Equatable {
|
||||
public let id: String
|
||||
public let title: String
|
||||
public let shortTitle: String
|
||||
public let value: ChannelStatsValue
|
||||
}
|
||||
|
||||
public enum ChannelStatsGraph: Equatable {
|
||||
case OnDemand(token: String)
|
||||
case Failed(error: String)
|
||||
@ -39,29 +32,29 @@ public final class ChannelStats: Equatable {
|
||||
public let viewsPerPost: ChannelStatsValue
|
||||
public let sharesPerPost: ChannelStatsValue
|
||||
public let enabledNotifications: ChannelStatsPercentValue
|
||||
public let viewsBySource: [ChannelStatsNamedValue]
|
||||
public let newFollowersBySource: [ChannelStatsNamedValue]
|
||||
public let languages: [ChannelStatsNamedValue]
|
||||
public let growthGraph: ChannelStatsGraph
|
||||
public let followersGraph: ChannelStatsGraph
|
||||
public let muteGraph: ChannelStatsGraph
|
||||
public let topHoursGraph: ChannelStatsGraph
|
||||
public let interactionsGraph: ChannelStatsGraph
|
||||
|
||||
public init(period: ChannelStatsDateRange, followers: ChannelStatsValue, viewsPerPost: ChannelStatsValue, sharesPerPost: ChannelStatsValue, enabledNotifications: ChannelStatsPercentValue, viewsBySource: [ChannelStatsNamedValue], newFollowersBySource: [ChannelStatsNamedValue], languages: [ChannelStatsNamedValue], growthGraph: ChannelStatsGraph, followersGraph: ChannelStatsGraph, muteGraph: ChannelStatsGraph, topHoursGraph: ChannelStatsGraph, interactionsGraph: ChannelStatsGraph) {
|
||||
public let viewsBySourceGraph: ChannelStatsGraph
|
||||
public let newFollowersBySourceGraph: ChannelStatsGraph
|
||||
public let languagesGraph: ChannelStatsGraph
|
||||
|
||||
public init(period: ChannelStatsDateRange, followers: ChannelStatsValue, viewsPerPost: ChannelStatsValue, sharesPerPost: ChannelStatsValue, enabledNotifications: ChannelStatsPercentValue, growthGraph: ChannelStatsGraph, followersGraph: ChannelStatsGraph, muteGraph: ChannelStatsGraph, topHoursGraph: ChannelStatsGraph, interactionsGraph: ChannelStatsGraph, viewsBySourceGraph: ChannelStatsGraph, newFollowersBySourceGraph: ChannelStatsGraph, languagesGraph: ChannelStatsGraph) {
|
||||
self.period = period
|
||||
self.followers = followers
|
||||
self.viewsPerPost = viewsPerPost
|
||||
self.sharesPerPost = sharesPerPost
|
||||
self.enabledNotifications = enabledNotifications
|
||||
self.viewsBySource = viewsBySource
|
||||
self.newFollowersBySource = newFollowersBySource
|
||||
self.languages = languages
|
||||
self.growthGraph = growthGraph
|
||||
self.followersGraph = followersGraph
|
||||
self.muteGraph = muteGraph
|
||||
self.topHoursGraph = topHoursGraph
|
||||
self.interactionsGraph = interactionsGraph
|
||||
self.viewsBySourceGraph = viewsBySourceGraph
|
||||
self.newFollowersBySourceGraph = newFollowersBySourceGraph
|
||||
self.languagesGraph = languagesGraph
|
||||
}
|
||||
|
||||
public static func == (lhs: ChannelStats, rhs: ChannelStats) -> Bool {
|
||||
@ -80,15 +73,6 @@ public final class ChannelStats: Equatable {
|
||||
if lhs.enabledNotifications != rhs.enabledNotifications {
|
||||
return false
|
||||
}
|
||||
if lhs.viewsBySource != rhs.viewsBySource {
|
||||
return false
|
||||
}
|
||||
if lhs.newFollowersBySource != rhs.newFollowersBySource {
|
||||
return false
|
||||
}
|
||||
if lhs.languages != rhs.languages {
|
||||
return false
|
||||
}
|
||||
if lhs.growthGraph != rhs.growthGraph {
|
||||
return false
|
||||
}
|
||||
@ -104,27 +88,48 @@ public final class ChannelStats: Equatable {
|
||||
if lhs.interactionsGraph != rhs.interactionsGraph {
|
||||
return false
|
||||
}
|
||||
if lhs.viewsBySourceGraph != rhs.viewsBySourceGraph {
|
||||
return false
|
||||
}
|
||||
if lhs.newFollowersBySourceGraph != rhs.newFollowersBySourceGraph {
|
||||
return false
|
||||
}
|
||||
if lhs.languagesGraph != rhs.languagesGraph {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func withUpdatedGrowthGraph(_ growthGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, viewsBySource: self.viewsBySource, newFollowersBySource: self.newFollowersBySource, languages: self.languages, growthGraph: growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph)
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedFollowersGraph(_ followersGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, viewsBySource: self.viewsBySource, newFollowersBySource: self.newFollowersBySource, languages: self.languages, growthGraph: self.growthGraph, followersGraph: followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph)
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedMuteGraph(_ muteGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, viewsBySource: self.viewsBySource, newFollowersBySource: self.newFollowersBySource, languages: self.languages, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph)
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedTopHoursGraph(_ viewsByHourGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, viewsBySource: self.viewsBySource, newFollowersBySource: self.newFollowersBySource, languages: self.languages, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: viewsByHourGraph, interactionsGraph: self.interactionsGraph)
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: viewsByHourGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedInteractionsGraph(_ interactionsGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, viewsBySource: self.viewsBySource, newFollowersBySource: self.newFollowersBySource, languages: self.languages, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: interactionsGraph)
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedViewsBySourceGraph(_ viewsBySourceGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedNewFollowersBySourceGraph(_ newFollowersBySourceGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: newFollowersBySourceGraph, languagesGraph: self.languagesGraph)
|
||||
}
|
||||
|
||||
public func withUpdatedLanguagesGraph(_ languagesGraph: ChannelStatsGraph) -> ChannelStats {
|
||||
return ChannelStats(period: self.period, followers: self.followers, viewsPerPost: self.viewsPerPost, sharesPerPost: self.sharesPerPost, enabledNotifications: self.enabledNotifications, growthGraph: self.growthGraph, followersGraph: self.followersGraph, muteGraph: self.muteGraph, topHoursGraph: self.topHoursGraph, interactionsGraph: self.interactionsGraph, viewsBySourceGraph: self.viewsBySourceGraph, newFollowersBySourceGraph: self.newFollowersBySourceGraph, languagesGraph: languagesGraph)
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,46 +137,54 @@ public struct ChannelStatsContextState: Equatable {
|
||||
public var stats: ChannelStats?
|
||||
}
|
||||
|
||||
private func requestStats(network: Network, datacenterId: Int32, peer: Peer, dark: Bool = false) -> Signal<ChannelStats?, NoError> {
|
||||
guard let inputChannel = apiInputChannel(peer) else {
|
||||
return .never()
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
if dark {
|
||||
flags |= (1 << 1)
|
||||
}
|
||||
|
||||
let signal: Signal<Api.stats.BroadcastStats, MTRpcError>
|
||||
if network.datacenterId != datacenterId {
|
||||
signal = network.download(datacenterId: Int(datacenterId), isMedia: false, tag: nil)
|
||||
|> castError(MTRpcError.self)
|
||||
|> mapToSignal { worker in
|
||||
return worker.request(Api.functions.stats.getBroadcastStats(flags: flags, channel: inputChannel))
|
||||
private func requestStats(postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId, dark: Bool = false) -> Signal<ChannelStats?, NoError> {
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
} |> mapToSignal { peer -> Signal<ChannelStats?, NoError> in
|
||||
guard let peer = peer, let inputChannel = apiInputChannel(peer) else {
|
||||
return .never()
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
if dark {
|
||||
flags |= (1 << 1)
|
||||
}
|
||||
|
||||
let signal: Signal<Api.stats.BroadcastStats, MTRpcError>
|
||||
if network.datacenterId != datacenterId {
|
||||
signal = network.download(datacenterId: Int(datacenterId), isMedia: false, tag: nil)
|
||||
|> castError(MTRpcError.self)
|
||||
|> mapToSignal { worker in
|
||||
return worker.request(Api.functions.stats.getBroadcastStats(flags: flags, channel: inputChannel))
|
||||
}
|
||||
} else {
|
||||
signal = network.request(Api.functions.stats.getBroadcastStats(flags: flags, channel: inputChannel))
|
||||
}
|
||||
|
||||
return signal
|
||||
|> map { result -> ChannelStats? in
|
||||
return ChannelStats(apiBroadcastStats: result)
|
||||
}
|
||||
|> `catch` { _ -> Signal<ChannelStats?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
} else {
|
||||
signal = network.request(Api.functions.stats.getBroadcastStats(flags: flags, channel: inputChannel))
|
||||
}
|
||||
|
||||
return signal
|
||||
|> map { result -> ChannelStats? in
|
||||
return ChannelStats(apiBroadcastStats: result)
|
||||
}
|
||||
|> `catch` { _ -> Signal<ChannelStats?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func requestGraph(network: Network, datacenterId: Int32, token: String) -> Signal<ChannelStatsGraph?, NoError> {
|
||||
private func requestGraph(network: Network, datacenterId: Int32, token: String, x: Int64? = nil) -> Signal<ChannelStatsGraph?, NoError> {
|
||||
var flags: Int32 = 0
|
||||
if let _ = x {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
let signal: Signal<Api.StatsGraph, MTRpcError>
|
||||
if network.datacenterId != datacenterId {
|
||||
signal = network.download(datacenterId: Int(datacenterId), isMedia: false, tag: nil)
|
||||
|> castError(MTRpcError.self)
|
||||
|> mapToSignal { worker in
|
||||
return worker.request(Api.functions.stats.loadAsyncGraph(token: token))
|
||||
return worker.request(Api.functions.stats.loadAsyncGraph(flags: flags, token: token, x: x))
|
||||
}
|
||||
} else {
|
||||
signal = network.request(Api.functions.stats.loadAsyncGraph(token: token))
|
||||
signal = network.request(Api.functions.stats.loadAsyncGraph(flags: flags, token: token, x: x))
|
||||
}
|
||||
|
||||
return signal
|
||||
@ -184,9 +197,10 @@ private func requestGraph(network: Network, datacenterId: Int32, token: String)
|
||||
}
|
||||
|
||||
private final class ChannelStatsContextImpl {
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let peer: Peer
|
||||
private let datacenterId: Int32
|
||||
private let peerId: PeerId
|
||||
|
||||
private var _state: ChannelStatsContextState {
|
||||
didSet {
|
||||
@ -203,12 +217,13 @@ private final class ChannelStatsContextImpl {
|
||||
private let disposable = MetaDisposable()
|
||||
private let disposables = DisposableDict<String>()
|
||||
|
||||
init(network: Network, datacenterId: Int32, peer: Peer) {
|
||||
init(postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId) {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.peer = peer
|
||||
self.datacenterId = datacenterId
|
||||
self.peerId = peerId
|
||||
self._state = ChannelStatsContextState(stats: nil)
|
||||
self._statePromise.set(.single(self._state))
|
||||
|
||||
@ -224,7 +239,7 @@ private final class ChannelStatsContextImpl {
|
||||
private func load() {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
|
||||
self.disposable.set((requestStats(network: self.network, datacenterId: self.datacenterId, peer: self.peer)
|
||||
self.disposable.set((requestStats(postbox: self.postbox, network: self.network, datacenterId: self.datacenterId, peerId: self.peerId)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] stats in
|
||||
if let strongSelf = self {
|
||||
strongSelf._state = ChannelStatsContextState(stats: stats)
|
||||
@ -307,6 +322,51 @@ private final class ChannelStatsContextImpl {
|
||||
}), forKey: token)
|
||||
}
|
||||
}
|
||||
|
||||
func loadViewsBySourceGraph() {
|
||||
guard let stats = self._state.stats else {
|
||||
return
|
||||
}
|
||||
if case let .OnDemand(token) = stats.viewsBySourceGraph {
|
||||
self.disposables.set((requestGraph(network: self.network, datacenterId: self.datacenterId, token: token)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] graph in
|
||||
if let strongSelf = self, let graph = graph {
|
||||
strongSelf._state = ChannelStatsContextState(stats: strongSelf._state.stats?.withUpdatedViewsBySourceGraph(graph))
|
||||
strongSelf._statePromise.set(.single(strongSelf._state))
|
||||
}
|
||||
}), forKey: token)
|
||||
}
|
||||
}
|
||||
|
||||
func loadNewFollowersBySourceGraph() {
|
||||
guard let stats = self._state.stats else {
|
||||
return
|
||||
}
|
||||
if case let .OnDemand(token) = stats.newFollowersBySourceGraph {
|
||||
self.disposables.set((requestGraph(network: self.network, datacenterId: self.datacenterId, token: token)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] graph in
|
||||
if let strongSelf = self, let graph = graph {
|
||||
strongSelf._state = ChannelStatsContextState(stats: strongSelf._state.stats?.withUpdatedNewFollowersBySourceGraph(graph))
|
||||
strongSelf._statePromise.set(.single(strongSelf._state))
|
||||
}
|
||||
}), forKey: token)
|
||||
}
|
||||
}
|
||||
|
||||
func loadLanguagesGraph() {
|
||||
guard let stats = self._state.stats else {
|
||||
return
|
||||
}
|
||||
if case let .OnDemand(token) = stats.languagesGraph {
|
||||
self.disposables.set((requestGraph(network: self.network, datacenterId: self.datacenterId, token: token)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] graph in
|
||||
if let strongSelf = self, let graph = graph {
|
||||
strongSelf._state = ChannelStatsContextState(stats: strongSelf._state.stats?.withUpdatedLanguagesGraph(graph))
|
||||
strongSelf._statePromise.set(.single(strongSelf._state))
|
||||
}
|
||||
}), forKey: token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChannelStatsContext {
|
||||
@ -324,12 +384,12 @@ public final class ChannelStatsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public init(network: Network, datacenterId: Int32, peer: Peer) {
|
||||
public init(postbox: Postbox, network: Network, datacenterId: Int32, peerId: PeerId) {
|
||||
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
|
||||
return ChannelStatsContextImpl(network: network, datacenterId: datacenterId, peer: peer)
|
||||
return ChannelStatsContextImpl(postbox: postbox, network: network, datacenterId: datacenterId, peerId: peerId)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
public func loadGrowthGraph() {
|
||||
self.impl.with { impl in
|
||||
impl.loadGrowthGraph()
|
||||
@ -359,12 +419,30 @@ public final class ChannelStatsContext {
|
||||
impl.loadInteractionsGraph()
|
||||
}
|
||||
}
|
||||
|
||||
public func loadViewsBySourceGraph() {
|
||||
self.impl.with { impl in
|
||||
impl.loadViewsBySourceGraph()
|
||||
}
|
||||
}
|
||||
|
||||
public func loadNewFollowersBySourceGraph() {
|
||||
self.impl.with { impl in
|
||||
impl.loadNewFollowersBySourceGraph()
|
||||
}
|
||||
}
|
||||
|
||||
public func loadLanguagesGraph() {
|
||||
self.impl.with { impl in
|
||||
impl.loadLanguagesGraph()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ChannelStatsGraph {
|
||||
init(apiStatsGraph: Api.StatsGraph) {
|
||||
switch apiStatsGraph {
|
||||
case let .statsGraph(json):
|
||||
case let .statsGraph(_, json, _):
|
||||
if case let .dataJSON(string) = json {
|
||||
self = .Loaded(data: string)
|
||||
} else {
|
||||
@ -396,15 +474,6 @@ extension ChannelStatsValue {
|
||||
}
|
||||
}
|
||||
|
||||
extension ChannelStatsNamedValue {
|
||||
init(apiStatsRowAbsValueAndPrev: Api.StatsRowAbsValueAndPrev) {
|
||||
switch apiStatsRowAbsValueAndPrev {
|
||||
case let .statsRowAbsValueAndPrev(id, title, shortTitle, values):
|
||||
self = ChannelStatsNamedValue(id: id, title: title, shortTitle: shortTitle, value: ChannelStatsValue(apiStatsAbsValueAndPrev: values))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ChannelStatsPercentValue {
|
||||
init(apiPercentValue: Api.StatsPercentValue) {
|
||||
switch apiPercentValue {
|
||||
@ -417,8 +486,8 @@ extension ChannelStatsPercentValue {
|
||||
extension ChannelStats {
|
||||
convenience init(apiBroadcastStats: Api.stats.BroadcastStats) {
|
||||
switch apiBroadcastStats {
|
||||
case let .broadcastStats(period, followers, viewsPerPost, sharesPerPost, enabledNotifications, viewsBySource, newFollowersBySource, languages, growthGraph, followersGraph, muteGraph, topHoursGraph, interactionsGraph):
|
||||
self.init(period: ChannelStatsDateRange(apiStatsDateRangeDays: period), followers: ChannelStatsValue(apiStatsAbsValueAndPrev: followers), viewsPerPost: ChannelStatsValue(apiStatsAbsValueAndPrev: viewsPerPost), sharesPerPost: ChannelStatsValue(apiStatsAbsValueAndPrev: sharesPerPost), enabledNotifications: ChannelStatsPercentValue(apiPercentValue: enabledNotifications), viewsBySource: viewsBySource.map { ChannelStatsNamedValue(apiStatsRowAbsValueAndPrev: $0) }, newFollowersBySource: newFollowersBySource.map { ChannelStatsNamedValue(apiStatsRowAbsValueAndPrev: $0) }, languages: languages.map { ChannelStatsNamedValue(apiStatsRowAbsValueAndPrev: $0) }, growthGraph: ChannelStatsGraph(apiStatsGraph: growthGraph), followersGraph: ChannelStatsGraph(apiStatsGraph: followersGraph), muteGraph: ChannelStatsGraph(apiStatsGraph: muteGraph), topHoursGraph: ChannelStatsGraph(apiStatsGraph: topHoursGraph), interactionsGraph: ChannelStatsGraph(apiStatsGraph: interactionsGraph))
|
||||
case let .broadcastStats(period, followers, viewsPerPost, sharesPerPost, enabledNotifications, growthGraph, followersGraph, muteGraph, topHoursGraph, interactionsGraph, viewsBySourceGraph, newFollowersBySourceGraph, languagesGraph, recentMessageInteractions):
|
||||
self.init(period: ChannelStatsDateRange(apiStatsDateRangeDays: period), followers: ChannelStatsValue(apiStatsAbsValueAndPrev: followers), viewsPerPost: ChannelStatsValue(apiStatsAbsValueAndPrev: viewsPerPost), sharesPerPost: ChannelStatsValue(apiStatsAbsValueAndPrev: sharesPerPost), enabledNotifications: ChannelStatsPercentValue(apiPercentValue: enabledNotifications), growthGraph: ChannelStatsGraph(apiStatsGraph: growthGraph), followersGraph: ChannelStatsGraph(apiStatsGraph: followersGraph), muteGraph: ChannelStatsGraph(apiStatsGraph: muteGraph), topHoursGraph: ChannelStatsGraph(apiStatsGraph: topHoursGraph), interactionsGraph: ChannelStatsGraph(apiStatsGraph: interactionsGraph), viewsBySourceGraph: ChannelStatsGraph(apiStatsGraph: viewsBySourceGraph), newFollowersBySourceGraph: ChannelStatsGraph(apiStatsGraph: newFollowersBySourceGraph), languagesGraph: ChannelStatsGraph(apiStatsGraph: languagesGraph))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user