feat(ios): add close button and ready canvas
This commit is contained in:
@@ -92,21 +92,73 @@ 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 {
|
||||||
background:#000;
|
background: radial-gradient(1200px 900px at 15% 20%, rgba(42, 113, 255, 0.18), rgba(0,0,0,0) 55%),
|
||||||
|
radial-gradient(900px 700px at 85% 30%, rgba(255, 0, 138, 0.14), rgba(0,0,0,0) 60%),
|
||||||
|
radial-gradient(1000px 900px at 60% 90%, rgba(0, 209, 255, 0.10), rgba(0,0,0,0) 60%),
|
||||||
|
#000;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
body::before {
|
||||||
|
content:"";
|
||||||
|
position: fixed;
|
||||||
|
inset: -20%;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(0deg, rgba(255,255,255,0.02) 0, rgba(255,255,255,0.02) 1px, transparent 1px, transparent 48px),
|
||||||
|
repeating-linear-gradient(90deg, rgba(255,255,255,0.02) 0, rgba(255,255,255,0.02) 1px, transparent 1px, transparent 48px);
|
||||||
|
transform: rotate(-7deg);
|
||||||
|
opacity: 0.55;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
canvas {
|
canvas {
|
||||||
display:block;
|
display:block;
|
||||||
width:100vw;
|
width:100vw;
|
||||||
height:100vh;
|
height:100vh;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
#clawdis-status {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
#clawdis-status .card {
|
||||||
|
text-align: center;
|
||||||
|
padding: 16px 18px;
|
||||||
|
border-radius: 14px;
|
||||||
|
background: rgba(18, 18, 22, 0.42);
|
||||||
|
border: 1px solid rgba(255,255,255,0.08);
|
||||||
|
box-shadow: 0 18px 60px rgba(0,0,0,0.55);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
}
|
||||||
|
#clawdis-status .title {
|
||||||
|
font: 600 20px -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", system-ui, sans-serif;
|
||||||
|
letter-spacing: 0.2px;
|
||||||
|
color: rgba(255,255,255,0.92);
|
||||||
|
text-shadow: 0 0 22px rgba(42, 113, 255, 0.35);
|
||||||
|
}
|
||||||
|
#clawdis-status .subtitle {
|
||||||
|
margin-top: 6px;
|
||||||
|
font: 500 12px -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
|
||||||
|
color: rgba(255,255,255,0.58);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas id="clawdis-canvas"></canvas>
|
<canvas id="clawdis-canvas"></canvas>
|
||||||
|
<div id="clawdis-status">
|
||||||
|
<div class="card">
|
||||||
|
<div class="title" id="clawdis-status-title">Ready</div>
|
||||||
|
<div class="subtitle" id="clawdis-status-subtitle">Waiting for agent</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
(() => {
|
(() => {
|
||||||
const canvas = document.getElementById('clawdis-canvas');
|
const canvas = document.getElementById('clawdis-canvas');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
const statusEl = document.getElementById('clawdis-status');
|
||||||
|
const titleEl = document.getElementById('clawdis-status-title');
|
||||||
|
const subtitleEl = document.getElementById('clawdis-status-subtitle');
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
const dpr = window.devicePixelRatio || 1;
|
const dpr = window.devicePixelRatio || 1;
|
||||||
@@ -120,7 +172,20 @@ final class ScreenController: ObservableObject {
|
|||||||
window.addEventListener('resize', resize);
|
window.addEventListener('resize', resize);
|
||||||
resize();
|
resize();
|
||||||
|
|
||||||
window.__clawdis = { canvas, ctx };
|
window.__clawdis = {
|
||||||
|
canvas,
|
||||||
|
ctx,
|
||||||
|
setStatus: (title, subtitle) => {
|
||||||
|
if (!statusEl) return;
|
||||||
|
if (!title && !subtitle) {
|
||||||
|
statusEl.style.display = 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
statusEl.style.display = 'grid';
|
||||||
|
if (titleEl && typeof title === 'string') titleEl.textContent = title;
|
||||||
|
if (subtitleEl && typeof subtitle === 'string') subtitleEl.textContent = subtitle;
|
||||||
|
}
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct SettingsTab: View {
|
struct SettingsTab: View {
|
||||||
@EnvironmentObject private var appModel: NodeAppModel
|
@EnvironmentObject private var appModel: NodeAppModel
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
@AppStorage("node.displayName") private var displayName: String = "iOS Node"
|
@AppStorage("node.displayName") private var displayName: String = "iOS Node"
|
||||||
@AppStorage("node.instanceId") private var instanceId: String = UUID().uuidString
|
@AppStorage("node.instanceId") private var instanceId: String = UUID().uuidString
|
||||||
@AppStorage("voiceWake.enabled") private var voiceWakeEnabled: Bool = false
|
@AppStorage("voiceWake.enabled") private var voiceWakeEnabled: Bool = false
|
||||||
@@ -65,6 +66,16 @@ struct SettingsTab: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Settings")
|
.navigationTitle("Settings")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
|
Button {
|
||||||
|
self.dismiss()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "xmark")
|
||||||
|
}
|
||||||
|
.accessibilityLabel("Close")
|
||||||
|
}
|
||||||
|
}
|
||||||
.onAppear { self.discovery.start() }
|
.onAppear { self.discovery.start() }
|
||||||
.onDisappear { self.discovery.stop() }
|
.onDisappear { self.discovery.stop() }
|
||||||
.onChange(of: self.discovery.bridges) { _, newValue in
|
.onChange(of: self.discovery.bridges) { _, newValue in
|
||||||
|
|||||||
Reference in New Issue
Block a user