This commit is contained in:
2026-08-12 07:06:01 +07:00
parent 1025658518
commit 9bc96dbc2d
39 changed files with 1682 additions and 658 deletions
+123
View File
@@ -0,0 +1,123 @@
import SwiftUI
// MARK: - Палитра
/// Фирменные цвета Rapira из дизайн-макета.
enum RapiraPalette {
// Рост
static let accent = Color(red: 0.251, green: 0.835, blue: 0.216) // #40D537
static let accentEdge = Color(red: 0.051, green: 0.157, blue: 0.082) // #0D2815
static let accentHalo = Color(red: 0.075, green: 0.214, blue: 0.106) // #13371B
static let accentText = Color(red: 0.277, green: 0.895, blue: 0.239) // #47E43D
// Падение зеркальная красная гамма.
static let negative = Color(red: 0.949, green: 0.267, blue: 0.267) // #F24444
static let negativeEdge = Color(red: 0.161, green: 0.051, blue: 0.051)
static let negativeHalo = Color(red: 0.220, green: 0.075, blue: 0.075)
static let negativeText = Color(red: 0.965, green: 0.310, blue: 0.290)
// Фон и разделители
static let backgroundTint = Color(red: 0.157, green: 0.161, blue: 0.169) // #28292B
static let divider = Color.white.opacity(0.06)
// MARK: Выбор цвета по направлению движения
static func line(_ positive: Bool) -> Color { positive ? accent : negative }
static func lineEdge(_ positive: Bool) -> Color { positive ? accentEdge : negativeEdge }
static func halo(_ positive: Bool) -> Color { positive ? accentHalo : negativeHalo }
static func stat(_ positive: Bool) -> Color { positive ? accentText : negativeText }
}
// MARK: - Фон
/// Радиальный фон из макета: широкая подсветка от верхней кромки, уходящая
/// в чёрный на 61%. В исходнике это эллипс с радиусами 995×512 отсюда
/// растяжение по горизонтали.
struct RapiraBackground: View {
var body: some View {
GeometryReader { geo in
RadialGradient(
gradient: Gradient(stops: [
.init(color: RapiraPalette.backgroundTint, location: 0),
.init(color: .black, location: 0.612),
]),
center: UnitPoint(x: 0.5, y: 0),
startRadius: 0,
endRadius: geo.size.height
)
.frame(width: geo.size.width, height: geo.size.height)
.scaleEffect(x: 1.94, y: 1, anchor: .top)
.clipped()
}
}
}
// MARK: - Логотип
/// Знак Rapira две «ленты», кривые сняты с фирменного SVG
/// (34.7 × 32 в исходных координатах).
struct RapiraMark: View {
var size: CGFloat = 22
var body: some View {
ZStack {
MarkShape(part: .upper).fill(.white)
MarkShape(part: .lower).fill(.white.opacity(0.6))
}
.frame(width: size * (34.736 / 32.0), height: size)
}
private struct MarkShape: Shape {
enum Part { case upper, lower }
let part: Part
func path(in rect: CGRect) -> Path {
let sx = rect.width / 34.736
let sy = rect.height / 32.0
func p(_ x: CGFloat, _ y: CGFloat) -> CGPoint {
CGPoint(x: rect.minX + x * sx, y: rect.minY + y * sy)
}
var path = Path()
switch part {
case .upper:
path.move(to: p(15.545, 0))
path.addCurve(to: p(7.406, 6.217), control1: p(12.037, 0), control2: p(8.393, 2.783))
path.addLine(to: p(0, 31.996))
path.addLine(to: p(6.942, 31.996))
path.addLine(to: p(12.094, 14.062))
path.addCurve(to: p(20.233, 7.845), control1: p(13.081, 10.629), control2: p(16.725, 7.845))
path.addLine(to: p(32.482, 7.845))
path.addLine(to: p(34.736, 0))
case .lower:
path.move(to: p(31.083, 12.803))
path.addLine(to: p(27.464, 25.713))
path.addCurve(to: p(19.432, 32.0), control1: p(26.490, 29.186), control2: p(22.895, 32.0))
path.addLine(to: p(11.886, 32.0))
path.addLine(to: p(15.506, 19.090))
path.addCurve(to: p(23.537, 12.803), control1: p(16.479, 15.618), control2: p(20.075, 12.803))
path.addLine(to: p(31.083, 12.803))
}
path.closeSubpath()
return path
}
}
}
// MARK: - Цвета монет
/// Фолбэк-цвета для иконок монет, когда SVG с CDN недоступен.
enum CoinPalette {
static func color(for currency: String) -> Color {
switch currency {
case "BTC": .orange
case "ETH": Color(red: 0.39, green: 0.49, blue: 0.94)
case "SOL": Color(red: 0.56, green: 0.25, blue: 0.95)
case "BNB": Color(red: 0.96, green: 0.72, blue: 0.04)
case "XRP": Color(red: 0.14, green: 0.14, blue: 0.14)
case "TON": Color(red: 0.04, green: 0.65, blue: 0.93)
case "USDT": Color(red: 0.149, green: 0.631, blue: 0.482)
default: Color(red: 0.55, green: 0.55, blue: 0.60)
}
}
}