diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index fa1ec86e3..ed740fe04 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -25,12 +25,6 @@ 2A1FE47C2938BB2600784BF1 /* FollowedTagsViewModel+DiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A1FE47B2938BB2600784BF1 /* FollowedTagsViewModel+DiffableDataSource.swift */; }; 2A1FE47E2938C11200784BF1 /* Collection+IsNotEmpty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A1FE47D2938C11200784BF1 /* Collection+IsNotEmpty.swift */; }; 2A33062D2987DBFA001D4C51 /* FollowersCountHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33062C2987DBFA001D4C51 /* FollowersCountHistory.swift */; }; - 2A33063629880835001D4C51 /* Math.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33062F29880834001D4C51 /* Math.swift */; }; - 2A33063729880835001D4C51 /* DataRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33063029880834001D4C51 /* DataRepresentable.swift */; }; - 2A33063829880835001D4C51 /* LineChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33063229880834001D4C51 /* LineChart.swift */; }; - 2A33063929880835001D4C51 /* CurvedChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33063329880834001D4C51 /* CurvedChart.swift */; }; - 2A33063A29880835001D4C51 /* LightChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33063429880834001D4C51 /* LightChart.swift */; }; - 2A33063B29880835001D4C51 /* ChartType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33063529880834001D4C51 /* ChartType.swift */; }; 2A33AB662982C4AF008A7FB1 /* FollowersCountWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A33AB652982C4AF008A7FB1 /* FollowersCountWidgetView.swift */; }; 2A3F6FE3292ECB5E002E6DA7 /* FollowedTagsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A3F6FE2292ECB5E002E6DA7 /* FollowedTagsViewModel.swift */; }; 2A3F6FE5292F6E44002E6DA7 /* FollowedTagsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A3F6FE4292F6E44002E6DA7 /* FollowedTagsTableViewCell.swift */; }; @@ -60,6 +54,7 @@ 2A9D0666298C05A800BF38CB /* LatestFollowersWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A9D0665298C05A800BF38CB /* LatestFollowersWidgetView.swift */; }; 2A9D066F298D0FD100BF38CB /* MastodonSDKDynamic in Frameworks */ = {isa = PBXBuildFile; productRef = 2A9D066E298D0FD100BF38CB /* MastodonSDKDynamic */; }; 2AB12E4629362F27006BC925 /* DataSourceFacade+Translate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB12E4529362F27006BC925 /* DataSourceFacade+Translate.swift */; }; + 2AB5011B2992322500346092 /* LightChart in Frameworks */ = {isa = PBXBuildFile; productRef = 2AB5011A2992322500346092 /* LightChart */; }; 2AE202AA297FE10B00F66E55 /* WidgetExtension.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 2A72812C297EA9D7004138C5 /* WidgetExtension.intentdefinition */; }; 2AE202AC297FE19100F66E55 /* FollowersCountIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE202AB297FE19100F66E55 /* FollowersCountIntentHandler.swift */; }; 2AE202AD297FE1CD00F66E55 /* WidgetExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A72813E297EC762004138C5 /* WidgetExtension.swift */; }; @@ -618,12 +613,6 @@ 2A1FE47B2938BB2600784BF1 /* FollowedTagsViewModel+DiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowedTagsViewModel+DiffableDataSource.swift"; sourceTree = ""; }; 2A1FE47D2938C11200784BF1 /* Collection+IsNotEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+IsNotEmpty.swift"; sourceTree = ""; }; 2A33062C2987DBFA001D4C51 /* FollowersCountHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowersCountHistory.swift; sourceTree = ""; }; - 2A33062F29880834001D4C51 /* Math.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Math.swift; sourceTree = ""; }; - 2A33063029880834001D4C51 /* DataRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataRepresentable.swift; sourceTree = ""; }; - 2A33063229880834001D4C51 /* LineChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineChart.swift; sourceTree = ""; }; - 2A33063329880834001D4C51 /* CurvedChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurvedChart.swift; sourceTree = ""; }; - 2A33063429880834001D4C51 /* LightChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LightChart.swift; sourceTree = ""; }; - 2A33063529880834001D4C51 /* ChartType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartType.swift; sourceTree = ""; }; 2A33625329759B4200481A90 /* OpenInActionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OpenInActionExtension.entitlements; sourceTree = ""; }; 2A33AB652982C4AF008A7FB1 /* FollowersCountWidgetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowersCountWidgetView.swift; sourceTree = ""; }; 2A3F6FE2292ECB5E002E6DA7 /* FollowedTagsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowedTagsViewModel.swift; sourceTree = ""; }; @@ -1220,6 +1209,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2AB5011B2992322500346092 /* LightChart in Frameworks */, 2A9D066F298D0FD100BF38CB /* MastodonSDKDynamic in Frameworks */, 2A728124297EA9D7004138C5 /* SwiftUI.framework in Frameworks */, 2A728122297EA9D7004138C5 /* WidgetKit.framework in Frameworks */, @@ -1398,27 +1388,6 @@ path = Pods; sourceTree = ""; }; - 2A33062E29880834001D4C51 /* LightChart */ = { - isa = PBXGroup; - children = ( - 2A33063129880834001D4C51 /* Charts */, - 2A33062F29880834001D4C51 /* Math.swift */, - 2A33063029880834001D4C51 /* DataRepresentable.swift */, - 2A33063429880834001D4C51 /* LightChart.swift */, - 2A33063529880834001D4C51 /* ChartType.swift */, - ); - path = LightChart; - sourceTree = ""; - }; - 2A33063129880834001D4C51 /* Charts */ = { - isa = PBXGroup; - children = ( - 2A33063229880834001D4C51 /* LineChart.swift */, - 2A33063329880834001D4C51 /* CurvedChart.swift */, - ); - path = Charts; - sourceTree = ""; - }; 2A506CF2292CD83B00059C37 /* FollowedTags */ = { isa = PBXGroup; children = ( @@ -1445,7 +1414,6 @@ 2A728125297EA9D7004138C5 /* WidgetExtension */ = { isa = PBXGroup; children = ( - 2A33062E29880834001D4C51 /* LightChart */, 2A86A14329892700007F1062 /* Variants */, 2AE202A9297FDDF500F66E55 /* WidgetExtension.entitlements */, 2A72813E297EC762004138C5 /* WidgetExtension.swift */, @@ -3034,6 +3002,7 @@ name = WidgetExtension; packageProductDependencies = ( 2A9D066E298D0FD100BF38CB /* MastodonSDKDynamic */, + 2AB5011A2992322500346092 /* LightChart */, ); productName = WidgetExtensionExtension; productReference = 2A728120297EA9D7004138C5 /* WidgetExtension.appex */; @@ -3247,6 +3216,7 @@ ); mainGroup = DB427DC925BAA00100D1B89D; packageReferences = ( + 2AB501192992322500346092 /* XCRemoteSwiftPackageReference "LightChart" */, ); productRefGroup = DB427DD325BAA00100D1B89D /* Products */; projectDirPath = ""; @@ -3512,22 +3482,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2A33063729880835001D4C51 /* DataRepresentable.swift in Sources */, 2A33062D2987DBFA001D4C51 /* FollowersCountHistory.swift in Sources */, - 2A33063829880835001D4C51 /* LineChart.swift in Sources */, 2A9D0666298C05A800BF38CB /* LatestFollowersWidgetView.swift in Sources */, 2A728130297EA9D8004138C5 /* WidgetExtension.intentdefinition in Sources */, 2A86A14B2989326E007F1062 /* MultiFollowersCountWidgetView.swift in Sources */, 2A72813F297EC762004138C5 /* WidgetExtension.swift in Sources */, - 2A33063A29880835001D4C51 /* LightChart.swift in Sources */, - 2A33063B29880835001D4C51 /* ChartType.swift in Sources */, - 2A33063629880835001D4C51 /* Math.swift in Sources */, 2A86A14929892B3A007F1062 /* MultiFollowersCountWidget.swift in Sources */, 2A33AB662982C4AF008A7FB1 /* FollowersCountWidgetView.swift in Sources */, 2A9D0664298C048800BF38CB /* LatestFollowersWidget.swift in Sources */, 2A728127297EA9D7004138C5 /* WidgetExtensionBundle.swift in Sources */, 2A72812B297EA9D7004138C5 /* FollowersCountWidget.swift in Sources */, - 2A33063929880835001D4C51 /* CurvedChart.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5330,6 +5294,17 @@ }; /* End XCConfigurationList section */ +/* Begin XCRemoteSwiftPackageReference section */ + 2AB501192992322500346092 /* XCRemoteSwiftPackageReference "LightChart" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Bearologics/LightChart.git"; + requirement = { + branch = master; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + /* Begin XCSwiftPackageProductDependency section */ 2A90A156296EEE500026C155 /* MastodonSDKDynamic */ = { isa = XCSwiftPackageProductDependency; @@ -5339,6 +5314,11 @@ isa = XCSwiftPackageProductDependency; productName = MastodonSDKDynamic; }; + 2AB5011A2992322500346092 /* LightChart */ = { + isa = XCSwiftPackageProductDependency; + package = 2AB501192992322500346092 /* XCRemoteSwiftPackageReference "LightChart" */; + productName = LightChart; + }; 357FEEAE29523D470021C9DC /* MastodonSDKDynamic */ = { isa = XCSwiftPackageProductDependency; productName = MastodonSDKDynamic; diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index cd7395c7e..232ec9c87 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -73,6 +73,15 @@ "version": "4.2.2" } }, + { + "package": "LightChart", + "repositoryURL": "https://github.com/Bearologics/LightChart.git", + "state": { + "branch": "master", + "revision": "a7e724e9ec3cdcaa2d0840b95780e66b870dbf1e", + "version": null + } + }, { "package": "MetaTextKit", "repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git", diff --git a/WidgetExtension/LightChart/ChartType.swift b/WidgetExtension/LightChart/ChartType.swift deleted file mode 100644 index 1a83b0b4c..000000000 --- a/WidgetExtension/LightChart/ChartType.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// ChartType.swift -// -// -// Created by Alexey Pichukov on 19.08.2020. -// - -import SwiftUI - -public enum ChartType { - case line - case curved -} - -public enum ChartVisualType { - case outline(color: Color, lineWidth: CGFloat) - case filled(color: Color, lineWidth: CGFloat) - case customFilled(color: Color, lineWidth: CGFloat, fillGradient: LinearGradient) -} - -public enum CurrentValueLineType { - case none - case line(color: Color, lineWidth: CGFloat) - case dash(color: Color, lineWidth: CGFloat, dash: [CGFloat]) -} diff --git a/WidgetExtension/LightChart/Charts/CurvedChart.swift b/WidgetExtension/LightChart/Charts/CurvedChart.swift deleted file mode 100644 index c6df1d934..000000000 --- a/WidgetExtension/LightChart/Charts/CurvedChart.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// File.swift -// -// -// Created by Alexey Pichukov on 20.08.2020. -// - -import SwiftUI - -public struct CurvedChart: View { - - private let data: [Double] - private let frame: CGRect - private let offset: Double - private let type: ChartVisualType - private let currentValueLineType: CurrentValueLineType - private var points: [CGPoint] = [] - - /// Creates a new `CurvedChart` - /// - /// - Parameters: - /// - data: A data set that should be presented on the chart - /// - frame: A frame from the parent view - /// - visualType: A type of chart, `.outline` by default - /// - offset: An offset for the chart, a space below the chart in percentage (0 - 1) - /// For example `offset: 0.2` means that the chart will occupy 80% of the upper - /// part of the view - /// - currentValueLineType: A type of current value line (`none` for no line on chart) - public init(data: [Double], - frame: CGRect, - visualType: ChartVisualType = .outline(color: .red, lineWidth: 2), - offset: Double = 0, - currentValueLineType: CurrentValueLineType = .none) { - self.data = data - self.frame = frame - self.type = visualType - self.offset = offset - self.currentValueLineType = currentValueLineType - self.points = points(forData: data, - frame: frame, - offset: offset, - lineWidth: lineWidth(visualType: visualType)) - } - - public var body: some View { - ZStack { - chart - .rotationEffect(.degrees(180), anchor: .center) - .rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0)) - .drawingGroup() - line - .rotationEffect(.degrees(180), anchor: .center) - .rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0)) - .drawingGroup() - } - } - - private var chart: some View { - switch type { - case .outline(let color, let lineWidth): - return AnyView(curvedPath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineJoin: .round))) - case .filled(let color, let lineWidth): - return AnyView(ZStack { - curvedPathGradient(points: points) - .fill(LinearGradient( - gradient: .init(colors: [color.opacity(0.2), color.opacity(0.02)]), - startPoint: .init(x: 0.5, y: 1), - endPoint: .init(x: 0.5, y: 0) - )) - curvedPath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineJoin: .round)) - }) - case .customFilled(let color, let lineWidth, let fillGradient): - return AnyView(ZStack { - curvedPathGradient(points: points) - .fill(fillGradient) - curvedPath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineJoin: .round)) - }) - } - } - - private var line: some View { - switch currentValueLineType { - case .none: - return AnyView(EmptyView()) - case .line(let color, let lineWidth): - return AnyView( - currentValueLinePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth)) - ) - case .dash(let color, let lineWidth, let dash): - return AnyView( - currentValueLinePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, dash: dash)) - ) - } - } - - // MARK: private functions - - private func curvedPath(points: [CGPoint]) -> Path { - func mid(_ point1: CGPoint, _ point2: CGPoint) -> CGPoint { - return CGPoint(x: (point1.x + point2.x) / 2, y:(point1.y + point2.y) / 2) - } - - func control(_ point1: CGPoint, _ point2: CGPoint) -> CGPoint { - var controlPoint = mid(point1, point2) - let delta = abs(point2.y - controlPoint.y) - - if point1.y < point2.y { - controlPoint.y += delta - } else if point1.y > point2.y { - controlPoint.y -= delta - } - - return controlPoint - } - - var path = Path() - guard points.count > 1 else { - return path - } - - var startPoint = points[0] - path.move(to: startPoint) - - guard points.count > 2 else { - path.addLine(to: points[1]) - return path - } - - for i in 1.. Path { - var path = curvedPath(points: points) - guard let lastPoint = points.last else { - return path - } - path.addLine(to: CGPoint(x: lastPoint.x, y: 0)) - path.addLine(to: CGPoint(x: 0, y: 0)) - path.addLine(to: CGPoint(x: 0, y: points[0].y)) - - return path - } - - private func currentValueLinePath(points: [CGPoint]) -> Path { - var path = Path() - guard let lastPoint = points.last else { - return path - } - path.move(to: CGPoint(x: 0, y: lastPoint.y)) - path.addLine(to: lastPoint) - return path - } -} - -extension CurvedChart: DataRepresentable { } diff --git a/WidgetExtension/LightChart/Charts/LineChart.swift b/WidgetExtension/LightChart/Charts/LineChart.swift deleted file mode 100644 index b2a0a3ce9..000000000 --- a/WidgetExtension/LightChart/Charts/LineChart.swift +++ /dev/null @@ -1,138 +0,0 @@ -// -// LineChart.swift -// -// -// Created by Alexey Pichukov on 19.08.2020. -// - -import SwiftUI - -public struct LineChart: View { - - private let data: [Double] - private let frame: CGRect - private let offset: Double - private let type: ChartVisualType - private let currentValueLineType: CurrentValueLineType - private var points: [CGPoint] = [] - - /// Creates a new `LineChart` - /// - /// - Parameters: - /// - data: A data set that should be presented on the chart - /// - frame: A frame from the parent view - /// - visualType: A type of chart, `.outline` by default - /// - offset: An offset for the chart, a space below the chart in percentage (0 - 1) - /// For example `offset: 0.2` means that the chart will occupy 80% of the upper - /// part of the view - /// - currentValueLineType: A type of current value line (`none` for no line on chart) - public init(data: [Double], - frame: CGRect, - visualType: ChartVisualType = .outline(color: .red, lineWidth: 2), - offset: Double = 0, - currentValueLineType: CurrentValueLineType = .none) { - self.data = data - self.frame = frame - self.type = visualType - self.offset = offset - self.currentValueLineType = currentValueLineType - self.points = points(forData: data, - frame: frame, - offset: offset, - lineWidth: lineWidth(visualType: visualType)) - } - - public var body: some View { - ZStack { - chart - .rotationEffect(.degrees(180), anchor: .center) - .rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0)) - .drawingGroup() - line - .rotationEffect(.degrees(180), anchor: .center) - .rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0)) - .drawingGroup() - } - } - - private var chart: some View { - switch type { - case .outline(let color, let lineWidth): - return AnyView(linePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineJoin: .round))) - case .filled(let color, let lineWidth): - return AnyView(ZStack { - linePathGradient(points: points) - .fill(LinearGradient( - gradient: .init(colors: [color.opacity(0.2), color.opacity(0.02)]), - startPoint: .init(x: 0.5, y: 1), - endPoint: .init(x: 0.5, y: 0) - )) - linePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineJoin: .round)) - }) - case .customFilled(let color, let lineWidth, let fillGradient): - return AnyView(ZStack { - linePathGradient(points: points) - .fill(fillGradient) - linePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, lineJoin: .round)) - }) - } - } - - private var line: some View { - switch currentValueLineType { - case .none: - return AnyView(EmptyView()) - case .line(let color, let lineWidth): - return AnyView( - currentValueLinePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth)) - ) - case .dash(let color, let lineWidth, let dash): - return AnyView( - currentValueLinePath(points: points) - .stroke(color, style: StrokeStyle(lineWidth: lineWidth, dash: dash)) - ) - } - } - - // MARK: private functions - - private func linePath(points: [CGPoint]) -> Path { - var path = Path() - guard points.count > 1 else { - return path - } - path.move(to: points[0]) - for i in 1.. Path { - var path = linePath(points: points) - guard let lastPoint = points.last else { - return path - } - path.addLine(to: CGPoint(x: lastPoint.x, y: 0)) - path.addLine(to: CGPoint(x: 0, y: 0)) - path.addLine(to: CGPoint(x: 0, y: points[0].y)) - - return path - } - - private func currentValueLinePath(points: [CGPoint]) -> Path { - var path = Path() - guard let lastPoint = points.last else { - return path - } - path.move(to: CGPoint(x: 0, y: lastPoint.y)) - path.addLine(to: lastPoint) - return path - } -} - -extension LineChart: DataRepresentable { } diff --git a/WidgetExtension/LightChart/DataRepresentable.swift b/WidgetExtension/LightChart/DataRepresentable.swift deleted file mode 100644 index f585014db..000000000 --- a/WidgetExtension/LightChart/DataRepresentable.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// DataRepresentable.swift -// -// -// Created by Alexey Pichukov on 19.08.2020. -// -// Modified by Marcus Kida for Mastodon on 30.01.2023. - -import Foundation -import CoreGraphics - -protocol DataRepresentable { - func points(forData data: [Double], frame: CGRect, offset: Double, lineWidth: CGFloat) -> [CGPoint] - func lineWidth(visualType: ChartVisualType) -> CGFloat -} - -extension DataRepresentable { - - func points(forData data: [Double], frame: CGRect, offset: Double, lineWidth: CGFloat) -> [CGPoint] { - var vector = Math.stretchOut(Math.norm(data)) - if offset != 0 { - vector = Math.stretchIn(vector, offset: offset) - } - var points: [CGPoint] = [] - for i in 0.. CGFloat { - switch visualType { - case .outline(_, let lineWidth): - return lineWidth - case .filled(_, let lineWidth): - return lineWidth - case .customFilled(_, let lineWidth, _): - return lineWidth - } - } -} diff --git a/WidgetExtension/LightChart/LightChart.swift b/WidgetExtension/LightChart/LightChart.swift deleted file mode 100644 index e7b868730..000000000 --- a/WidgetExtension/LightChart/LightChart.swift +++ /dev/null @@ -1,52 +0,0 @@ -import SwiftUI - -public struct LightChartView: View { - - private let data: [Double] - private let type: ChartType - private let visualType: ChartVisualType - private let offset: Double - private let currentValueLineType: CurrentValueLineType - - public init(data: [Double], - type: ChartType = .line, - visualType: ChartVisualType = .outline(color: .red, lineWidth: 2), - offset: Double = 0, - currentValueLineType: CurrentValueLineType = .none) { - self.data = data - self.type = type - self.visualType = visualType - self.offset = offset - self.currentValueLineType = currentValueLineType - } - - public var body: some View { - GeometryReader { reader in - chart(withFrame: CGRect(x: 0, - y: 0, - width: reader.frame(in: .local).width , - height: reader.frame(in: .local).height)) - } - } - - private func chart(withFrame frame: CGRect) -> AnyView { - switch type { - case .line: - return AnyView( - LineChart(data: data, - frame: frame, - visualType: visualType, - offset: offset, - currentValueLineType: currentValueLineType) - ) - case .curved: - return AnyView( - CurvedChart(data: data, - frame: frame, - visualType: visualType, - offset: offset, - currentValueLineType: currentValueLineType) - ) - } - } -} diff --git a/WidgetExtension/LightChart/Math.swift b/WidgetExtension/LightChart/Math.swift deleted file mode 100644 index 837af4ceb..000000000 --- a/WidgetExtension/LightChart/Math.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// Math.swift -// -// -// Created by Alexey Pichukov on 19.08.2020. -// - -import Foundation -import CoreGraphics - -struct Math { - - static func norm(_ vector: [Double]) -> [Double] { - let norm = sqrt(Double(vector.reduce(0) { $0 + $1 * $1 })) - return norm == 0 ? vector : vector.map { $0 / norm } - } - - static func stretchOut(_ vector: [Double]) -> [Double] { - guard let min = vector.min(), - let rawMax = vector.max() else { - return vector - } - let max = rawMax - min - return vector.map { ($0 - min) / (max != 0 ? max : 1) } - } - - static func stretchIn(_ vector: [Double], offset: Double) -> [Double] { - guard let max = vector.max() else { - return vector - } - let newMax = max - offset - return vector.map { $0 * newMax + offset } - } -} diff --git a/WidgetExtension/Variants/FollowersCount/FollowersCountWidgetView.swift b/WidgetExtension/Variants/FollowersCount/FollowersCountWidgetView.swift index 288fcdcdc..2f5b93610 100644 --- a/WidgetExtension/Variants/FollowersCount/FollowersCountWidgetView.swift +++ b/WidgetExtension/Variants/FollowersCount/FollowersCountWidgetView.swift @@ -4,6 +4,7 @@ import SwiftUI import WidgetKit import MastodonAsset import MastodonLocalization +import LightChart struct FollowersCountWidgetView: View { private let followersHistory = FollowersCountHistory.shared