Chart fixes

This commit is contained in:
Ilya Laktyushin 2020-03-25 22:35:26 +04:00
parent d774ecc5d5
commit b9b5cb1b73
17 changed files with 44 additions and 38 deletions

View File

@ -172,7 +172,7 @@ public class BaseChartController: ChartThemeContainer {
public var setDetailsViewPositionClosure: ((CGFloat) -> Void)?
public var setDetailsChartVisibleClosure: ((Bool, Bool) -> Void)?
public var setDetailsViewModel: ((ChartDetailsViewModel, Bool) -> Void)?
public var setDetailsViewModel: ((ChartDetailsViewModel, Bool, Bool) -> Void)?
public var getDetailsData: ((Date, @escaping (ChartsCollection?) -> Void) -> Void)?
public var setChartTitleClosure: ((String, Bool) -> Void)?
public var setBackButtonVisibilityClosure: ((Bool, Bool) -> Void)?

View File

@ -196,7 +196,7 @@ class GeneralChartComponentController: ChartThemeContainer {
var detailsVisible = false
func showDetailsView(at chartPosition: CGFloat, detailsViewPosition: CGFloat, dataIndex: Int, date: Date, animted: Bool) {
setDetailsViewModel?(chartDetailsViewModel(closestDate: date, pointIndex: dataIndex), animted)
setDetailsViewModel?(chartDetailsViewModel(closestDate: date, pointIndex: dataIndex), animted, false)
setDetailsChartVisibleClosure?(true, true)
setDetailsViewPositionClosure?(detailsViewPosition)
detailsVisible = true
@ -226,7 +226,7 @@ class GeneralChartComponentController: ChartThemeContainer {
var setChartTitleClosure: ((String, Bool) -> Void)?
var setDetailsViewPositionClosure: ((CGFloat) -> Void)?
var setDetailsChartVisibleClosure: ((Bool, Bool) -> Void)?
var setDetailsViewModel: ((ChartDetailsViewModel, Bool) -> Void)?
var setDetailsViewModel: ((ChartDetailsViewModel, Bool, Bool) -> Void)?
var chartRangePagingClosure: ((Bool, CGFloat) -> Void)? // isEnabled, PageSize
func apply(theme: ChartTheme, animated: Bool) {

View File

@ -134,7 +134,7 @@ public class BaseLinesChartController: BaseChartController {
public override func didTapZoomIn(date: Date, pointIndex: Int) {
guard isZoomed == false else { return }
setDetailsViewModel?(chartDetailsViewModel(closestDate: date, pointIndex: pointIndex, loading: true), false)
setDetailsViewModel?(chartDetailsViewModel(closestDate: date, pointIndex: pointIndex, loading: true), false, false)
self.getDetailsData?(date, { updatedCollection in
if let updatedCollection = updatedCollection {

View File

@ -147,7 +147,7 @@ public class GeneralLinesChartController: BaseLinesChartController {
let chartValue: CGFloat = CGFloat(closestDate.timeIntervalSince1970)
let detailsViewPosition = (chartValue - horizontalRange.lowerBound) / horizontalRange.distance * chartFrame.width + chartFrame.minX
self.setDetailsViewModel?(chartDetailsViewModel(closestDate: closestDate, pointIndex: minIndex, loading: false), chartInteractionWasBegin)
self.setDetailsViewModel?(chartDetailsViewModel(closestDate: closestDate, pointIndex: minIndex, loading: false), chartInteractionWasBegin, !chartInteractionWasBegin)
self.setDetailsChartVisibleClosure?(true, true)
self.setDetailsViewPositionClosure?(detailsViewPosition)
self.verticalLineRenderer.values = [chartValue]

View File

@ -176,7 +176,7 @@ public class TwoAxisLinesChartController: BaseLinesChartController {
let chartValue: CGFloat = CGFloat(closestDate.timeIntervalSince1970)
let detailsViewPosition = (chartValue - horizontalRange.lowerBound) / horizontalRange.distance * chartFrame.width + chartFrame.minX
self.setDetailsViewModel?(chartDetailsViewModel(closestDate: closestDate, pointIndex: minIndex, loading: false), chartInteractionWasBegin)
self.setDetailsViewModel?(chartDetailsViewModel(closestDate: closestDate, pointIndex: minIndex, loading: false), chartInteractionWasBegin, !chartInteractionWasBegin)
self.setDetailsChartVisibleClosure?(true, true)
self.setDetailsViewPositionClosure?(detailsViewPosition)
self.verticalLineRenderer.values = [chartValue]

View File

@ -59,8 +59,8 @@ public class PercentPieChartController: BaseChartController {
controller.setDetailsChartVisibleClosure = { [unowned self] (visible, animated) in
self.setDetailsChartVisibleClosure?(visible, animated)
}
controller.setDetailsViewModel = { [unowned self] (viewModel, animated) in
self.setDetailsViewModel?(viewModel, animated)
controller.setDetailsViewModel = { [unowned self] (viewModel, animated, feedback) in
self.setDetailsViewModel?(viewModel, animated, feedback)
}
controller.updatePreviewRangeClosure = { [unowned self] (fraction, animated) in
self.chartRangeUpdatedClosure?(fraction, animated)

View File

@ -136,7 +136,7 @@ class PieChartComponentController: GeneralChartComponentController {
func updateSelectedDataLabelIfNeeded() {
if let segment = pieChartRenderer.selectedSegment {
self.setDetailsChartVisibleClosure?(true, true)
self.setDetailsViewModel?(chartDetailsViewModel(segmentInde: segment), false)
self.setDetailsViewModel?(chartDetailsViewModel(segmentInde: segment), false, false)
self.setDetailsViewPositionClosure?(chartFrame().width / 4)
} else {
self.setDetailsChartVisibleClosure?(false, true)

View File

@ -193,7 +193,7 @@ class BarsComponentController: GeneralChartComponentController {
color: .white,
visible: visibleChartValues.count > 1)
} else {
viewModel.title = ""
viewModel.title = "\(Int(closestDate.timeIntervalSince1970)):00"
}
return viewModel
}

View File

@ -51,8 +51,8 @@ public class DailyBarsChartController: BaseChartController {
controller.setDetailsChartVisibleClosure = { [unowned self] (visible, animated) in
self.setDetailsChartVisibleClosure?(visible, animated)
}
controller.setDetailsViewModel = { [unowned self] (viewModel, animated) in
self.setDetailsViewModel?(viewModel, animated)
controller.setDetailsViewModel = { [unowned self] (viewModel, animated, feedback) in
self.setDetailsViewModel?(viewModel, animated, feedback)
}
controller.updatePreviewRangeClosure = { [unowned self] (fraction, animated) in
self.chartRangeUpdatedClosure?(fraction, animated)

View File

@ -54,8 +54,8 @@ public class StackedBarsChartController: BaseChartController {
controller.setDetailsChartVisibleClosure = { [unowned self] (visible, animated) in
self.setDetailsChartVisibleClosure?(visible, animated)
}
controller.setDetailsViewModel = { [unowned self] (viewModel, animated) in
self.setDetailsViewModel?(viewModel, animated)
controller.setDetailsViewModel = { [unowned self] (viewModel, animated, feedback) in
self.setDetailsViewModel?(viewModel, animated, feedback)
}
controller.updatePreviewRangeClosure = { [unowned self] (fraction, animated) in
self.chartRangeUpdatedClosure?(fraction, animated)

View File

@ -54,8 +54,8 @@ public class StepBarsChartController: BaseChartController {
controller.setDetailsChartVisibleClosure = { [unowned self] (visible, animated) in
self.setDetailsChartVisibleClosure?(visible, animated)
}
controller.setDetailsViewModel = { [unowned self] (viewModel, animated) in
self.setDetailsViewModel?(viewModel, animated)
controller.setDetailsViewModel = { [unowned self] (viewModel, animated, feedback) in
self.setDetailsViewModel?(viewModel, animated, feedback)
}
controller.updatePreviewRangeClosure = { [unowned self] (fraction, animated) in
self.chartRangeUpdatedClosure?(fraction, animated)

View File

@ -193,7 +193,7 @@ public class TwoAxisStepBarsChartController: BaseLinesChartController {
let chartValue: CGFloat = CGFloat(closestDate.timeIntervalSince1970)
let detailsViewPosition = (chartValue - horizontalRange.lowerBound) / horizontalRange.distance * chartFrame.width + chartFrame.minX + barOffset
self.setDetailsViewModel?(chartDetailsViewModel(closestDate: closestDate, pointIndex: minIndex, loading: false), chartInteractionWasBegin)
self.setDetailsViewModel?(chartDetailsViewModel(closestDate: closestDate, pointIndex: minIndex, loading: false), chartInteractionWasBegin, !chartInteractionWasBegin)
self.setDetailsChartVisibleClosure?(true, true)
self.setDetailsViewPositionClosure?(detailsViewPosition)
self.verticalLineRenderer.values = [chartValue]

View File

@ -8,6 +8,7 @@
import UIKit
import GraphCore
import Display
private enum Constants {
static let chartViewHeightFraction: CGFloat = 0.55
@ -36,6 +37,8 @@ class ChartStackSection: UIView, ChartThemeContainer {
var displayRange: Bool = true
let hapticFeedback = HapticFeedback()
init() {
sectionContainerView = UIView()
chartView = ChartView()
@ -188,8 +191,11 @@ class ChartStackSection: UIView, ChartThemeContainer {
controller.chartFrame = { [unowned self] in
return self.chartView.chartFrame
}
controller.setDetailsViewModel = { [unowned self] viewModel, animated in
controller.setDetailsViewModel = { [unowned self] viewModel, animated, feedback in
self.chartView.setDetailsViewModel(viewModel: viewModel, animated: animated)
if feedback {
self.hapticFeedback.tap()
}
}
controller.setDetailsChartVisibleClosure = { [unowned self] visible, animated in
self.chartView.setDetailsChartVisible(visible, animated: animated)

View File

@ -123,12 +123,12 @@ class ChartView: UIControl {
let detailsViewSize = detailsView.intrinsicContentSize
maxDetailsViewWidth = max(maxDetailsViewWidth, detailsViewSize.width)
if maxDetailsViewWidth + detailsTableLeftOffset > detailsViewPosition {
detailsView.frame = CGRect(x: min(detailsViewPosition + detailsTableLeftOffset, bounds.width - maxDetailsViewWidth - detailsTableLeftOffset),
detailsView.frame = CGRect(x: max(detailsTableLeftOffset, min(detailsViewPosition + detailsTableLeftOffset, bounds.width - maxDetailsViewWidth - detailsTableLeftOffset)),
y: chartInsets.top + detailsTableTopOffset,
width: maxDetailsViewWidth,
height: detailsViewSize.height)
} else {
detailsView.frame = CGRect(x: min(detailsViewPosition - maxDetailsViewWidth - detailsTableLeftOffset, bounds.width - maxDetailsViewWidth - detailsTableLeftOffset),
detailsView.frame = CGRect(x: max(detailsTableLeftOffset, min(detailsViewPosition - maxDetailsViewWidth - detailsTableLeftOffset, bounds.width - maxDetailsViewWidth - detailsTableLeftOffset)),
y: chartInsets.top + detailsTableTopOffset,
width: maxDetailsViewWidth,
height: detailsViewSize.height)

View File

@ -141,14 +141,14 @@ private enum StatsEntry: ItemListNodeEntry {
return 16
case .postInteractionsGraph:
return 17
case .postsTitle:
return 18
case let .post(index, _, _, _, _, _):
return 19 + index
case .instantPageInteractionsTitle:
return 1000
case .instantPageInteractionsGraph:
return 1001
return 18
case .instantPageInteractionsGraph:
return 19
case .postsTitle:
return 20
case let .post(index, _, _, _, _, _):
return 21 + index
}
}
@ -398,6 +398,11 @@ private func statsControllerEntries(data: ChannelStats?, messages: [Message]?, i
entries.append(.postInteractionsTitle(presentationData.theme, presentationData.strings.Stats_InteractionsTitle))
entries.append(.postInteractionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.interactionsGraph, .twoAxisStep))
}
if !data.instantPageInteractionsGraph.isEmpty {
entries.append(.instantPageInteractionsTitle(presentationData.theme, presentationData.strings.Stats_InstantViewInteractionsTitle))
entries.append(.instantPageInteractionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.instantPageInteractionsGraph, .twoAxisStep))
}
if let messages = messages, !messages.isEmpty, let interactions = interactions, !interactions.isEmpty {
entries.append(.postsTitle(presentationData.theme, presentationData.strings.Stats_PostsTitle))
@ -409,11 +414,6 @@ private func statsControllerEntries(data: ChannelStats?, messages: [Message]?, i
}
}
}
if !data.instantPageInteractionsGraph.isEmpty {
entries.append(.instantPageInteractionsTitle(presentationData.theme, presentationData.strings.Stats_InstantViewInteractionsTitle))
entries.append(.instantPageInteractionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.instantPageInteractionsGraph, .twoAxisStep))
}
}
return entries

View File

@ -174,7 +174,7 @@ class StatsGraphItemNode: ListViewItemNode {
height = calculateVisiblityHeight(width: params.width - params.leftInset - params.rightInset, items: items)
}
if item.type == .hourlyStep {
height -= 42.0
height -= 82.0
}
visibilityHeight = height
}
@ -246,7 +246,7 @@ class StatsGraphItemNode: ListViewItemNode {
}
strongSelf.chartContainerNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: contentSize.height))
strongSelf.chartNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width - leftInset - rightInset, height: 750.0))
strongSelf.chartNode.frame = CGRect(origin: CGPoint(x: 0.0, y: item.type == .hourlyStep ? -40.0 : 0.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: 750.0))
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
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)))

View File

@ -158,9 +158,9 @@ class StatsOverviewItemNode: ListViewItemNode {
let (followersValueLabelLayout, followersValueLabelApply) = makeFollowersValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: compactNumericCountString(Int(item.stats.followers.current)), font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (viewsPerPostValueLabelLayout, viewsPerPostValueLabelApply) = makeViewsPerPostValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.viewsPerPost.current > 0 ? compactNumericCountString(Int(item.stats.viewsPerPost.current)) : "", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (viewsPerPostValueLabelLayout, viewsPerPostValueLabelApply) = makeViewsPerPostValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.viewsPerPost.current > 0 || item.stats.sharesPerPost.current > 0 ? compactNumericCountString(Int(item.stats.viewsPerPost.current)) : "", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (sharesPerPostValueLabelLayout, sharesPerPostValueLabelApply) = makeSharesPerPostValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.sharesPerPost.current > 0 ? compactNumericCountString(Int(item.stats.sharesPerPost.current)) : "", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (sharesPerPostValueLabelLayout, sharesPerPostValueLabelApply) = makeSharesPerPostValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.sharesPerPost.current > 0 || item.stats.viewsPerPost.current > 0 ? compactNumericCountString(Int(item.stats.sharesPerPost.current)) : "", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var enabledNotifications: Double = 0.0
if item.stats.enabledNotifications.total > 0 {
@ -171,9 +171,9 @@ class StatsOverviewItemNode: ListViewItemNode {
let (followersTitleLabelLayout, followersTitleLabelApply) = makeFollowersTitleLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stats_Followers, font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (viewsPerPostTitleLabelLayout, viewsPerPostTitleLabelApply) = makeViewsPerPostTitleLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.viewsPerPost.current > 0 ? item.presentationData.strings.Stats_ViewsPerPost : "", font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (viewsPerPostTitleLabelLayout, viewsPerPostTitleLabelApply) = makeViewsPerPostTitleLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.viewsPerPost.current > 0 || item.stats.sharesPerPost.current > 0 ? item.presentationData.strings.Stats_ViewsPerPost : "", font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (sharesPerPostTitleLabelLayout, sharesPerPostTitleLabelApply) = makeSharesPerPostTitleLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.sharesPerPost.current > 0 ? item.presentationData.strings.Stats_SharesPerPost : "", font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (sharesPerPostTitleLabelLayout, sharesPerPostTitleLabelApply) = makeSharesPerPostTitleLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.stats.sharesPerPost.current > 0 || item.stats.viewsPerPost.current > 0 ? item.presentationData.strings.Stats_SharesPerPost : "", font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (enabledNotificationsTitleLabelLayout, enabledNotificationsTitleLabelApply) = makeEnabledNotificationsTitleLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Stats_EnabledNotifications, font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))