SPB Git

spb/prisme Public MIT

Navigateur iOS intelligent — chaque page comprise localement avant d'être affichée. SwiftUI · WebKit · Foundation Models, 100% on-device.

Swift 96.7% JavaScript 3.3%
3.3 KB · 99 lines swift
Raw Blame History
1//2//  HistoryView.swift3//  Prisme4//5//  Author: Simon-Pierre Boucher <contact@spboucher.ai>6//78import SwiftUI910/// Semantic history browser: recent visits by day, natural language search11/// on top ("le site avec la recette de ramen vu au printemps").12struct HistoryView: View {13    let history: HistoryStore14    let containers: IdentityContainerStore15    let onOpen: (PageVisit) -> Void1617    @Environment(\.dismiss) private var dismiss18    @State private var query = ""1920    private var results: [PageVisit] {21        query.trimmingCharacters(in: .whitespaces).count >= 222            ? history.search(query)23            : history.recent24    }2526    var body: some View {27        NavigationStack {28            Group {29                if results.isEmpty {30                    ContentUnavailableView {31                        Label(32                            query.isEmpty ? "Encore rien à retrouver" : "Rien trouvé",33                            systemImage: "clock.arrow.circlepath"34                        )35                    } description: {36                        Text(query.isEmpty37                            ? "Les pages visitées seront retrouvables ici, en langage naturel. Tout reste sur l'appareil."38                            : "Aucune page visitée ne correspond à « \(query) ».")39                    }40                } else {41                    visitList42                }43            }44            .navigationTitle("Historique")45            .navigationBarTitleDisplayMode(.inline)46            .searchable(47                text: $query,48                placement: .navigationBarDrawer(displayMode: .always),49                prompt: "Rechercher une page visitée…"50            )51            .toolbar {52                ToolbarItem(placement: .cancellationAction) {53                    Button("Fermer") { dismiss() }54                }55            }56        }57    }5859    private var visitList: some View {60        List(results, id: \.urlString) { visit in61            Button {62                onOpen(visit)63                dismiss()64            } label: {65                HStack(alignment: .top, spacing: Spacing.m) {66                    Circle()67                        .fill(color(for: visit))68                        .frame(width: 8, height: 8)69                        .padding(.top, 6)70                    VStack(alignment: .leading, spacing: 2) {71                        Text(visit.title)72                            .foregroundStyle(.primary)73                            .lineLimit(2)74                        HStack(spacing: Spacing.xs) {75                            Text(visit.host)76                            Text("·")77                            Text(visit.visitedAt, style: .relative)78                        }79                        .font(.caption)80                        .foregroundStyle(.secondary)81                        if !visit.gist.isEmpty {82                            Text(visit.gist)83                                .font(.caption)84                                .foregroundStyle(.tertiary)85                                .lineLimit(2)86                        }87                    }88                }89            }90            .accessibilityIdentifier("history.row")91        }92        .listStyle(.plain)93    }9495    private func color(for visit: PageVisit) -> Color {96        containers.container(for: visit.containerID)?.color.color ?? .secondary97    }98}99