refactor(ios): minimal full-screen canvas

This commit is contained in:
Peter Steinberger
2025-12-13 00:50:20 +00:00
parent ca20a2dc06
commit 8cc2dc715c
4 changed files with 70 additions and 44 deletions

View File

@@ -7,7 +7,7 @@ struct ClawdisNodeApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
RootTabs() RootCanvas()
.environmentObject(self.appModel) .environmentObject(self.appModel)
.environmentObject(self.appModel.voiceWake) .environmentObject(self.appModel.voiceWake)
.onChange(of: self.scenePhase) { _, newValue in .onChange(of: self.scenePhase) { _, newValue in

View File

@@ -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()
}
}
}

View File

@@ -6,14 +6,15 @@ import WebKit
final class ScreenController: ObservableObject { final class ScreenController: ObservableObject {
let webView: WKWebView let webView: WKWebView
@Published var mode: ClawdisScreenMode = .web @Published var mode: ClawdisScreenMode = .canvas
@Published var urlString: String = "https://example.com" @Published var urlString: String = ""
@Published var errorText: String? @Published var errorText: String?
init() { init() {
let config = WKWebViewConfiguration() let config = WKWebViewConfiguration()
config.websiteDataStore = .nonPersistent() config.websiteDataStore = .nonPersistent()
self.webView = WKWebView(frame: .zero, configuration: config) self.webView = WKWebView(frame: .zero, configuration: config)
self.reload()
} }
func setMode(_ mode: ClawdisScreenMode) { func setMode(_ mode: ClawdisScreenMode) {
@@ -91,29 +92,37 @@ final class ScreenController: ObservableObject {
:root { color-scheme: dark; } :root { color-scheme: dark; }
html,body { height:100%; margin:0; } html,body { height:100%; margin:0; }
body { body {
font: 13px -apple-system, system-ui; background:#000;
display:flex;
align-items:center;
justify-content:center;
background:#0b1020;
color:#e5e7eb;
} }
.card { canvas {
max-width: 520px; display:block;
padding: 18px; width:100vw;
border-radius: 14px; height:100vh;
border: 1px solid rgba(255,255,255,.10);
background: rgba(255,255,255,.06);
box-shadow: 0 18px 60px rgba(0,0,0,.35);
} }
.muted { color: rgba(229,231,235,.75); margin-top: 8px; }
</style> </style>
</head> </head>
<body> <body>
<div class="card"> <canvas id="clawdis-canvas"></canvas>
<div style="font-weight:600; font-size:14px;">Canvas scaffold</div> <script>
<div class="muted">Next: agent-driven on-disk workspace.</div> (() => {
</div> const canvas = document.getElementById('clawdis-canvas');
const ctx = canvas.getContext('2d');
function resize() {
const dpr = window.devicePixelRatio || 1;
const w = Math.max(1, Math.floor(window.innerWidth * dpr));
const h = Math.max(1, Math.floor(window.innerHeight * dpr));
canvas.width = w;
canvas.height = h;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
window.addEventListener('resize', resize);
resize();
window.__clawdis = { canvas, ctx };
})();
</script>
</body> </body>
</html> </html>
""" """

View File

@@ -5,31 +5,19 @@ struct ScreenTab: View {
@EnvironmentObject private var appModel: NodeAppModel @EnvironmentObject private var appModel: NodeAppModel
var body: some View { var body: some View {
NavigationStack { ZStack(alignment: .top) {
VStack(spacing: 0) { ScreenWebView(controller: self.appModel.screen)
ScreenWebView(controller: self.appModel.screen) .ignoresSafeArea()
.overlay(alignment: .top) { .overlay(alignment: .top) {
if let errorText = self.appModel.screen.errorText { if let errorText = self.appModel.screen.errorText {
Text(errorText) Text(errorText)
.font(.footnote) .font(.footnote)
.padding(10) .padding(10)
.background(.thinMaterial) .background(.thinMaterial)
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
.padding() .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)
} }
} }