Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Fix #8136: Assets line chart V2 #8525

Merged
merged 2 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 45 additions & 72 deletions Sources/BraveWallet/Chart/LineChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ struct LineChartView<DataType: DataPoint, FillStyle: View>: View {
private struct LineChartShape: Shape {
/// The points, plotted relatively in a [0, 1] coordinate space
var points: [CGPoint]
/// To close shape for the background colour
var closed = false

var animatableData: LineChartAnimatableData {
get { .init(points: points.map(\.animatableData)) }
Expand Down Expand Up @@ -102,8 +104,12 @@ struct LineChartView<DataType: DataPoint, FillStyle: View>: View {
}
previousPoint = scaledPoint
}
if closed {
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
}
}
.strokedPath(StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round))
}
}

Expand Down Expand Up @@ -135,41 +141,6 @@ struct LineChartView<DataType: DataPoint, FillStyle: View>: View {
}

@State private var animationScale: CGFloat = 0

var finalDotView: some View {
let size: CGFloat = 14.0
return GeometryReader { proxy in
if numberOfColumns != points.count,
let scaledPoint = point(for: points.endIndex - 1, in: proxy.size) {
Circle()
.frame(width: size, height: size)
.background(
Circle()
.opacity((1.0 - Double(animationScale)) * 0.6)
// Can't scale effect to 0, causes bugs
.scaleEffect(max(animationScale, 0.1) * 2.5)
.animation(Animation.linear(duration: 2).repeatForever(autoreverses: false), value: animationScale)
)
.frame(maxWidth: .infinity, alignment: .leading)
.offset(x: scaledPoint.x - (size / 2.0), y: scaledPoint.y - (size / 2.0))
.transition(
.asymmetric(
insertion: AnyTransition.opacity.animation(Animation.linear(duration: 0.1).delay(0.2)),
removal: AnyTransition.opacity.animation(.linear(duration: 0.1))
)
)
.onAppear {
animationScale = 1
}
.onDisappear {
withAnimation(.none) {
animationScale = 0.0
}
}
}
}
}

@State private var dragValueSize: CGSize = .zero

private let dateFormatter = DateFormatter().then {
Expand Down Expand Up @@ -202,49 +173,51 @@ struct LineChartView<DataType: DataPoint, FillStyle: View>: View {
self.dragValueSize = $0
}
.font(.footnote)
fill
.mask(
LineChartShape(points: points)
.padding(.vertical, 14)
.drawingGroup() // Drawing group clips anything above it, so we need additional padding
.overlay(
finalDotView
.padding(.vertical, 14) // But drag calculations need to use the correct coordinates without padding)
)
)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.vertical, -14) // But drag calculations need to use the correct coordinates without padding
.overlay(
Group {
if let dragContext = dragContext {
ZStack {
fill
.clipShape(LineChartShape(points: points, closed: true))
LineChartShape(points: points)
.stroke(Color(.braveBlurpleTint), lineWidth: 2)
}
.frame(maxWidth: .infinity, alignment: .leading)
.overlay(
Group {
if let dragContext = dragContext {
ZStack {
Rectangle()
.fill(Color(.secondaryButtonTint))
.fill(Color(.braveBlurpleTint))
.frame(width: 2)
.frame(maxHeight: .infinity)
.padding(.vertical, -10)
.position(x: dragContext.location.x, y: dragContext.size.height / 2)
Circle()
.strokeBorder(Color(.braveBlurpleTint), style: .init(lineWidth: 2))
.frame(width: 12, height: 12)
.background(Color(.braveBackground).clipShape(Circle()))
.position(x: dragContext.location.x, y: dragContext.location.y)
}
}
)
.overlay(
GeometryReader { proxy in
Color.clear
.contentShape(Rectangle())
.gesture(
DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
dragContext = makeDragContext(
from: value.location.x,
in: proxy.size
)
selectedDataPoint = dragContext?.dataPoint
})
.onEnded({ _ in
dragContext = nil
selectedDataPoint = nil
})
)
})
}
)
.overlay(
GeometryReader { proxy in
Color.clear
.contentShape(Rectangle())
.gesture(
DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
dragContext = makeDragContext(
from: value.location.x,
in: proxy.size
)
selectedDataPoint = dragContext?.dataPoint
})
.onEnded({ _ in
dragContext = nil
selectedDataPoint = nil
})
)
})
}
.padding(.bottom, 16)
.padding(.top, 4)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct AssetDetailHeaderView: View {
@Environment(\.sizeCategory) private var sizeCategory
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@Environment(\.openURL) private var openWalletURL
@Environment(\.colorScheme) private var colourScheme
@State private var selectedCandle: BraveWallet.AssetTimePrice?

private var deltaText: some View {
Expand Down Expand Up @@ -228,8 +229,12 @@ struct AssetDetailHeaderView: View {
.shimmer(assetDetailStore.isLoadingPrice)
let data = assetDetailStore.priceHistory.isEmpty ? emptyData : assetDetailStore.priceHistory
LineChartView(data: data, numberOfColumns: data.count, selectedDataPoint: $selectedCandle) {
Color(.walletGreen)
.shimmer(assetDetailStore.isLoadingChart)
LinearGradient(
gradient: Gradient(colors: [Color(.braveBlurpleTint).opacity(colourScheme == .dark ? 0.5 : 0.2), .clear]),
startPoint: .top,
endPoint: .bottom
)
.shimmer(assetDetailStore.isLoadingChart)
}
.chartAccessibility(
title: String.localizedStringWithFormat(
Expand Down
10 changes: 8 additions & 2 deletions Sources/BraveWallet/Crypto/Portfolio/PortfolioHeaderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ struct PortfolioHeaderView: View {
@State private var selectedBalance: BalanceTimePrice?
@ObservedObject private var isShowingGraph = Preferences.Wallet.isShowingGraph
@ObservedObject private var isShowingBalances = Preferences.Wallet.isShowingBalances

@Environment(\.colorScheme) private var colourScheme

private var isShowingBackupBanner: Bool {
!keyringStore.isWalletBackedUp && !dismissedBackupBannerThisSession
Expand Down Expand Up @@ -167,8 +169,12 @@ struct PortfolioHeaderView: View {
timeframeSelector
let chartData = historicalBalances.isEmpty ? emptyBalanceData : historicalBalances
LineChartView(data: chartData, numberOfColumns: chartData.count, selectedDataPoint: $selectedBalance) {
LinearGradient(braveGradient: .lightGradient02)
.shimmer(isLoading)
LinearGradient(
gradient: Gradient(colors: [Color(.braveBlurpleTint).opacity(colourScheme == .dark ? 0.5 : 0.2), .clear]),
startPoint: .top,
endPoint: .bottom
)
.shimmer(isLoading)
}
.chartAccessibility(
title: Strings.Wallet.portfolioPageTitle,
Expand Down