spb/zyquo-atlas Public License
The AI-native macOS web browser — every surface, intelligent.
Swift 75.2%
JavaScript 22%
Shell 2%
Makefile 0.9%
1//2// OmniboxView.swift3// Zyquo Atlas4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// The address/search field. Shows a security indicator, reflects the active9// tab's URL when not being edited, and on submit resolves URL-vs-search via10// OmniIntent. The Phase 3 "ask AI" route and answer overlay attach here.11//1213import SwiftUI1415struct OmniboxView: View {16 @ObservedObject var tab: Tab17 let onSubmit: (String) -> Void18 var onAsk: (String) -> Void = { _ in }19 @EnvironmentObject private var themeEngine: ThemeEngine20 @EnvironmentObject private var windowState: WindowState21 private var theme: AtlasTheme { themeEngine.theme }2223 @State private var text: String = ""24 @State private var isEditing: Bool = false25 @FocusState private var focused: Bool2627 var body: some View {28 HStack(spacing: ZyquoSpacing.xs) {29 Image(systemName: securityGlyph)30 .font(.system(size: 11, weight: .semibold))31 .foregroundStyle(securityColor)3233 TextField("Search or enter website name", text: $text)34 .textFieldStyle(.plain)35 .font(ZyquoFont.control)36 .foregroundStyle(theme.textPrimary)37 .focused($focused)38 .onSubmit {39 onSubmit(text)40 focused = false41 }42 .onChange(of: focused) { now in43 isEditing = now44 if now { selectAll() } else { syncFromTab() }45 }4647 if isEditing && !text.isEmpty {48 Button {49 onAsk(text)50 focused = false51 } label: {52 Label("Ask AI", systemImage: "sparkles")53 .font(.system(size: 10, weight: .semibold))54 .padding(.horizontal, ZyquoSpacing.xs)55 .padding(.vertical, 2)56 .background(Capsule().fill(theme.accentSubtle))57 .foregroundStyle(theme.accentIndigo)58 }59 .buttonStyle(.plain)60 .help("Ask AI about this (⌥Return)")61 Button {62 text = ""63 } label: {64 Image(systemName: "xmark.circle.fill")65 .font(.system(size: 12))66 .foregroundStyle(theme.textTertiary)67 }68 .buttonStyle(.plain)69 }70 }71 .padding(.horizontal, ZyquoSpacing.sm)72 .frame(height: 30)73 .background(74 RoundedRectangle(cornerRadius: ZyquoRadius.small)75 .fill(theme.surfaceSecondary)76 )77 .overlay(78 RoundedRectangle(cornerRadius: ZyquoRadius.small)79 .strokeBorder(focused ? theme.accent : theme.border,80 lineWidth: focused ? 1.5 : ZyquoMetrics.hairline)81 )82 .onChange(of: tab.url) { _ in if !isEditing { syncFromTab() } }83 .onChange(of: windowState.omniboxFocusToken) { _ in focused = true }84 .onAppear { syncFromTab() }85 }8687 // MARK: - Helpers8889 private var securityGlyph: String {90 guard tab.url != nil else { return "magnifyingglass" }91 return tab.hasSecureConnection ? "lock.fill" : "exclamationmark.triangle.fill"92 }9394 private var securityColor: Color {95 guard tab.url != nil else { return theme.textTertiary }96 return tab.hasSecureConnection ? theme.textSecondary : theme.warning97 }9899 private func syncFromTab() {100 text = tab.url?.absoluteString ?? ""101 }102103 private func selectAll() {104 // Reflect the raw URL for editing; SwiftUI selects on focus via the105 // field's default behavior when text is present.106 if text.isEmpty { syncFromTab() }107 }108}109