// // StartPageView.swift // Zyquo Atlas // // Author: Simon-Pierre Boucher // Mail: contact@spboucher.ai // // The customizable new-tab / start page (Phase 4.2). Shows the theme // background, a greeting, a prominent AI-or-search ask box, and a favorites // quick grid. Bookmarks/history widgets and per-user layout of these sections // fill in with the bookmark & history services in Phase 6. // import SwiftUI struct StartPageView: View { let onNavigate: (String) -> Void let onAsk: () -> Void @EnvironmentObject private var themeEngine: ThemeEngine private var theme: AtlasTheme { themeEngine.theme } @State private var query = "" // Placeholder favorites until BookmarksService (Phase 6). private let quickLinks: [(String, String)] = [ ("Wikipedia", "https://en.wikipedia.org"), ("DuckDuckGo", "https://duckduckgo.com"), ("GitHub", "https://github.com"), ("Hacker News", "https://news.ycombinator.com"), ("MDN", "https://developer.mozilla.org"), ("arXiv", "https://arxiv.org"), ] var body: some View { ZStack { theme.backgroundView.ignoresSafeArea() VStack(spacing: ZyquoSpacing.xl) { Spacer() VStack(spacing: ZyquoSpacing.xs) { Text("Zyquo Atlas") .font(themeEngine.layout.font(34, weight: .bold)) .foregroundStyle(theme.textPrimary) Text("Explore the web, with AI everywhere.") .font(themeEngine.layout.font(14)) .foregroundStyle(theme.textSecondary) } askBox .frame(maxWidth: 620) favoritesGrid .frame(maxWidth: 620) Spacer() Spacer() } .padding(ZyquoSpacing.xxl) } } private var askBox: some View { HStack(spacing: ZyquoSpacing.sm) { Image(systemName: "magnifyingglass") .foregroundStyle(theme.textTertiary) TextField("Search, enter a URL, or ask AI…", text: $query) .textFieldStyle(.plain) .font(themeEngine.layout.font(15)) .foregroundStyle(theme.textPrimary) .onSubmit { let q = query.trimmingCharacters(in: .whitespacesAndNewlines) guard !q.isEmpty else { return } onNavigate(q); query = "" } Button(action: onAsk) { Label("Ask AI", systemImage: "sparkles") .font(themeEngine.layout.font(12, weight: .medium)) .padding(.horizontal, ZyquoSpacing.sm) .padding(.vertical, ZyquoSpacing.xxs) .background(RoundedRectangle(cornerRadius: ZyquoRadius.small).fill(theme.accentSubtle)) .foregroundStyle(theme.accentIndigo) } .buttonStyle(.plain) } .padding(.horizontal, ZyquoSpacing.md) .frame(height: 52) .background( RoundedRectangle(cornerRadius: ZyquoRadius.large) .fill(theme.surface) .shadow(color: ZyquoShadow.soft.color, radius: ZyquoShadow.soft.radius, y: ZyquoShadow.soft.y) ) .overlay( RoundedRectangle(cornerRadius: ZyquoRadius.large) .strokeBorder(theme.border, lineWidth: ZyquoMetrics.hairline) ) } private var favoritesGrid: some View { LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: ZyquoSpacing.sm), count: 3), spacing: ZyquoSpacing.sm) { ForEach(quickLinks, id: \.0) { name, url in Button { onNavigate(url) } label: { HStack(spacing: ZyquoSpacing.xs) { Image(systemName: "globe").foregroundStyle(theme.accent) Text(name) .font(themeEngine.layout.font(12.5, weight: .medium)) .foregroundStyle(theme.textPrimary) .lineLimit(1) Spacer(minLength: 0) } .padding(.horizontal, ZyquoSpacing.sm) .frame(height: 40) .background(RoundedRectangle(cornerRadius: ZyquoRadius.medium).fill(theme.surface)) .overlay(RoundedRectangle(cornerRadius: ZyquoRadius.medium) .strokeBorder(theme.border, lineWidth: ZyquoMetrics.hairline)) } .buttonStyle(.plain) } } } }