Charts improvements

This commit is contained in:
Ilya Laktyushin 2020-03-14 00:46:32 +04:00
parent 598f270635
commit bcae054398
33 changed files with 461 additions and 339 deletions

View File

@ -5382,7 +5382,7 @@ Any member of this group will be able to see messages in the channel.";
"Stats.MessageForwards_0" = "%@ forwards";
"Stats.MessageForwards_1" = "%@ forward";
"Stats.MessageForwards_2" = "%@ forwards";
"Stats.MessageForwards_3_10" = "%@ forwardss";
"Stats.MessageForwards_3_10" = "%@ forwards";
"Stats.MessageForwards_many" = "%@ forwards";
"Stats.MessageForwards_any" = "%@ forwards";
@ -5392,4 +5392,4 @@ Any member of this group will be able to see messages in the channel.";
"InstantPage.Views_3_10" = "%@ views";
"InstantPage.Views_many" = "%@ views";
"InstantPage.Views_any" = "%@ views";
"InstantPage.FeedbackButtonShort" = "Leave feedback";
"InstantPage.FeedbackButtonShort" = "Wrong layout?";

View File

@ -74,20 +74,23 @@ public struct ChartDetailsViewModel {
public internal(set) var values: [Value]
public internal(set) var totalValue: Value?
public internal(set) var tapAction: (() -> Void)?
public internal(set) var hideAction: (() -> Void)?
static let blank = ChartDetailsViewModel(title: "", showArrow: false, showPrefixes: false, values: [], totalValue: nil, tapAction: nil)
static let blank = ChartDetailsViewModel(title: "", showArrow: false, showPrefixes: false, values: [], totalValue: nil, tapAction: nil, hideAction: nil)
public init(title: String,
showArrow: Bool,
showPrefixes: Bool,
values: [Value],
totalValue: Value?,
tapAction: (() -> Void)?) {
tapAction: (() -> Void)?,
hideAction: (() -> Void)?) {
self.title = title
self.showArrow = showArrow
self.showPrefixes = showPrefixes
self.values = values
self.totalValue = totalValue
self.tapAction = tapAction
self.hideAction = hideAction
}
}

View File

@ -70,10 +70,11 @@ enum BaseConstants {
}()
}
public class BaseChartController: GColorModeContainer {
public class BaseChartController: ChartThemeContainer {
//let performanceRenderer = PerformanceRenderer()
var initialChartsCollection: ChartsCollection
var isZoomed: Bool = false
public var isZoomable: Bool = true
var chartTitle: String = ""
@ -148,7 +149,7 @@ public class BaseChartController: GColorModeContainer {
fatalError("Abstract")
}
public func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
fatalError("Abstract")
}
@ -180,7 +181,7 @@ public class BaseChartController: GColorModeContainer {
fatalError("Abstract")
}
public func apply(colorMode: GColorMode, animated: Bool) {
public func apply(theme: ChartTheme, animated: Bool) {
}
}

View File

@ -18,15 +18,16 @@ enum GeneralChartComponentConstants {
static let defaultZoomedRangeLength = CGFloat(TimeInterval.day)
}
class GeneralChartComponentController: GColorModeContainer {
class GeneralChartComponentController: ChartThemeContainer {
var chartsCollection: ChartsCollection = ChartsCollection.blank
var chartVisibility: [Bool] = []
var lastChartInteractionPoint: CGPoint = .zero
var isChartInteractionBegun: Bool = false
var isChartInteracting: Bool = false
let isZoomed: Bool
var isZoomable = true
var colorMode: GColorMode = .day
var theme: ChartTheme = ChartTheme.defaultDayTheme
var totalHorizontalRange: ClosedRange<CGFloat> = BaseConstants.defaultRange
var totalVerticalRange: ClosedRange<CGFloat> = BaseConstants.defaultRange
var initialHorizontalRange: ClosedRange<CGFloat> = BaseConstants.defaultRange
@ -214,8 +215,8 @@ class GeneralChartComponentController: GColorModeContainer {
var setDetailsViewModel: ((ChartDetailsViewModel, Bool) -> Void)?
var chartRangePagingClosure: ((Bool, CGFloat) -> Void)? // isEnabled, PageSize
func apply(colorMode: GColorMode, animated: Bool) {
self.colorMode = colorMode
func apply(theme: ChartTheme, animated: Bool) {
self.theme = theme
}
// MARK: - Helpers
@ -310,12 +311,15 @@ class GeneralChartComponentController: GColorModeContainer {
dateString = BaseConstants.headerMediumRangeFormatter.string(from: closestDate)
}
let viewModel = ChartDetailsViewModel(title: dateString,
showArrow: !self.isZoomed,
showArrow: self.isZoomable && !self.isZoomed,
showPrefixes: false,
values: values,
totalValue: nil,
tapAction: { [weak self] in
self?.zoomInOnDateClosure?(closestDate) })
self?.zoomInOnDateClosure?(closestDate) },
hideAction: { [weak self] in
})
return viewModel
}

View File

@ -78,7 +78,7 @@ public class BaseLinesChartController: BaseChartController {
isChartInteractionBegun = false
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
}
@ -114,11 +114,14 @@ public class BaseLinesChartController: BaseChartController {
dateString = BaseConstants.headerMediumRangeFormatter.string(from: closestDate)
}
let viewModel = ChartDetailsViewModel(title: dateString,
showArrow: !self.isZoomed,
showArrow: self.isZoomable && !self.isZoomed,
showPrefixes: false,
values: values,
totalValue: nil,
tapAction: { [weak self] in self?.didTapZoomIn(date: closestDate) })
tapAction: { [weak self] in self?.didTapZoomIn(date: closestDate) },
hideAction: { [weak self] in
self?.setDetailsChartVisibleClosure?(false, true)
})
return viewModel
}

View File

@ -176,7 +176,7 @@ public class GeneralLinesChartController: BaseLinesChartController {
return visibleCharts
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
cancelChartInteraction()
let horizontalRange = ClosedRange(uncheckedBounds:
@ -184,11 +184,11 @@ public class GeneralLinesChartController: BaseLinesChartController {
upper: totalHorizontalRange.lowerBound + rangeFraction.upperBound * totalHorizontalRange.distance))
zoomedChartRange = horizontalRange
updateChartRangeTitle(animated: true)
updateChartRangeTitle(animated: animated)
updateMainChartHorizontalRange(range: horizontalRange, animated: false)
updateHorizontalLimits(horizontalRange: horizontalRange, animated: true)
updateVerticalLimitsAndRange(horizontalRange: horizontalRange, animated: true)
updateHorizontalLimits(horizontalRange: horizontalRange, animated: animated)
updateVerticalLimitsAndRange(horizontalRange: horizontalRange, animated: animated)
}
func updateMainChartHorizontalRange(range: ClosedRange<CGFloat>, animated: Bool) {
@ -239,12 +239,12 @@ public class GeneralLinesChartController: BaseLinesChartController {
}
}
override public func apply(colorMode: GColorMode, animated: Bool) {
horizontalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.axisXColor = colorMode.chartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = colorMode.chartHelperLinesColor
lineBulletsRenderer.setInnerColor(colorMode.chartBackgroundColor, animated: animated)
verticalLineRenderer.linesColor = colorMode.chartStrongLinesColor
override public func apply(theme: ChartTheme, animated: Bool) {
horizontalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.axisXColor = theme.chartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = theme.chartHelperLinesColor
lineBulletsRenderer.setInnerColor(theme.chartBackgroundColor, animated: animated)
verticalLineRenderer.linesColor = theme.chartStrongLinesColor
}
}

View File

