Skip to content

Commit 74a0312

Browse files
committed
feat(ios): restructure tabs — Focus/Decide/Capture
- Add QuickDecisionView for fast decision recording (what, why, project, assumptions) - Restructure iOS tabs: Focus (hero) / Decide / Capture - Move Settings to toolbar gear icon (sheet presentation) - Improve DailyFocusView empty state with context card (goals, project, signals) - Add CortexEngine.recordDecision() for decision memory - Remove Insights from iOS tabs (insights surface through Focus priorities) CortexOS learns your thinking patterns. Decisions build compounding intelligence.
1 parent 175b226 commit 74a0312

4 files changed

Lines changed: 375 additions & 18 deletions

File tree

CortexOSApp/Shared/Services/CortexEngine.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ final class CortexEngine: ObservableObject {
210210
}
211211
}
212212

213+
// MARK: - Decisions
214+
215+
func recordDecision(_ request: DecisionCreateRequest) async -> Bool {
216+
do {
217+
let decision = try await api.recordDecision(request)
218+
// Merge into local snapshot if available
219+
if snapshot != nil {
220+
await sync()
221+
}
222+
errorMessage = nil
223+
return true
224+
} catch {
225+
errorMessage = error.localizedDescription
226+
return false
227+
}
228+
}
229+
213230
// MARK: - Feedback (was this useful?)
214231

215232
func sendFeedback(item: String, useful: Bool) async {

CortexOSApp/Shared/Views/ContentView.swift

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// CortexOS
44
//
55
// Root navigation — radically simple.
6-
// iOS: Focus is the hero. Capture + Insights secondary.
7-
// macOS: 4 sidebar items. That's it.
6+
// iOS: Focus is the hero. Decide + Capture secondary.
7+
// macOS: 5 sidebar items. That's it.
88
//
99

1010
import SwiftUI
@@ -20,26 +20,46 @@ struct ContentView: View {
2020
#endif
2121
}
2222

23-
// MARK: - iOS (3 tabs — Focus first, always)
23+
// MARK: - iOS (3 tabs — Focus / Decide / Capture)
2424

2525
#if os(iOS)
26+
@State private var showSettings = false
27+
2628
private var iOSRoot: some View {
2729
TabView {
28-
NavigationStack { DailyFocusView() }
29-
.tabItem { Label("Focus", systemImage: "sparkles") }
30+
NavigationStack {
31+
DailyFocusView()
32+
.toolbar {
33+
ToolbarItem(placement: .topBarTrailing) {
34+
Button { showSettings = true } label: {
35+
Image(systemName: "gearshape")
36+
.foregroundStyle(CortexColor.textTertiary)
37+
}
38+
}
39+
}
40+
}
41+
.tabItem { Label("Focus", systemImage: "sparkles") }
42+
43+
NavigationStack { QuickDecisionView() }
44+
.tabItem { Label("Decide", systemImage: "checkmark.seal") }
3045

3146
NavigationStack { QuickCaptureView() }
3247
.tabItem { Label("Capture", systemImage: "plus.circle") }
33-
34-
NavigationStack { InsightFeedView() }
35-
.tabItem { Label("Insights", systemImage: "lightbulb") }
36-
37-
NavigationStack { SettingsView() }
38-
.tabItem { Label("Settings", systemImage: "gearshape") }
3948
}
4049
.tint(CortexColor.accent)
4150
.environmentObject(engine)
4251
.task { await engine.sync() }
52+
.sheet(isPresented: $showSettings) {
53+
NavigationStack {
54+
SettingsView()
55+
.environmentObject(engine)
56+
.toolbar {
57+
ToolbarItem(placement: .topBarTrailing) {
58+
Button("Done") { showSettings = false }
59+
}
60+
}
61+
}
62+
}
4363
}
4464
#endif
4565

CortexOSApp/Shared/Views/DailyFocusView.swift

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,72 @@ struct DailyFocusView: View {
1919
} else if let legacy = engine.dailyBrief {
2020
legacyContent(legacy)
2121
} else {
22-
EmptyStateView(
23-
icon: "sparkles",
24-
title: "No focus brief yet",
25-
message: "Run the pipeline to generate today's priorities.",
26-
actionTitle: "Generate",
27-
action: { Task { await engine.generateFocusBrief() } }
28-
)
22+
VStack(spacing: CortexSpacing.xl) {
23+
EmptyStateView(
24+
icon: "sparkles",
25+
title: "No focus brief yet",
26+
message: "CortexOS distils your top 3 priorities.\nConnect to the server and run the pipeline.",
27+
actionTitle: "Generate Focus",
28+
action: { Task { await engine.generateFocusBrief() } }
29+
)
30+
31+
// Orientation: show what CortexOS knows
32+
if let snapshot = engine.snapshot {
33+
quickContextCard(snapshot)
34+
}
35+
}
2936
}
3037
}
3138
.background(CortexColor.bgPrimary)
3239
.navigationTitle("Focus")
3340
.refreshable { await engine.sync() }
3441
}
3542

43+
// MARK: - Quick context when empty
44+
45+
@ViewBuilder
46+
private func quickContextCard(_ snapshot: SyncSnapshot) -> some View {
47+
VStack(alignment: .leading, spacing: CortexSpacing.sm) {
48+
if let project = snapshot.activeProject {
49+
HStack(spacing: CortexSpacing.xs) {
50+
Image(systemName: "folder.fill")
51+
.font(.caption)
52+
.foregroundStyle(CortexColor.accent)
53+
Text(project.projectName)
54+
.font(CortexFont.captionMedium)
55+
.foregroundStyle(CortexColor.textPrimary)
56+
}
57+
}
58+
59+
if !snapshot.profile.goals.isEmpty {
60+
VStack(alignment: .leading, spacing: CortexSpacing.xxs) {
61+
Text("Your goals")
62+
.font(CortexFont.mono)
63+
.foregroundStyle(CortexColor.textTertiary)
64+
ForEach(snapshot.profile.goals.prefix(3), id: \.self) { goal in
65+
Text("\(goal)")
66+
.font(CortexFont.caption)
67+
.foregroundStyle(CortexColor.textSecondary)
68+
}
69+
}
70+
}
71+
72+
if !snapshot.signals.isEmpty {
73+
HStack(spacing: CortexSpacing.xs) {
74+
ForEach(snapshot.signals.prefix(3)) { signal in
75+
ContextTag(text: signal.topic)
76+
}
77+
}
78+
}
79+
}
80+
.padding(CortexSpacing.lg)
81+
.frame(maxWidth: .infinity, alignment: .leading)
82+
.background(CortexColor.bgSurface)
83+
.clipShape(RoundedRectangle(cornerRadius: CortexRadius.card, style: .continuous))
84+
.cortexShadow()
85+
.padding(.horizontal, CortexSpacing.xl)
86+
}
87+
3688
// MARK: - Sync-powered focus
3789

3890
@ViewBuilder

0 commit comments

Comments
 (0)