From 8cc2dc715cce4cacd011d1456964aff85ad97961 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 13 Dec 2025 00:50:20 +0000 Subject: [PATCH] refactor(ios): minimal full-screen canvas --- apps/ios/Sources/ClawdisNodeApp.swift | 2 +- apps/ios/Sources/RootCanvas.swift | 29 +++++++++++ .../ios/Sources/Screen/ScreenController.swift | 49 +++++++++++-------- apps/ios/Sources/Screen/ScreenTab.swift | 34 +++++-------- 4 files changed, 70 insertions(+), 44 deletions(-) create mode 100644 apps/ios/Sources/RootCanvas.swift diff --git a/apps/ios/Sources/ClawdisNodeApp.swift b/apps/ios/Sources/ClawdisNodeApp.swift index d1690f4cf..529c3e943 100644 --- a/apps/ios/Sources/ClawdisNodeApp.swift +++ b/apps/ios/Sources/ClawdisNodeApp.swift @@ -7,7 +7,7 @@ struct ClawdisNodeApp: App { var body: some Scene { WindowGroup { - RootTabs() + RootCanvas() .environmentObject(self.appModel) .environmentObject(self.appModel.voiceWake) .onChange(of: self.scenePhase) { _, newValue in diff --git a/apps/ios/Sources/RootCanvas.swift b/apps/ios/Sources/RootCanvas.swift new file mode 100644 index 000000000..16a3c032a --- /dev/null +++ b/apps/ios/Sources/RootCanvas.swift @@ -0,0 +1,29 @@ +import SwiftUI + +struct RootCanvas: View { + @State private var isShowingSettings = false + + var body: some View { + ZStack(alignment: .topTrailing) { + ScreenTab() + + Button { + self.isShowingSettings = true + } label: { + Image(systemName: "gearshape.fill") + .font(.system(size: 16, weight: .semibold)) + .foregroundStyle(.primary) + .padding(10) + .background(.thinMaterial) + .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) + } + .buttonStyle(.plain) + .padding(.top, 10) + .padding(.trailing, 10) + .accessibilityLabel("Settings") + } + .sheet(isPresented: self.$isShowingSettings) { + SettingsTab() + } + } +} diff --git a/apps/ios/Sources/Screen/ScreenController.swift b/apps/ios/Sources/Screen/ScreenController.swift index bdcd209be..0dfc043c7 100644 --- a/apps/ios/Sources/Screen/ScreenController.swift +++ b/apps/ios/Sources/Screen/ScreenController.swift @@ -6,14 +6,15 @@ import WebKit final class ScreenController: ObservableObject { let webView: WKWebView - @Published var mode: ClawdisScreenMode = .web - @Published var urlString: String = "https://example.com" + @Published var mode: ClawdisScreenMode = .canvas + @Published var urlString: String = "" @Published var errorText: String? init() { let config = WKWebViewConfiguration() config.websiteDataStore = .nonPersistent() self.webView = WKWebView(frame: .zero, configuration: config) + self.reload() } func setMode(_ mode: ClawdisScreenMode) { @@ -91,29 +92,37 @@ final class ScreenController: ObservableObject { :root { color-scheme: dark; } html,body { height:100%; margin:0; } body { - font: 13px -apple-system, system-ui; - display:flex; - align-items:center; - justify-content:center; - background:#0b1020; - color:#e5e7eb; + background:#000; } - .card { - max-width: 520px; - padding: 18px; - border-radius: 14px; - border: 1px solid rgba(255,255,255,.10); - background: rgba(255,255,255,.06); - box-shadow: 0 18px 60px rgba(0,0,0,.35); + canvas { + display:block; + width:100vw; + height:100vh; } - .muted { color: rgba(229,231,235,.75); margin-top: 8px; } -
-
Canvas scaffold
-
Next: agent-driven on-disk workspace.
-
+ + """ diff --git a/apps/ios/Sources/Screen/ScreenTab.swift b/apps/ios/Sources/Screen/ScreenTab.swift index e54599029..5cdc81bdf 100644 --- a/apps/ios/Sources/Screen/ScreenTab.swift +++ b/apps/ios/Sources/Screen/ScreenTab.swift @@ -5,31 +5,19 @@ struct ScreenTab: View { @EnvironmentObject private var appModel: NodeAppModel var body: some View { - NavigationStack { - VStack(spacing: 0) { - ScreenWebView(controller: self.appModel.screen) - .overlay(alignment: .top) { - if let errorText = self.appModel.screen.errorText { - Text(errorText) - .font(.footnote) - .padding(10) - .background(.thinMaterial) - .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) - .padding() - } + ZStack(alignment: .top) { + ScreenWebView(controller: self.appModel.screen) + .ignoresSafeArea() + .overlay(alignment: .top) { + if let errorText = self.appModel.screen.errorText { + Text(errorText) + .font(.footnote) + .padding(10) + .background(.thinMaterial) + .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) + .padding() } - - if self.appModel.isBackgrounded { - Divider() - Text("Screen commands unavailable while backgrounded.") - .font(.footnote) - .foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - .padding() } - } - .navigationTitle("Screen") - .navigationBarTitleDisplayMode(.inline) } }