@ -199,7 +199,7 @@ public class TwoAxisLinesChartController: BaseLinesChartController {
self.setupChartCollection(chartsCollection: initialChartCollection, animated: true, isZoomed: false)
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
cancelChartInteraction()
let horizontalRange = ClosedRange(uncheckedBounds:
@ -297,14 +297,14 @@ public class TwoAxisLinesChartController: BaseLinesChartController {
}
}
public override func apply(colorMode: GColorMode, animated: Bool) {
horizontalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalLineRenderer.linesColor = colorMode.chartStrongLinesColor
public override func apply(theme: ChartTheme, animated: Bool) {
horizontalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalLineRenderer.linesColor = theme.chartStrongLinesColor
for controller in graphControllers {
controller.verticalScalesRenderer.horizontalLinesColor = colorMode.chartHelperLinesColor
controller.lineBulletsRenderer.setInnerColor(colorMode.chartBackgroundColor, animated: animated)
controller.verticalScalesRenderer.axisXColor = colorMode.chartStrongLinesColor
controller.verticalScalesRenderer.horizontalLinesColor = theme.chartHelperLinesColor
controller.lineBulletsRenderer.setInnerColor(theme.chartBackgroundColor, animated: animated)
controller.verticalScalesRenderer.axisXColor = theme.chartStrongLinesColor
}
}
}

View File

@ -151,13 +151,16 @@ class PercentChartComponentController: GeneralChartComponentController {
dateString = BaseConstants.headerMediumRangeFormatter.string(from: closestDate)
}
let viewModel = ChartDetailsViewModel(title: dateString,
showArrow: !self.isZoomed,
showArrow: self.isZoomable && !self.isZoomed,
showPrefixes: true,
values: values,
totalValue: nil,
tapAction: { [weak self] in
self?.hideDetailsView(animated: true)
self?.zoomInOnDateClosure?(closestDate) })
self?.zoomInOnDateClosure?(closestDate) },
hideAction: { [weak self] in
self?.hideDetailsView(animated: true)
})
return viewModel
}
@ -188,13 +191,13 @@ class PercentChartComponentController: GeneralChartComponentController {
verticalLineRenderer.isEnabled = false
}
override func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
override func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
horizontalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.axisXColor = colorMode.barChartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = colorMode.barChartStrongLinesColor
verticalLineRenderer.linesColor = colorMode.chartStrongLinesColor
horizontalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.axisXColor = theme.barChartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = theme.barChartStrongLinesColor
verticalLineRenderer.linesColor = theme.chartStrongLinesColor
}
}

View File

@ -281,7 +281,7 @@ public class PercentPieChartController: BaseChartController {
})
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
if isZoomed {
return pieController.chartRangeFractionDidUpdated(rangeFraction)
} else {
@ -289,11 +289,11 @@ public class PercentPieChartController: BaseChartController {
}
}
public override func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
public override func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
pieController.apply(colorMode: colorMode, animated: animated)
percentController.apply(colorMode: colorMode, animated: animated)
transitionRenderer.backgroundColor = colorMode.chartBackgroundColor
pieController.apply(theme: theme, animated: animated)
percentController.apply(theme: theme, animated: animated)
transitionRenderer.backgroundColor = theme.chartBackgroundColor
}
}

View File

@ -156,7 +156,8 @@ class PieChartComponentController: GeneralChartComponentController {
color: pieItem.color,
visible: true)],
totalValue: nil,
tapAction: nil)
tapAction: nil,
hideAction: nil)
return viewModel
}

View File

@ -226,19 +226,19 @@ class BarsComponentController: GeneralChartComponentController {
mainBarsRenderer.setSelectedIndex(nil, animated: animated)
}
override func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
override func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
horizontalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.axisXColor = colorMode.barChartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = colorMode.barChartStrongLinesColor
mainBarsRenderer.update(backgroundColor: colorMode.chartBackgroundColor, animated: false)
previewBarsChartRenderer.update(backgroundColor: colorMode.chartBackgroundColor, animated: false)
horizontalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.axisXColor = theme.barChartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = theme.barChartStrongLinesColor
mainBarsRenderer.update(backgroundColor: theme.chartBackgroundColor, animated: false)
previewBarsChartRenderer.update(backgroundColor: theme.chartBackgroundColor, animated: false)
secondVerticalScalesRenderer?.labelsColor = colorMode.chartLabelsColor
secondVerticalScalesRenderer?.axisXColor = colorMode.barChartStrongLinesColor
secondVerticalScalesRenderer?.horizontalLinesColor = colorMode.barChartStrongLinesColor
secondVerticalScalesRenderer?.labelsColor = theme.chartLabelsColor
secondVerticalScalesRenderer?.axisXColor = theme.barChartStrongLinesColor
secondVerticalScalesRenderer?.horizontalLinesColor = theme.barChartStrongLinesColor
}
override func updateChartRangeTitle(animated: Bool) {

View File

@ -235,7 +235,7 @@ public class DailyBarsChartController: BaseChartController {
switchToChart(chartsCollection: barsController.chartsCollection, isZoomed: false, animated: true)
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
if isZoomed {
return linesController.chartRangeFractionDidUpdated(rangeFraction)
} else {
@ -243,11 +243,11 @@ public class DailyBarsChartController: BaseChartController {
}
}
override public func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
override public func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
linesController.apply(colorMode: colorMode, animated: animated)
barsController.apply(colorMode: colorMode, animated: animated)
linesController.apply(theme: theme, animated: animated)
barsController.apply(theme: theme, animated: animated)
}
public override var drawChartVisibity: Bool {

View File

@ -202,14 +202,14 @@ class LinesComponentController: GeneralChartComponentController {
lineBulletsRenderer.isEnabled = false
}
override func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
override func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
horizontalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.labelsColor = colorMode.chartLabelsColor
verticalScalesRenderer.axisXColor = colorMode.chartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = colorMode.chartHelperLinesColor
lineBulletsRenderer.setInnerColor(colorMode.chartBackgroundColor, animated: animated)
verticalLineRenderer.linesColor = colorMode.chartStrongLinesColor
horizontalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.labelsColor = theme.chartLabelsColor
verticalScalesRenderer.axisXColor = theme.chartStrongLinesColor
verticalScalesRenderer.horizontalLinesColor = theme.chartHelperLinesColor
lineBulletsRenderer.setInnerColor(theme.chartBackgroundColor, animated: animated)
verticalLineRenderer.linesColor = theme.chartStrongLinesColor
}
}

View File

