Polish native mac app shell

This commit is contained in:
saymrwulf 2026-04-27 21:41:35 +02:00
parent dae66daa60
commit f6ffb2ffc4

View file

@ -1,11 +1,16 @@
import AppKit
import SwiftUI
@main
struct BraiinsRatchetApp: App {
init() {
NSApplication.shared.applicationIconImage = AppIconFactory.makeIcon()
}
var body: some Scene {
WindowGroup {
ContentView()
.frame(minWidth: 980, minHeight: 680)
.frame(minWidth: 1120, minHeight: 760)
}
.windowStyle(.hiddenTitleBar)
}
@ -22,19 +27,26 @@ struct ContentView: View {
ZStack {
LinearGradient(
colors: [
Color(red: 0.05, green: 0.07, blue: 0.08),
Color(red: 0.08, green: 0.14, blue: 0.15),
Color(red: 0.17, green: 0.20, blue: 0.17)
Color(red: 0.02, green: 0.05, blue: 0.06),
Color(red: 0.04, green: 0.14, blue: 0.15),
Color(red: 0.20, green: 0.24, blue: 0.18)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()
VStack(alignment: .leading, spacing: 22) {
header
controls
manualExposureControls
atmosphericShapes
HStack(alignment: .top, spacing: 22) {
VStack(alignment: .leading, spacing: 20) {
header
statusDeck
controls
manualExposureControls
}
.frame(width: 390)
outputPanel
}
.padding(30)
@ -46,6 +58,18 @@ struct ContentView: View {
private var header: some View {
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 10) {
Image(nsImage: AppIconFactory.makeIcon(size: 38))
.resizable()
.frame(width: 38, height: 38)
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
Text("Real-money monitor")
.font(.system(size: 13, weight: .black, design: .rounded))
.foregroundStyle(.black.opacity(0.72))
.padding(.horizontal, 10)
.padding(.vertical, 6)
.background(Color(red: 0.68, green: 0.96, blue: 0.82), in: Capsule())
}
Text("Braiins Ratchet")
.font(.system(size: 44, weight: .black, design: .rounded))
.foregroundStyle(.white)
@ -55,8 +79,60 @@ struct ContentView: View {
}
}
private var atmosphericShapes: some View {
ZStack {
Circle()
.fill(Color(red: 0.52, green: 0.95, blue: 0.72).opacity(0.18))
.frame(width: 420, height: 420)
.blur(radius: 70)
.offset(x: -360, y: -240)
Circle()
.fill(Color(red: 0.95, green: 0.67, blue: 0.33).opacity(0.14))
.frame(width: 360, height: 360)
.blur(radius: 80)
.offset(x: 430, y: 260)
RoundedRectangle(cornerRadius: 80, style: .continuous)
.stroke(.white.opacity(0.06), lineWidth: 1)
.frame(width: 780, height: 460)
.rotationEffect(.degrees(-12))
.offset(x: 280, y: -130)
}
.ignoresSafeArea()
}
private var statusDeck: some View {
VStack(spacing: 12) {
statusCard(title: "Lifecycle", value: "Durable", detail: "SQLite-backed resume after reboot")
statusCard(title: "Execution", value: "Manual", detail: "No owner-token order placement")
statusCard(title: "Exposure", value: "Tracked", detail: "Record long Braiins positions")
}
}
private func statusCard(title: String, value: String, detail: String) -> some View {
HStack {
VStack(alignment: .leading, spacing: 4) {
Text(title.uppercased())
.font(.system(size: 10, weight: .black, design: .rounded))
.foregroundStyle(.white.opacity(0.48))
Text(value)
.font(.system(size: 21, weight: .heavy, design: .rounded))
.foregroundStyle(.white)
Text(detail)
.font(.system(size: 12, weight: .medium, design: .rounded))
.foregroundStyle(.white.opacity(0.62))
}
Spacer()
}
.padding(16)
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 22, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: 22, style: .continuous)
.stroke(.white.opacity(0.13), lineWidth: 1)
)
}
private var controls: some View {
HStack(spacing: 12) {
VStack(alignment: .leading, spacing: 10) {
glassButton("Refresh Cockpit") {
Task { await runRatchet(["next"]) }
}
@ -85,7 +161,7 @@ struct ContentView: View {
Text("Manual Braiins Exposure")
.font(.system(size: 15, weight: .bold, design: .rounded))
.foregroundStyle(.white.opacity(0.82))
HStack(spacing: 10) {
VStack(spacing: 10) {
TextField("Description, e.g. Braiins order abc 0.0001 BTC", text: $manualDescription)
.textFieldStyle(.plain)
.padding(10)
@ -93,7 +169,6 @@ struct ContentView: View {
.foregroundStyle(.white)
TextField("Hours", text: $maturityHours)
.textFieldStyle(.plain)
.frame(width: 72)
.padding(10)
.background(.thinMaterial, in: RoundedRectangle(cornerRadius: 12))
.foregroundStyle(.white)
@ -114,7 +189,6 @@ struct ContentView: View {
}
TextField("ID", text: $closePositionId)
.textFieldStyle(.plain)
.frame(width: 54)
.padding(10)
.background(.thinMaterial, in: RoundedRectangle(cornerRadius: 12))
.foregroundStyle(.white)
@ -143,7 +217,7 @@ struct ContentView: View {
.foregroundStyle(.white.opacity(0.92))
.frame(maxWidth: .infinity, alignment: .leading)
.textSelection(.enabled)
.padding(22)
.padding(26)
}
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 28, style: .continuous))
.overlay(
@ -151,6 +225,7 @@ struct ContentView: View {
.stroke(.white.opacity(0.16), lineWidth: 1)
)
.shadow(color: .black.opacity(0.35), radius: 28, x: 0, y: 18)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
private func glassButton(_ title: String, action: @escaping () -> Void) -> some View {
@ -162,6 +237,7 @@ struct ContentView: View {
.padding(.vertical, 10)
}
.buttonStyle(.plain)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.thinMaterial, in: Capsule())
.overlay(Capsule().stroke(.white.opacity(0.18), lineWidth: 1))
.disabled(isRunning)
@ -177,6 +253,62 @@ struct ContentView: View {
}
}
enum AppIconFactory {
static func makeIcon(size: CGFloat = 512) -> NSImage {
let image = NSImage(size: NSSize(width: size, height: size))
image.lockFocus()
let rect = NSRect(x: 0, y: 0, width: size, height: size)
let corner = size * 0.22
let path = NSBezierPath(roundedRect: rect.insetBy(dx: size * 0.04, dy: size * 0.04), xRadius: corner, yRadius: corner)
NSGradient(
colors: [
NSColor(red: 0.03, green: 0.09, blue: 0.10, alpha: 1),
NSColor(red: 0.04, green: 0.27, blue: 0.26, alpha: 1),
NSColor(red: 0.55, green: 0.86, blue: 0.50, alpha: 1)
]
)?.draw(in: path, angle: -35)
NSColor.white.withAlphaComponent(0.18).setStroke()
path.lineWidth = size * 0.012
path.stroke()
let ringRect = rect.insetBy(dx: size * 0.18, dy: size * 0.18)
let ring = NSBezierPath(ovalIn: ringRect)
NSColor(red: 0.73, green: 1.0, blue: 0.78, alpha: 0.26).setFill()
ring.fill()
let inner = NSBezierPath(ovalIn: rect.insetBy(dx: size * 0.27, dy: size * 0.27))
NSColor(red: 0.02, green: 0.07, blue: 0.08, alpha: 0.85).setFill()
inner.fill()
let pick = NSBezierPath()
pick.move(to: NSPoint(x: size * 0.30, y: size * 0.30))
pick.line(to: NSPoint(x: size * 0.68, y: size * 0.70))
pick.line(to: NSPoint(x: size * 0.76, y: size * 0.62))
pick.line(to: NSPoint(x: size * 0.38, y: size * 0.22))
pick.close()
NSColor(red: 1.0, green: 0.77, blue: 0.35, alpha: 0.98).setFill()
pick.fill()
let spark = NSBezierPath()
spark.move(to: NSPoint(x: size * 0.55, y: size * 0.28))
spark.line(to: NSPoint(x: size * 0.62, y: size * 0.42))
spark.line(to: NSPoint(x: size * 0.76, y: size * 0.48))
spark.line(to: NSPoint(x: size * 0.62, y: size * 0.54))
spark.line(to: NSPoint(x: size * 0.55, y: size * 0.68))
spark.line(to: NSPoint(x: size * 0.48, y: size * 0.54))
spark.line(to: NSPoint(x: size * 0.34, y: size * 0.48))
spark.line(to: NSPoint(x: size * 0.48, y: size * 0.42))
spark.close()
NSColor(red: 0.76, green: 1.0, blue: 0.74, alpha: 0.95).setFill()
spark.fill()
image.unlockFocus()
return image
}
}
enum RatchetProcess {
static func run(arguments: [String], input: String? = nil) async -> String {
await Task.detached {