From db092c79a175e3283f479ee0b234b24bde3c736e Mon Sep 17 00:00:00 2001 From: soryu-co Date: Fri, 24 Apr 2026 13:15:29 +0000 Subject: Add Makima iOS app scaffold (M0 + M1 design system) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure-native SwiftUI client for makima.jp under makima/ios/. M0 (scaffold) - XcodeGen project (iOS 18+, Swift 5.10, bundle co.soryu.makima) - Makefile targets: bootstrap, xcgen, ios-sim-fast, ios-device-fast, test, lint - GitHub Actions workflow ios-ci.yml — builds + runs XCTest on macos-14 - MIT repo root license already in place M1 (design system, web-aesthetic port) - Palette: #0c1729 background, #9bc3ff accent, #3f6fb3 border (ported from Tailwind) - Typography: SF Mono for chrome, uppercase tracked nav labels - Components: DashedBorder, GridOverlay, MastheadBar + WebSocketStatus pill, NavStripPlaceholder (NAV// prefix), JapaneseLongPressText (mobile analogue of JapaneseHoverText), Logo (reuses frontend/public/logo/makima-logo.svg with Canvas concentric-ring fallback), Badge - RootView demo screen: masthead, nav strip, logo, CONTROL SYSTEM badge, SYSTEM// status card, GLOSSARY// card with 命令/契約/聴取/史料 long-press terms Auth (v1 plan, not wired here): x-makima-api-key header — verified against src/server/auth.rs. Authorization: Bearer reserved for v1.1 Supabase OAuth. v1 plan doc: makima/ios/docs/ios-v1-plan.md Not in this PR: networking, WebSocket client, stores, feature surfaces (Home/Contracts/Tasks/Directives/Daemons/Listen), notifications. Those land across M2-M8 per the plan. --- .../Makima/Design/Components/MastheadBar.swift | 100 +++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 makima/ios/Sources/Makima/Design/Components/MastheadBar.swift (limited to 'makima/ios/Sources/Makima/Design/Components/MastheadBar.swift') diff --git a/makima/ios/Sources/Makima/Design/Components/MastheadBar.swift b/makima/ios/Sources/Makima/Design/Components/MastheadBar.swift new file mode 100644 index 0000000..a304f95 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/MastheadBar.swift @@ -0,0 +1,100 @@ +import SwiftUI + +enum WebSocketStatus { + case idle, connecting, online, offline + + var label: String { + switch self { + case .idle: return "WS//IDLE" + case .connecting: return "WS//…" + case .online: return "WS//ONLINE" + case .offline: return "WS//OFFLINE" + } + } + + var color: Color { + switch self { + case .idle: return Palette.foregroundMuted + case .connecting: return Palette.warn + case .online: return Palette.ok + case .offline: return Palette.danger + } + } +} + +/// Top chrome strip, replaces a traditional nav bar. +/// Composition: small logo + "MAKIMA" brand + spacer + ws-pill + server label + version. +struct MastheadBar: View { + let serverLabel: String + let wsStatus: WebSocketStatus + let version: String + + var body: some View { + HStack(spacing: 10) { + Logo(size: 22) + Text("MAKIMA") + .font(.system(.caption, design: .monospaced).weight(.semibold)) + .tracking(2) + .foregroundStyle(Palette.foreground) + + Spacer(minLength: 8) + + Text(wsStatus.label) + .font(Typography.navLabel) + .foregroundStyle(wsStatus.color) + Text("·") + .foregroundStyle(Palette.borderMuted) + Text(serverLabel) + .font(Typography.navLabel) + .foregroundStyle(Palette.accent) + Text("·") + .foregroundStyle(Palette.borderMuted) + Text("v\(version)") + .font(Typography.navLabel) + .foregroundStyle(Palette.foregroundMuted) + } + .padding(.horizontal, 14) + .padding(.vertical, 10) + .background( + LinearGradient( + colors: [Palette.backgroundDeep.opacity(0.95), Palette.panel.opacity(0.7)], + startPoint: .top, endPoint: .bottom + ) + ) + .overlay(alignment: .bottom) { + Rectangle().fill(Palette.border).frame(height: 2) + } + } +} + +struct NavStripPlaceholder: View { + private let labels = ["LISTEN", "DIRECTIVES", "ORDERS", "CONTRACTS", "DAEMONS", "HISTORY"] + + var body: some View { + HStack(spacing: 10) { + Text("NAV//") + .font(Typography.navLabel) + .foregroundStyle(Palette.accent) + .padding(.trailing, 4) + .overlay(alignment: .trailing) { + Rectangle().fill(Palette.borderMuted).frame(width: 1, height: 14) + .offset(x: 4) + } + ForEach(labels, id: \.self) { l in + Text(l) + .font(Typography.navLabel) + .foregroundStyle(Palette.accent.opacity(0.8)) + } + Spacer() + } + .padding(.horizontal, 12) + .padding(.vertical, 10) + .background(Palette.panel) + .overlay(alignment: .top) { + Rectangle().fill(Palette.borderMuted).frame(height: 1) + } + .overlay(alignment: .bottom) { + Rectangle().fill(Palette.borderMuted).frame(height: 1) + } + } +} -- cgit v1.2.3