mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Chart fixes
This commit is contained in:
parent
d774ecc5d5
commit
b9b5cb1b73
@ -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)?
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -193,7 +193,7 @@ class BarsComponentController: GeneralChartComponentController {
|
||||
color: .white,
|
||||
visible: visibleChartValues.count > 1)
|
||||
} else {
|
||||
viewModel.title = ""
|
||||
viewModel.title = "\(Int(closestDate.timeIntervalSince1970)):00"
|
||||
}
|
||||
return viewModel
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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()))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user