@ -17,6 +17,12 @@ public class StackedBarsChartController: BaseChartController {
let barsController: BarsComponentController
let zoomedBarsController: BarsComponentController
override public var isZoomable: Bool {
didSet {
barsController.isZoomable = self.isZoomable
}
}
override public init(chartsCollection: ChartsCollection) {
let horizontalScalesRenderer = HorizontalScalesRenderer()
let verticalScalesRenderer = VerticalScalesRenderer()
@ -235,7 +241,7 @@ public class StackedBarsChartController: BaseChartController {
switchToChart(chartsCollection: barsController.chartsCollection, isZoomed: false, animated: true)
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
if isZoomed {
return zoomedBarsController.chartRangeFractionDidUpdated(rangeFraction)
} else {
@ -243,10 +249,10 @@ public class StackedBarsChartController: BaseChartController {
}
}
public override func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
public override func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
zoomedBarsController.apply(colorMode: colorMode, animated: animated)
barsController.apply(colorMode: colorMode, animated: animated)
zoomedBarsController.apply(theme: theme, animated: animated)
barsController.apply(theme: theme, animated: animated)
}
}

View File

@ -235,7 +235,7 @@ public class StepBarsChartController: BaseChartController {
switchToChart(chartsCollection: barsController.chartsCollection, isZoomed: false, animated: true)
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool = true) {
if isZoomed {
return zoomedBarsController.chartRangeFractionDidUpdated(rangeFraction)
} else {
@ -243,11 +243,11 @@ public class StepBarsChartController: BaseChartController {
}
}
override public func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
override public func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
zoomedBarsController.apply(colorMode: colorMode, animated: animated)
barsController.apply(colorMode: colorMode, animated: animated)
zoomedBarsController.apply(theme: theme, animated: animated)
barsController.apply(theme: theme, animated: animated)
}
public override var drawChartVisibity: Bool {

View File

@ -200,11 +200,14 @@ public class StepBarsChartController2: BaseChartController {
dateString = BaseConstants.headerMediumRangeFormatter.string(from: closestDate)
}
let viewModel = ChartDetailsViewModel(title: dateString,
showArrow: !self.isZoomed,
showArrow: self.isZoomable && !self.isZoomed,
showPrefixes: false,
values: values,
totalValue: nil,
tapAction: { [weak self] in })
tapAction: { [weak self] in },
hideAction: { [weak self] in
self?.setDetailsChartVisibleClosure?(false, true)
})
return viewModel
}
@ -317,7 +320,7 @@ public class StepBarsChartController2: BaseChartController {
self.setupChartCollection(chartsCollection: self.initialChartCollection, animated: true, isZoomed: false)
}
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>) {
public override func updateChartRange(_ rangeFraction: ClosedRange<CGFloat>, animated: Bool) {
cancelChartInteraction()
let horizontalRange = ClosedRange(uncheckedBounds:
@ -360,15 +363,15 @@ public class StepBarsChartController2: BaseChartController {
}
}
override public func apply(colorMode: GColorMode, animated: Bool) {
super.apply(colorMode: colorMode, animated: animated)
override public func apply(theme: ChartTheme, animated: Bool) {
super.apply(theme: theme, animated: animated)
self.graphControllers.forEach { controller in
controller.verticalScalesRenderer.horizontalLinesColor = colorMode.chartHelperLinesColor
controller.lineBulletsRenderer.setInnerColor(colorMode.chartBackgroundColor, animated: animated)
controller.verticalScalesRenderer.axisXColor = colorMode.chartStrongLinesColor
controller.verticalScalesRenderer.horizontalLinesColor = theme.chartHelperLinesColor
controller.lineBulletsRenderer.setInnerColor(theme.chartBackgroundColor, animated: animated)
controller.verticalScalesRenderer.axisXColor = theme.chartStrongLinesColor
}
verticalLineRenderer.linesColor = colorMode.chartStrongLinesColor
verticalLineRenderer.linesColor = theme.chartStrongLinesColor
}
public override var drawChartVisibity: Bool {

View File

@ -13,21 +13,14 @@ import Cocoa
import UIKit
#endif
class ChartDetailsRenderer: BaseChartRenderer, GColorModeContainer {
class ChartDetailsRenderer: BaseChartRenderer, ChartThemeContainer {
private lazy var colorAnimator = AnimationController<CGFloat>(current: 1, refreshClosure: refreshClosure)
private var fromColorMode: GColorMode = .day
private var currentColorMode: GColorMode = .day
func apply(colorMode: GColorMode, animated: Bool) {
if currentColorMode != colorMode {
fromColorMode = currentColorMode
currentColorMode = colorMode
if animated {
colorAnimator.set(current: 0)
colorAnimator.animate(to: 1, duration: .defaultDuration)
} else {
colorAnimator.set(current: 1)
}
}
private var fromColorMode: ChartTheme = ChartTheme.defaultDayTheme
private var currentColorMode: ChartTheme = ChartTheme.defaultDayTheme
func apply(theme: ChartTheme, animated: Bool) {
fromColorMode = currentColorMode
currentColorMode = theme
colorAnimator.set(current: 1)
}
private var valuesAnimators: [AnimationController<CGFloat>] = []

View File

@ -23,173 +23,179 @@ public typealias GColor = NSColor
typealias NSEdgeInsets = UIEdgeInsets
#endif
public protocol GColorModeContainer {
func apply(colorMode: GColorMode, animated: Bool)
public protocol ChartThemeContainer {
func apply(theme: ChartTheme, animated: Bool)
}
public enum GColorMode {
case day
case night
}
extension GColorMode {
public var chartTitleColor: GColor { // Текст с датой на чарте
switch self {
case .day: return .black
case .night: return .white
}
}
public var actionButtonColor: GColor { // Кнопка Zoom Out/ Смена режима день/ночь
switch self {
case .day: return GColor(red: 53/255.0, green: 120/255.0, blue: 246/255.0, alpha: 1.0)
case .night: return GColor(red: 84/255.0, green: 164/255.0, blue: 247/255.0, alpha: 1.0)
}
}
public var tableBackgroundColor: GColor {
switch self {
case .day: return GColor(red: 239/255.0, green: 239/255.0, blue: 244/255.0, alpha: 1.0)
case .night: return GColor(red: 24/255.0, green: 34/255.0, blue: 45/255.0, alpha: 1.0)
}
public class ChartTheme {
public let chartTitleColor: GColor
public let actionButtonColor: GColor
public let tableBackgroundColor: GColor
public let chartBackgroundColor: GColor
public let tableSeparatorColor: GColor
public let chartLabelsColor: GColor
public let chartHelperLinesColor: GColor
public let chartStrongLinesColor: GColor
public let barChartStrongLinesColor: GColor
public let chartDetailsTextColor: GColor
public let chartDetailsArrowColor: GColor
public let chartDetailsViewColor: GColor
public let descriptionActionColor: GColor
public let rangeViewFrameColor: GColor
public let rangeViewTintColor: GColor
public let rangeViewMarkerColor: GColor
public init(chartTitleColor: GColor, actionButtonColor: GColor, tableBackgroundColor: GColor, chartBackgroundColor: GColor, tableSeparatorColor: GColor, chartLabelsColor: GColor, chartHelperLinesColor: GColor, chartStrongLinesColor: GColor, barChartStrongLinesColor: GColor, chartDetailsTextColor: GColor, chartDetailsArrowColor: GColor, chartDetailsViewColor: GColor, descriptionActionColor: GColor, rangeViewFrameColor: GColor, rangeViewTintColor: GColor, rangeViewMarkerColor: GColor) {
self.chartTitleColor = chartTitleColor
self.actionButtonColor = actionButtonColor
self.tableBackgroundColor = tableBackgroundColor
self.chartBackgroundColor = chartBackgroundColor
self.tableSeparatorColor = tableSeparatorColor
self.chartLabelsColor = chartLabelsColor
self.chartHelperLinesColor = chartHelperLinesColor
self.chartStrongLinesColor = chartStrongLinesColor
self.barChartStrongLinesColor = barChartStrongLinesColor
self.chartDetailsTextColor = chartDetailsTextColor
self.chartDetailsArrowColor = chartDetailsArrowColor
self.chartDetailsViewColor = chartDetailsViewColor
self.descriptionActionColor = descriptionActionColor
self.rangeViewFrameColor = rangeViewFrameColor
self.rangeViewTintColor = rangeViewTintColor
self.rangeViewMarkerColor = rangeViewMarkerColor
}
public var chartBackgroundColor: GColor {
switch self {
case .day: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
case .night: return GColor(red: 34/255.0, green: 47/255.0, blue: 63/255.0, alpha: 1.0)
}
}
public static var defaultDayTheme = ChartTheme(chartTitleColor: GColor.black, actionButtonColor: GColor(red: 53/255.0, green: 120/255.0, blue: 246/255.0, alpha: 1.0), tableBackgroundColor: GColor(red: 239/255.0, green: 239/255.0, blue: 244/255.0, alpha: 1.0), chartBackgroundColor: GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0), tableSeparatorColor: GColor(red: 200/255.0, green: 199/255.0, blue: 204/255.0, alpha: 1.0), chartLabelsColor: GColor(red: 37/255.0, green: 37/255.0, blue: 41/255.0, alpha: 0.5), chartHelperLinesColor: GColor(red: 24/255.0, green: 45/255.0, blue: 59/255.0, alpha: 0.1), chartStrongLinesColor: GColor(red: 24/255.0, green: 45/255.0, blue: 59/255.0, alpha: 0.35), barChartStrongLinesColor: GColor(red: 37/255.0, green: 37/255.0, blue: 41/255.0, alpha: 0.2), chartDetailsTextColor: GColor(red: 109/255.0, green: 109/255.0, blue: 114/255.0, alpha: 1.0), chartDetailsArrowColor: GColor(red: 197/255.0, green: 199/255.0, blue: 205/255.0, alpha: 1.0), chartDetailsViewColor: GColor(red: 245/255.0, green: 245/255.0, blue: 251/255.0, alpha: 1.0), descriptionActionColor: GColor(red: 1/255.0, green: 125/255.0, blue: 229/255.0, alpha: 1.0), rangeViewFrameColor: GColor(red: 202/255.0, green: 212/255.0, blue: 222/255.0, alpha: 1.0), rangeViewTintColor: GColor(red: 239/255.0, green: 239/255.0, blue: 244/255.0, alpha: 0.5), rangeViewMarkerColor: GColor.white)
public var sectionTitleColor: GColor {
switch self {
case .day: return GColor(red: 109/255.0, green: 109/255.0, blue: 114/255.0, alpha: 1.0)
case .night: return GColor(red: 133/255.0, green: 150/255.0, blue: 171/255.0, alpha: 1.0)
}
}
public var tableSeparatorColor: GColor {
switch self {
case .day: return GColor(red: 200/255.0, green: 199/255.0, blue: 204/255.0, alpha: 1.0)
case .night: return GColor(red: 18/255.0, green: 26/255.0, blue: 35/255.0, alpha: 1.0)
}
}
public var chartLabelsColor: GColor {
switch self {
case .day: return GColor(red: 37/255.0, green: 37/255.0, blue: 41/255.0, alpha: 0.5)
case .night: return GColor(red: 186/255.0, green: 204/255.0, blue: 225/255.0, alpha: 0.6)
}
}
public var chartHelperLinesColor: GColor {
switch self {
case .day: return GColor(red: 24/255.0, green: 45/255.0, blue: 59/255.0, alpha: 0.1)
case .night: return GColor(red: 133/255.0, green: 150/255.0, blue: 171/255.0, alpha: 0.20)
}
}
public var chartStrongLinesColor: GColor {
switch self {
case .day: return GColor(red: 24/255.0, green: 45/255.0, blue: 59/255.0, alpha: 0.35)
case .night: return GColor(red: 186/255.0, green: 204/255.0, blue: 225/255.0, alpha: 0.45)
}
}
public var barChartStrongLinesColor: GColor {
switch self {
case .day: return GColor(red: 37/255.0, green: 37/255.0, blue: 41/255.0, alpha: 0.2)
case .night: return GColor(red: 186/255.0, green: 204/255.0, blue: 225/255.0, alpha: 0.45)
}
}
public var chartDetailsTextColor: GColor {
switch self {
case .day: return GColor(red: 109/255.0, green: 109/255.0, blue: 114/255.0, alpha: 1.0)
case .night: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
}
}
public var chartDetailsArrowColor: GColor {
switch self {
case .day: return GColor(red: 197/255.0, green: 199/255.0, blue: 205/255.0, alpha: 1.0)
case .night: return GColor(red: 76/255.0, green: 84/255.0, blue: 96/255.0, alpha: 1.0)
}
}
public var chartDetailsViewColor: GColor {
switch self {
case .day: return GColor(red: 245/255.0, green: 245/255.0, blue: 251/255.0, alpha: 1.0)
case .night: return GColor(red: 25/255.0, green: 35/255.0, blue: 47/255.0, alpha: 1.0)
}
}
public var descriptionChatNameColor: GColor {
switch self {
case .day: return .black
case .night: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
}
}
public var descriptionActionColor: GColor {
switch self {
case .day: return GColor(red: 1/255.0, green: 125/255.0, blue: 229/255.0, alpha: 1.0)
case .night: return GColor(red: 24/255.0, green: 145/255.0, blue: 255/255.0, alpha: 1.0)
}
}
public var rangeViewBackgroundColor: GColor {
switch self {
case .day: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
case .night: return GColor(red: 34/255.0, green: 47/255.0, blue: 63/255.0, alpha: 1.0)
}
}
public var rangeViewFrameColor: GColor {
switch self {
case .day: return GColor(red: 202/255.0, green: 212/255.0, blue: 222/255.0, alpha: 1.0)
case .night: return GColor(red: 53/255.0, green: 70/255.0, blue: 89/255.0, alpha: 1.0)
}
}
public var rangeViewTintColor: GColor {
switch self {
case .day: return GColor(red: 239/255.0, green: 239/255.0, blue: 244/255.0, alpha: 0.5)
case .night: return GColor(red: 24/255.0, green: 34/255.0, blue: 45/255.0, alpha: 0.5)
}
}
public var rangeViewMarkerColor: GColor {
switch self {
case .day: return GColor.white
case .night: return GColor.white
}
}
public var viewTintColor: GColor {
switch self {
case .day: return .black
case .night: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
}
}
// public var actionButtonColor: GColor { // Кнопка Zoom Out/ Смена режима день/ночь
// switch self {
// case .day: return GColor(red: 53/255.0, green: 120/255.0, blue: 246/255.0, alpha: 1.0)
// case .night: return GColor(red: 84/255.0, green: 164/255.0, blue: 247/255.0, alpha: 1.0)
// }
// }
//
// public var tableBackgroundColor: GColor {
// switch self {
// case .day: return GColor(red: 239/255.0, green: 239/255.0, blue: 244/255.0, alpha: 1.0)
// case .night: return GColor(red: 24/255.0, green: 34/255.0, blue: 45/255.0, alpha: 1.0)
// }
// }
//
// public var chartBackgroundColor: GColor {
// switch self {
// case .day: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
// case .night: return GColor(red: 34/255.0, green: 47/255.0, blue: 63/255.0, alpha: 1.0)
// }
// }
//
// public var tableSeparatorColor: GColor {
// switch self {
// case .day: return GColor(red: 200/255.0, green: 199/255.0, blue: 204/255.0, alpha: 1.0)
// case .night: return GColor(red: 18/255.0, green: 26/255.0, blue: 35/255.0, alpha: 1.0)
// }
// }
//
// public var chartLabelsColor: GColor {
// switch self {
// case .day: return GColor(red: 37/255.0, green: 37/255.0, blue: 41/255.0, alpha: 0.5)
// case .night: return GColor(red: 186/255.0, green: 204/255.0, blue: 225/255.0, alpha: 0.6)
// }
// }
//
// public var chartHelperLinesColor: GColor {
// switch self {
// case .day: return GColor(red: 24/255.0, green: 45/255.0, blue: 59/255.0, alpha: 0.1)
// case .night: return GColor(red: 133/255.0, green: 150/255.0, blue: 171/255.0, alpha: 0.20)
// }
// }
//
// public var chartStrongLinesColor: GColor {
// switch self {
// case .day: return GColor(red: 24/255.0, green: 45/255.0, blue: 59/255.0, alpha: 0.35)
// case .night: return GColor(red: 186/255.0, green: 204/255.0, blue: 225/255.0, alpha: 0.45)
// }
// }
//
// public var barChartStrongLinesColor: GColor {
// switch self {
// case .day: return GColor(red: 37/255.0, green: 37/255.0, blue: 41/255.0, alpha: 0.2)
// case .night: return GColor(red: 186/255.0, green: 204/255.0, blue: 225/255.0, alpha: 0.45)
// }
// }
//
// public var chartDetailsTextColor: GColor {
// switch self {
// case .day: return GColor(red: 109/255.0, green: 109/255.0, blue: 114/255.0, alpha: 1.0)
// case .night: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
// }
// }
//
// public var chartDetailsArrowColor: GColor {
// switch self {
// case .day: return GColor(red: 197/255.0, green: 199/255.0, blue: 205/255.0, alpha: 1.0)
// case .night: return GColor(red: 76/255.0, green: 84/255.0, blue: 96/255.0, alpha: 1.0)
// }
// }
//
// public var chartDetailsViewColor: GColor {
// switch self {
// case .day: return GColor(red: 245/255.0, green: 245/255.0, blue: 251/255.0, alpha: 1.0)
// case .night: return GColor(red: 25/255.0, green: 35/255.0, blue: 47/255.0, alpha: 1.0)
// }
// }
//
//
// public var descriptionActionColor: GColor {
// switch self {
// case .day: return GColor(red: 1/255.0, green: 125/255.0, blue: 229/255.0, alpha: 1.0)
// case .night: return GColor(red: 24/255.0, green: 145/255.0, blue: 255/255.0, alpha: 1.0)
// }
// }
//
// public var rangeViewBackgroundColor: GColor {
// switch self {
// case .day: return GColor(red: 254/255.0, green: 254/255.0, blue: 254/255.0, alpha: 1.0)
// case .night: return GColor(red: 34/255.0, green: 47/255.0, blue: 63/255.0, alpha: 1.0)
// }
// }
//
// public var rangeViewFrameColor: GColor {
// switch self {
// case .day: return GColor(red: 202/255.0, green: 212/255.0, blue: 222/255.0, alpha: 1.0)
// case .night: return GColor(red: 53/255.0, green: 70/255.0, blue: 89/255.0, alpha: 1.0)
// }
// }
//
// public var rangeViewTintColor: GColor {
// switch self {
// case .day: return GColor(red: 239/255.0, green: 239/255.0, blue: 244/255.0, alpha: 0.5)
// case .night: return GColor(red: 24/255.0, green: 34/255.0, blue: 45/255.0, alpha: 0.5)
// }
// }
//
// public var rangeViewMarkerColor: GColor {
// switch self {
// case .day: return GColor.white
// case .night: return GColor.white
// }
// }
//
//
public var rangeCropImage: GImage? {
switch self {
case .day:
// case .day:
let image = GImage(named: "selection_frame_light")
#if os(macOS)
image?.resizingMode = .stretch
image?.capInsets = NSEdgeInsets(top: 15, left: 15, bottom: 15, right: 15)
#endif
return image
case .night:
let image = GImage(named: "selection_frame_dark")
#if os(macOS)
image?.resizingMode = .stretch
image?.capInsets = NSEdgeInsets(top: 15, left: 15, bottom: 15, right: 15)
#endif
return image
}
// case .night:
// let image = GImage(named: "selection_frame_dark")
// #if os(macOS)
// image?.resizingMode = .stretch
// image?.capInsets = NSEdgeInsets(top: 15, left: 15, bottom: 15, right: 15)
// #endif
// return image
}
}

View File

@ -15,20 +15,21 @@ private let verticalMargins: CGFloat = 8
private var labelHeight: CGFloat = 18
private var margin: CGFloat = 10
private var prefixLabelWidth: CGFloat = 27
private var textLabelWidth: CGFloat = 80
private var textLabelWidth: CGFloat = 96
private var valueLabelWidth: CGFloat = 65
class ChartDetailsView: UIControl {
let titleLabel = UILabel()
let arrowView = UIImageView()
let activityIndicator = UIActivityIndicatorView()
let arrowButton = UIButton()
var prefixViews: [UILabel] = []
var labelsViews: [UILabel] = []
var valuesViews: [UILabel] = []
private var viewModel: ChartDetailsViewModel?
private var colorMode: GColorMode = .day
private var theme: ChartTheme = ChartTheme.defaultDayTheme
override init(frame: CGRect) {
super.init(frame: frame)
@ -36,13 +37,16 @@ class ChartDetailsView: UIControl {
layer.cornerRadius = cornerRadius
clipsToBounds = true
addTarget(self, action: #selector(didTap), for: .touchUpInside)
addTarget(self, action: #selector(didTapWhole), for: .touchUpInside)
titleLabel.font = UIFont.systemFont(ofSize: 12, weight: .bold)
arrowView.image = UIImage(bundleImageName: "Chart/arrow_right")
arrowView.contentMode = .scaleAspectFill
arrowButton.addTarget(self, action: #selector(didTap), for: .touchUpInside)
addSubview(titleLabel)
addSubview(arrowView)
addSubview(arrowButton)
}
required init?(coder aDecoder: NSCoder) {
@ -66,6 +70,8 @@ class ChartDetailsView: UIControl {
}
let labelsCount: Int = viewModel.values.count + ((viewModel.totalValue == nil) ? 0 : 1)
arrowButton.frame = CGRect(x: 0.0, y: 0.0, width: width, height: 30.0)
setLabelsCount(array: &prefixViews,
count: viewModel.showPrefixes ? labelsCount : 0,
font: UIFont.systemFont(ofSize: 12, weight: .bold))
@ -82,14 +88,14 @@ class ChartDetailsView: UIControl {
var x: CGFloat = margin
if viewModel.showPrefixes {
let prefixLabel = self.prefixViews[index]
prefixLabel.textColor = self.colorMode.chartDetailsTextColor
prefixLabel.textColor = self.theme.chartDetailsTextColor
prefixLabel.setText(value.prefix, animated: false)
prefixLabel.frame = CGRect(x: x, y: y, width: prefixLabelWidth, height: labelHeight)
x += prefixLabelWidth + margin
prefixLabel.alpha = value.visible ? 1 : 0
}
let titleLabel = self.labelsViews[index]
titleLabel.setTextColor(self.colorMode.chartDetailsTextColor, animated: false)
titleLabel.setTextColor(self.theme.chartDetailsTextColor, animated: false)
titleLabel.setText(value.title, animated: false)
titleLabel.frame = CGRect(x: x, y: y, width: textLabelWidth, height: labelHeight)
titleLabel.alpha = value.visible ? 1 : 0
@ -109,21 +115,21 @@ class ChartDetailsView: UIControl {
var x: CGFloat = margin
if viewModel.showPrefixes {
let prefixLabel = self.prefixViews[viewModel.values.count]
prefixLabel.textColor = self.colorMode.chartDetailsTextColor
prefixLabel.textColor = self.theme.chartDetailsTextColor
prefixLabel.setText(value.prefix, animated: false)
prefixLabel.frame = CGRect(x: x, y: y, width: prefixLabelWidth, height: labelHeight)
prefixLabel.alpha = value.visible ? 1 : 0
x += prefixLabelWidth + margin
}
let titleLabel = self.labelsViews[viewModel.values.count]
titleLabel.setTextColor(self.colorMode.chartDetailsTextColor, animated: false)
titleLabel.setTextColor(self.theme.chartDetailsTextColor, animated: false)
titleLabel.setText(value.title, animated: false)
titleLabel.frame = CGRect(x: x, y: y, width: textLabelWidth, height: labelHeight)
titleLabel.alpha = value.visible ? 1 : 0
x += textLabelWidth
let valueLabel = self.valuesViews[viewModel.values.count]
valueLabel.setTextColor(self.colorMode.chartDetailsTextColor, animated: false)
valueLabel.setTextColor(self.theme.chartDetailsTextColor, animated: false)
valueLabel.setText(value.value, animated: false)
valueLabel.frame = CGRect(x: x, y: y, width: valueLabelWidth, height: labelHeight)
valueLabel.alpha = value.visible ? 1 : 0
@ -154,6 +160,10 @@ class ChartDetailsView: UIControl {
viewModel?.tapAction?()
}
@objc private func didTapWhole() {
viewModel?.hideAction?()
}
func setLabelsCount(array: inout [UILabel],
count: Int,
font: UIFont,
@ -172,16 +182,16 @@ class ChartDetailsView: UIControl {
}
}
extension ChartDetailsView: GColorModeContainer {
func apply(colorMode: GColorMode, animated: Bool) {
self.colorMode = colorMode
self.titleLabel.setTextColor(colorMode.chartDetailsTextColor, animated: animated)
extension ChartDetailsView: ChartThemeContainer {
func apply(theme: ChartTheme, animated: Bool) {
self.theme = theme
self.titleLabel.setTextColor(theme.chartDetailsTextColor, animated: animated)
if let viewModel = self.viewModel {
self.setup(viewModel: viewModel, animated: animated)
}
UIView.perform(animated: animated) {
self.arrowView.tintColor = colorMode.chartDetailsArrowColor
self.backgroundColor = colorMode.chartDetailsViewColor
self.arrowView.tintColor = theme.chartDetailsArrowColor
self.backgroundColor = theme.chartDetailsViewColor
}
}
}

View File

@ -5,6 +5,7 @@ import Display
import AsyncDisplayKit
import AppBundle
import GraphCore
import TelegramPresentationData
public enum ChartType {
case lines
@ -14,6 +15,15 @@ public enum ChartType {
case step
}
public extension ChartTheme {
convenience init(presentationTheme: PresentationTheme) {
let tableBackgroundColor = UIColor(rgb: 0xefeff4)
let rangeViewTintColor = UIColor(rgb: 0xefeff4)
self.init(chartTitleColor: presentationTheme.list.itemPrimaryTextColor, actionButtonColor: presentationTheme.list.itemAccentColor, tableBackgroundColor: tableBackgroundColor, chartBackgroundColor: presentationTheme.list.itemBlocksBackgroundColor, tableSeparatorColor: presentationTheme.list.itemSecondaryTextColor, chartLabelsColor: presentationTheme.list.itemSecondaryTextColor, chartHelperLinesColor: presentationTheme.list.itemSecondaryTextColor, chartStrongLinesColor: presentationTheme.list.itemSecondaryTextColor, barChartStrongLinesColor: presentationTheme.list.itemSecondaryTextColor, chartDetailsTextColor: presentationTheme.list.itemSecondaryTextColor, chartDetailsArrowColor: presentationTheme.list.itemSecondaryTextColor, chartDetailsViewColor: presentationTheme.list.itemSecondaryTextColor, descriptionActionColor: presentationTheme.list.itemSecondaryTextColor, rangeViewFrameColor: presentationTheme.list.itemSecondaryTextColor, rangeViewTintColor: rangeViewTintColor, rangeViewMarkerColor: UIColor.white)
}
}
public final class ChartNode: ASDisplayNode {
private var chartView: ChartStackSection {
return self.view as! ChartStackSection
@ -33,6 +43,16 @@ public final class ChartNode: ASDisplayNode {
self.view.disablesInteractiveTransitionGestureRecognizer = true
}
public func setupTheme(_ theme: ChartTheme) {
self.chartView.apply(theme: ChartTheme.defaultDayTheme, animated: false)
}
public override func layout() {
super.layout()
self.chartView.setNeedsDisplay()
}
public func setup(_ data: String, type: ChartType, getDetailsData: @escaping (Date, @escaping (String?) -> Void) -> Void) {
if let data = data.data(using: .utf8) {
ChartsDataManager.readChart(data: data, extraCopiesCount: 0, sync: true, success: { [weak self] collection in
@ -40,19 +60,22 @@ public final class ChartNode: ASDisplayNode {
switch type {
case .lines:
controller = GeneralLinesChartController(chartsCollection: collection)
controller.isZoomable = false
case .twoAxis:
controller = TwoAxisLinesChartController(chartsCollection: collection)
controller.isZoomable = false
case .pie:
controller = PercentPieChartController(chartsCollection: collection)
case .bars:
controller = StackedBarsChartController(chartsCollection: collection)
controller.isZoomable = false
case .step:
controller = StepBarsChartController(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
ChartsDataManager.readChart(data: data, extraCopiesCount: 0, sync: true, success: { collection in
Queue.mainQueue().async {
completion(collection)
}
@ -66,7 +89,6 @@ public final class ChartNode: ASDisplayNode {
}
if let strongSelf = self {
strongSelf.chartView.setup(controller: controller, title: "")
strongSelf.chartView.apply(colorMode: .day, animated: false)
}
}) { error in

View File

@ -22,7 +22,7 @@ private class LeftAlignedIconButton: UIButton {
}
}
class ChartStackSection: UIView, GColorModeContainer {
class ChartStackSection: UIView, ChartThemeContainer {
var chartView: ChartView
var rangeView: RangeChartView
var visibilityView: ChartVisibilityView
@ -81,37 +81,37 @@ class ChartStackSection: UIView, GColorModeContainer {
backButton.setVisible(false, animated: false)
}
func apply(colorMode: GColorMode, animated: Bool) {
func apply(theme: ChartTheme, animated: Bool) {
UIView.perform(animated: animated && self.isVisibleInWindow) {
self.backgroundColor = colorMode.tableBackgroundColor
self.backgroundColor = theme.tableBackgroundColor
self.sectionContainerView.backgroundColor = colorMode.chartBackgroundColor
self.rangeView.backgroundColor = colorMode.chartBackgroundColor
self.visibilityView.backgroundColor = colorMode.chartBackgroundColor
self.sectionContainerView.backgroundColor = theme.chartBackgroundColor
self.rangeView.backgroundColor = theme.chartBackgroundColor
self.visibilityView.backgroundColor = theme.chartBackgroundColor
self.backButton.tintColor = colorMode.actionButtonColor
self.backButton.setTitleColor(colorMode.actionButtonColor, for: .normal)
self.backButton.tintColor = theme.actionButtonColor
self.backButton.setTitleColor(theme.actionButtonColor, for: .normal)
for separator in self.separators {
separator.backgroundColor = colorMode.tableSeparatorColor
separator.backgroundColor = theme.tableSeparatorColor
}
}
if rangeView.isVisibleInWindow || chartView.isVisibleInWindow {
chartView.loadDetailsViewIfNeeded()
chartView.apply(colorMode: colorMode, animated: animated && chartView.isVisibleInWindow)
controller.apply(colorMode: colorMode, animated: animated)
rangeView.apply(colorMode: colorMode, animated: animated && rangeView.isVisibleInWindow)
chartView.apply(theme: theme, animated: animated && chartView.isVisibleInWindow)
controller.apply(theme: theme, animated: animated)
rangeView.apply(theme: theme, animated: animated && rangeView.isVisibleInWindow)
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval.random(in: 0...0.1)) {
self.chartView.loadDetailsViewIfNeeded()
self.controller.apply(colorMode: colorMode, animated: false)
self.chartView.apply(colorMode: colorMode, animated: false)
self.rangeView.apply(colorMode: colorMode, animated: false)
self.controller.apply(theme: theme, animated: false)
self.chartView.apply(theme: theme, animated: false)
self.rangeView.apply(theme: theme, animated: false)
}
}
self.titleLabel.setTextColor(colorMode.chartTitleColor, animated: animated && titleLabel.isVisibleInWindow)
self.titleLabel.setTextColor(theme.chartTitleColor, animated: animated && titleLabel.isVisibleInWindow)
}
@objc private func didTapBackButton() {
@ -147,10 +147,10 @@ class ChartStackSection: UIView, GColorModeContainer {
let bounds = self.bounds
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.sectionContainerView.frame = CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: 750.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: 42.0))
self.visibilityView.frame = CGRect(origin: CGPoint(x: 0.0, y: 308.0), size: CGSize(width: bounds.width, height: 222.0))
self.visibilityView.frame = CGRect(origin: CGPoint(x: 0.0, y: 308.0), size: CGSize(width: bounds.width, height: 350.0))
self.backButton.frame = CGRect(x: 0.0, y: 0.0, width: 96.0, height: 38.0)
}
@ -214,9 +214,9 @@ class ChartStackSection: UIView, GColorModeContainer {
controller.initializeChart()
updateToolViews(animated: false)
// rangeView.setRange(0.8...1.0, animated: false)
rangeView.setRange(0.8...1.0, animated: false)
// TimeInterval.animationDurationMultipler = 0.00001
// controller.updateChartRange(0.8...1.0)
controller.updateChartRange(0.8...1.0, animated: false)
// TimeInterval.animationDurationMultipler = 1.0
}
}

View File

@ -162,8 +162,8 @@ class ChartView: UIControl {
}
extension ChartView: GColorModeContainer {
func apply(colorMode: GColorMode, animated: Bool) {
detailsView?.apply(colorMode: colorMode, animated: animated && (detailsView?.isVisibleInWindow ?? false))
extension ChartView: ChartThemeContainer {
func apply(theme: ChartTheme, animated: Bool) {
detailsView?.apply(theme: theme, animated: animated && (detailsView?.isVisibleInWindow ?? false))
}
}

View File

@ -8,6 +8,7 @@
import UIKit
import GraphCore
import Display
private enum Constants {
static let itemHeight: CGFloat = 30
@ -38,10 +39,18 @@ class ChartVisibilityView: UIView {
for (index, item) in items.enumerated() {
let view = selectionViews[index]
view.item = item
view.tapClosure = { [weak self] in
view.tapClosure = { [weak self, weak view] in
guard let self = self else { return }
self.setItemSelected(!self.selectedItems[index], at: index, animated: true)
self.notifyItemSelection()
let selected = !self.selectedItems[index]
let selectedItemsCount = self.selectedItems.filter { $0 }.count
if selectedItemsCount == 1 && !selected {
view?.layer.addShakeAnimation()
} else {
self.setItemSelected(selected, at: index, animated: true)
self.notifyItemSelection()
}
}
view.longTapClosure = { [weak self] in
@ -138,11 +147,11 @@ class ChartVisibilityView: UIView {
}
}
extension ChartVisibilityView: GColorModeContainer {
func apply(colorMode: GColorMode, animated: Bool) {
extension ChartVisibilityView: ChartThemeContainer {
func apply(theme: ChartTheme, animated: Bool) {
UIView.perform(animated: animated) {
self.backgroundColor = colorMode.chartBackgroundColor
self.tintColor = colorMode.descriptionActionColor
self.backgroundColor = theme.chartBackgroundColor
self.tintColor = theme.descriptionActionColor
}
}
}

View File

@ -48,6 +48,8 @@ class RangeChartView: UIControl {
private var selectedMarkerInitialLocation: CGPoint?
private var isBoundCropHighlighted: Bool = false
private var isRangePagingEnabled: Bool = false
private var targetTapLocation: CGPoint?
public let chartView = ChartView()
@ -154,6 +156,8 @@ class RangeChartView: UIControl {
selectedMarkerInitialLocation = point
isBoundCropHighlighted = true
} else {
targetTapLocation = point
selectedMarkerHorizontalOffset = cropFrameView.frame.width / 2.0
selectedMarker = nil
selectedMarkerInitialLocation = nil
return
@ -175,11 +179,23 @@ class RangeChartView: UIControl {
self._isTracking = true
}
targetTapLocation = nil
sendActions(for: .valueChanged)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard isEnabled else { return }
if let point = targetTapLocation {
let horizontalPosition = point.x - selectedMarkerHorizontalOffset
let fraction = fractionFor(offsetX: horizontalPosition)
updateMarkerOffset(.center, fraction: fraction)
sendActions(for: .touchUpInside)
self.targetTapLocation = nil
return
}
guard let selectedMarker = selectedMarker else {
touchedOutsideClosure?()
return
@ -204,6 +220,7 @@ class RangeChartView: UIControl {
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
self.targetTapLocation = nil
self.selectedMarker = nil
self.selectedMarkerInitialLocation = nil
self.isBoundCropHighlighted = false
@ -292,11 +309,11 @@ private extension RangeChartView {
}
}
extension RangeChartView: GColorModeContainer {
func apply(colorMode: GColorMode, animated: Bool) {
extension RangeChartView: ChartThemeContainer {
func apply(theme: ChartTheme, animated: Bool) {
let colusre = {
self.lowerBoundTintView.backgroundColor = colorMode.rangeViewTintColor
self.upperBoundTintView.backgroundColor = colorMode.rangeViewTintColor
self.lowerBoundTintView.backgroundColor = theme.rangeViewTintColor
self.upperBoundTintView.backgroundColor = theme.rangeViewTintColor
}

View File

@ -22,6 +22,7 @@ static_library(
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/MergeLists:MergeLists",
"//submodules/PhotoResources:PhotoResources",
"//submodules/GraphCore:GraphCore",
"//submodules/GraphUI:GraphUI",
],
frameworks = [

View File

@ -23,6 +23,7 @@ swift_library(
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/MergeLists:MergeLists",
"//submodules/PhotoResources:PhotoResources",
"//submodules/GraphCore:GraphCore",
"//submodules/GraphUI:GraphUI",
],
visibility = [

View File

@ -8,7 +8,9 @@ import SyncCore
import TelegramPresentationData
import ItemListUI
import PresentationDataUtils
import GraphCore
import GraphUI
import ActivityIndicator
class StatsGraphItem: ListViewItem, ItemListItem {
let presentationData: ItemListPresentationData
@ -72,6 +74,7 @@ class StatsGraphItemNode: ListViewItemNode {
private let maskNode: ASImageNode
let chartNode: ChartNode
private let activityIndicator: ActivityIndicator
private var item: StatsGraphItem?
@ -89,12 +92,15 @@ class StatsGraphItemNode: ListViewItemNode {
self.bottomStripeNode.isLayerBacked = true
self.chartNode = ChartNode()
self.activityIndicator = ActivityIndicator(type: ActivityIndicatorType.custom(.black, 16.0, 2.0, false))
self.activityIndicator.isHidden = true
super.init(layerBacked: false, dynamicBounce: false)
self.clipsToBounds = true
self.addSubnode(self.chartNode)
self.addSubnode(self.activityIndicator)
}
override func didLoad() {
@ -201,21 +207,36 @@ class StatsGraphItemNode: ListViewItemNode {
strongSelf.bottomStripeNode.isHidden = hasCorners
}
strongSelf.chartNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: layout.size.width - leftInset - rightInset, height: 500.0))
strongSelf.chartNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 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)))
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
strongSelf.activityIndicator.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - 16.0) / 2.0), y: floor((layout.size.height - 16.0) / 2.0)), size: CGSize(width: 16.0, height: 16.0))
}
if let updatedGraph = updatedGraph, case let .Loaded(_, data) = updatedGraph {
strongSelf.chartNode.setup(data, type: item.type, getDetailsData: { [weak self] date, completion in
if let strongSelf = self, let item = strongSelf.item {
item.getDetailsData?(date, completion)
}
})
strongSelf.activityIndicator.type = .custom(item.presentationData.theme.list.itemSecondaryTextColor, 16.0, 2.0, false)
if let updatedGraph = updatedGraph {
if case let .Loaded(_, data) = updatedGraph {
strongSelf.chartNode.setup(data, type: item.type, getDetailsData: { [weak self] date, completion in
if let strongSelf = self, let item = strongSelf.item {
item.getDetailsData?(date, completion)
}
})
strongSelf.activityIndicator.isHidden = true
strongSelf.chartNode.isHidden = false
} else if case .OnDemand = updatedGraph {
strongSelf.activityIndicator.isHidden = false
strongSelf.chartNode.isHidden = true
}
}
if let updatedTheme = updatedTheme {
strongSelf.chartNode.setupTheme(ChartTheme(presentationTheme: updatedTheme))
}
}
})

View File

@ -147,7 +147,6 @@ class StatsOverviewItemNode: ListViewItemNode {
let leftInset = params.leftInset
let rightInset: CGFloat = params.rightInset
var updatedTheme: PresentationTheme?
var updatedGraph: ChannelStatsGraph?
if currentItem?.presentationData.theme !== item.presentationData.theme {
updatedTheme = item.presentationData.theme
@ -214,16 +213,23 @@ class StatsOverviewItemNode: ListViewItemNode {
let itemBackgroundColor: UIColor
let itemSeparatorColor: UIColor
let height: CGFloat
if item.stats.viewsPerPost.current.isZero && item.stats.sharesPerPost.current.isZero {
height = 64.0
} else {
height = 120.0
}
switch item.style {
case .plain:
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
contentSize = CGSize(width: params.width, height: 120.0)
contentSize = CGSize(width: params.width, height: height)
insets = itemListNeighborsPlainInsets(neighbors)
case .blocks:
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
contentSize = CGSize(width: params.width, height: 120.0)
contentSize = CGSize(width: params.width, height: height)
insets = itemListNeighborsGroupedInsets(neighbors)
}

View File

@ -41,7 +41,7 @@ public enum ChannelStatsGraph: Equatable {
switch self {
case let .OnDemand(token):
return token
case let .Loaded(token, data):
case let .Loaded(token, _):
return token
default:
return nil

View File

@ -53,7 +53,7 @@ private class ChatHistoryListSelectionRecognizer: UIPanGestureRecognizer {
let translation = location.offsetBy(dx: -self.initialLocation.x, dy: -self.initialLocation.y)
if self.recognized == nil {
if (fabs(translation.y) >= selectionGestureActivationThreshold) {
if (abs(translation.y) >= selectionGestureActivationThreshold) {
self.recognized = true
}
}
@ -1709,7 +1709,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
var resultMessages: [Message]?
self.forEachVisibleItemNode { itemNode in
if resultMessages == nil, let itemNode = itemNode as? ListViewItemNode, itemNode.frame.contains(point) {
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item as? ChatMessageItem {
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item {
switch item.content {
case let .message(message, _, _ , _):
resultMessages = [message]
@ -1750,6 +1750,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
self.selectionScrollSkipUpdate = false
case .possible:
break
@unknown default:
fatalError()
}
}
@ -1825,7 +1827,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
if let strongSelf = self, let delta = strongSelf.selectionScrollDelta {
let distance: CGFloat = 15.0 * min(1.0, 0.15 + abs(delta * delta))
let direction: ListViewScrollDirection = delta > 0.0 ? .up : .down
strongSelf.scrollWithDirection(direction, distance: distance)
let _ = strongSelf.scrollWithDirection(direction, distance: distance)
if let location = strongSelf.selectionLastLocation {
if !strongSelf.selectionScrollSkipUpdate {

View File

@ -245,11 +245,14 @@ enum ManagedDiceAnimationState: Equatable {
final class ManagedDiceAnimationNode: ManagedAnimationNode {
private let context: AccountContext
private let emojis: [TelegramMediaFile]
private var diceState: ManagedDiceAnimationState = .rolling
private let disposable = MetaDisposable()
init(context: AccountContext) {
init(context: AccountContext, emojis: [TelegramMediaFile]) {
self.context = context
self.emojis = emojis
super.init(size: CGSize(width: 136.0, height: 136.0))
@ -268,6 +271,16 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode {
case .rolling:
switch diceState {
case let .value(value):
// self.disposable.set(freeMediaFileInteractiveFetched(account: item.context.account, fileReference: .standalone(media: emojiFile)).start())
//
// return chatMessageAnimationData(postbox: self.account.postbox, resource: self.resource, fitzModifier: self.fitzModifier, width: width, height: height, synchronousLoad: false)
// |> filter { data in
// return data.size != 0
// }
// |> map { data -> (String, Bool) in
// return (data.path, data.complete)
// }
self.trackTo(item: ManagedAnimationItem(source: .local("DiceRolling"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0), duration: 0.3))
case .rolling:
break

View File

@ -8,18 +8,18 @@ private enum ID3Tag: CaseIterable {
var header: Data {
switch self {
case .v2:
return Data(bytes: [ 0x49, 0x44, 0x33, 0x02, 0x00 ])
return Data([ 0x49, 0x44, 0x33, 0x02, 0x00 ])
case .v3:
return Data(bytes: [ 0x49, 0x44, 0x33, 0x03, 0x00 ])
return Data([ 0x49, 0x44, 0x33, 0x03, 0x00 ])
}
}
var artworkHeader: Data {
switch self {
case .v2:
return Data(bytes: [ 0x50, 0x49, 0x43 ])
return Data([ 0x50, 0x49, 0x43 ])
case .v3:
return Data(bytes: [ 0x41, 0x50, 0x49, 0x43 ])
return Data([ 0x41, 0x50, 0x49, 0x43 ])
}
}
@ -58,7 +58,7 @@ private let artOffset = 10
private let v2FrameOffset: UInt32 = 6
private let v3FrameOffset: UInt32 = 10
private let tagEnding = Data(bytes: [ 0x00, 0x00, 0x00 ])
private let tagEnding = Data([ 0x00, 0x00, 0x00 ])
private enum ID3ArtworkFormat: CaseIterable {
case jpg
@ -67,9 +67,9 @@ private enum ID3ArtworkFormat: CaseIterable {
var magic: Data {
switch self {
case .jpg:
return Data(bytes: [ 0xff, 0xd8, 0xff ])
return Data([ 0xff, 0xd8, 0xff ])
case .png:
return Data(bytes: [ 0x89, 0x50, 0x4e, 0x47 ])
return Data([ 0x89, 0x50, 0x4e, 0x47 ])
}
}
}
@ -118,7 +118,7 @@ private class DataStream {
}
func upTo(_ marker: UInt8) -> Data? {
if let end = (self.position ..< self.data.count).index( where: { self.data[$0] == marker } ) {
if let end = (self.position ..< self.data.count).firstIndex( where: { self.data[$0] == marker } ) {
let upTo = self.next(end - self.position)
self.skip()
return upTo
@ -132,7 +132,7 @@ private class DataStream {
}
func skipThrough(_ marker: UInt8) {
if let end = (self.position ..< self.data.count).index( where: { self.data[$0] == marker } ) {
if let end = (self.position ..< self.data.count).firstIndex( where: { self.data[$0] == marker } ) {
self.position = end + 1
} else {
self.position = self.data.count

View File

@ -105,11 +105,8 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager {
return result
}
let autoNightModeTriggered = presentationData.autoNightModeTriggered ?? false
let autoNightModeTriggered = presentationData.autoNightModeTriggered
disposable.set(uploadSignal.start(next: { [weak self] status in
guard let strongSelf = self else {
return
}
if case let .complete(wallpaper) = status {
let updateWallpaper: (TelegramWallpaper) -> Void = { wallpaper in
if let resource = wallpaper.mainResource {