mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
23dd8becb9
Phase 1 — Page headers for the 9 non-mockup feature views: Skills, Gateway, Platforms, Personalities, QuickCommands, CredentialPools, Plugins, Webhooks, Profiles. Each now ships a ScarfPageHeader with title + subtitle + tokenized trailing actions (ScarfPrimary / Secondary / Ghost buttons), wrapped in .fixedSize so labels can't wrap at narrow widths. Outer .background(ScarfColor.backgroundPrimary). Phase 2 — Modal sheets: ModelPickerSheet, NousSignInSheet, RenameProjectSheet, MoveToFolderSheet, the five Templates sheets (TemplateInstall / TemplateConfig / TemplateExport / TemplateUninstall / ConfigEditorSheet), three MCPServer sheets (AddCustom / Editor / PresetPicker), AddServerSheet, ManageServersView, MissingServerView. .font(.headline) -> .scarfStyle(.headline); .buttonStyle(.borderedProminent) -> ScarfPrimaryButton(); raw text fields where touched -> ScarfTextField; cancel buttons -> ScarfGhostButton. Phase 3 — All 12 platform setup views (Discord / Email / Feishu / HomeAssistant / IMessage / Matrix / Mattermost / Signal / Slack / Telegram / Webhook / WhatsApp). Connect buttons swapped to ScarfPrimaryButton. Phase 4 — All 7 project dashboard widgets (Chart / List / Progress / Stat / Table / Text / Webview). .font(.caption) -> .scarfStyle(.caption); .background(.quaternary.opacity(0.5)) -> ScarfColor.backgroundSecondary; RoundedRectangle(cornerRadius: 8) -> ScarfRadius.lg. Phase 5 — Project sub-views: ProjectSessionsView, ProjectsSidebar, ProjectSlashCommandsView. Same token sweep. Phase 6 — Common chrome: - LoadingOverlay: .font(.callout/caption) -> .scarfStyle; secondary foreground -> ScarfColor.foregroundMuted; window-background -> ScarfColor.backgroundPrimary. - ServerSwitcherToolbar: status dot + label tokenized. - ConnectionStatusPill: status colors -> ScarfColor.success/warning/ danger; error sheet header -> ScarfPrimaryButton retry. Build green on both Mac (scarf) and iOS (scarf mobile) schemes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
85 lines
2.2 KiB
Swift
85 lines
2.2 KiB
Swift
import SwiftUI
|
|
import ScarfCore
|
|
import ScarfDesign
|
|
import Charts
|
|
|
|
// Flattened data point for Charts to avoid complex nested generic inference
|
|
private struct PlottablePoint: Identifiable {
|
|
let id = UUID()
|
|
let seriesName: String
|
|
let x: String
|
|
let y: Double
|
|
let color: Color
|
|
}
|
|
|
|
struct ChartWidgetView: View {
|
|
let widget: DashboardWidget
|
|
|
|
private var points: [PlottablePoint] {
|
|
guard let series = widget.series else { return [] }
|
|
return series.flatMap { s in
|
|
let color = parseColor(s.color)
|
|
return s.data.map { d in
|
|
PlottablePoint(seriesName: s.name, x: d.x, y: d.y, color: color)
|
|
}
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 6) {
|
|
Text(widget.title)
|
|
.scarfStyle(.caption)
|
|
.foregroundStyle(.secondary)
|
|
chartContent
|
|
.frame(height: 150)
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.padding(12)
|
|
.background(ScarfColor.backgroundSecondary)
|
|
.clipShape(RoundedRectangle(cornerRadius: ScarfRadius.lg))
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var chartContent: some View {
|
|
switch widget.chartType {
|
|
case "pie":
|
|
pieChart
|
|
case "bar":
|
|
barChart
|
|
default:
|
|
lineChart
|
|
}
|
|
}
|
|
|
|
private var lineChart: some View {
|
|
Chart(points) { point in
|
|
LineMark(
|
|
x: .value("X", point.x),
|
|
y: .value("Y", point.y)
|
|
)
|
|
.foregroundStyle(point.color)
|
|
.symbol(by: .value("Series", point.seriesName))
|
|
}
|
|
}
|
|
|
|
private var barChart: some View {
|
|
Chart(points) { point in
|
|
BarMark(
|
|
x: .value("X", point.x),
|
|
y: .value("Y", point.y)
|
|
)
|
|
.foregroundStyle(point.color)
|
|
}
|
|
}
|
|
|
|
private var pieChart: some View {
|
|
Chart(points) { point in
|
|
SectorMark(
|
|
angle: .value(point.x, point.y),
|
|
innerRadius: .ratio(0.5)
|
|
)
|
|
.foregroundStyle(point.color)
|
|
}
|
|
}
|
|
}
|