Bug gixes, features added, GUI updates and more
This commit is contained in:
144
oAI/Views/Screens/HistoryView.swift
Normal file
144
oAI/Views/Screens/HistoryView.swift
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// HistoryView.swift
|
||||
// oAI
|
||||
//
|
||||
// Command history viewer with search
|
||||
//
|
||||
|
||||
import os
|
||||
import SwiftUI
|
||||
|
||||
struct HistoryView: View {
|
||||
@Environment(\.dismiss) var dismiss
|
||||
@State private var searchText = ""
|
||||
@State private var historyEntries: [HistoryEntry] = []
|
||||
var onSelect: ((String) -> Void)?
|
||||
|
||||
private var filteredHistory: [HistoryEntry] {
|
||||
if searchText.isEmpty {
|
||||
return historyEntries
|
||||
}
|
||||
return historyEntries.filter {
|
||||
$0.input.lowercased().contains(searchText.lowercased()) ||
|
||||
$0.formattedDate.contains(searchText)
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
// Header
|
||||
HStack {
|
||||
Text("Command History")
|
||||
.font(.system(size: 18, weight: .bold))
|
||||
Spacer()
|
||||
Button { dismiss() } label: {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.font(.title2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.keyboardShortcut(.escape, modifiers: [])
|
||||
}
|
||||
.padding(.horizontal, 24)
|
||||
.padding(.top, 20)
|
||||
.padding(.bottom, 12)
|
||||
|
||||
// Search bar
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "magnifyingglass")
|
||||
.foregroundStyle(.secondary)
|
||||
TextField("Search by text or date (dd.mm.yyyy)...", text: $searchText)
|
||||
.textFieldStyle(.plain)
|
||||
if !searchText.isEmpty {
|
||||
Button { searchText = "" } label: {
|
||||
Image(systemName: "xmark.circle.fill")
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
.padding(10)
|
||||
.background(.quaternary.opacity(0.5), in: RoundedRectangle(cornerRadius: 8))
|
||||
.padding(.horizontal, 24)
|
||||
.padding(.bottom, 12)
|
||||
|
||||
Divider()
|
||||
|
||||
// Content
|
||||
if filteredHistory.isEmpty {
|
||||
Spacer()
|
||||
VStack(spacing: 8) {
|
||||
Image(systemName: searchText.isEmpty ? "list.bullet" : "magnifyingglass")
|
||||
.font(.largeTitle)
|
||||
.foregroundStyle(.tertiary)
|
||||
Text(searchText.isEmpty ? "No Command History" : "No Matches")
|
||||
.font(.headline)
|
||||
.foregroundStyle(.secondary)
|
||||
Text(searchText.isEmpty ? "Your command history will appear here" : "Try a different search term or date")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
Spacer()
|
||||
} else {
|
||||
List {
|
||||
ForEach(filteredHistory) { entry in
|
||||
HistoryRow(entry: entry)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
onSelect?(entry.input)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
.listStyle(.plain)
|
||||
}
|
||||
}
|
||||
.frame(minWidth: 600, minHeight: 400)
|
||||
.background(Color.oaiBackground)
|
||||
.task {
|
||||
loadHistory()
|
||||
}
|
||||
}
|
||||
|
||||
private func loadHistory() {
|
||||
do {
|
||||
let records = try DatabaseService.shared.loadCommandHistory()
|
||||
historyEntries = records.map { HistoryEntry(input: $0.input, timestamp: $0.timestamp) }
|
||||
} catch {
|
||||
Log.db.error("Failed to load command history: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct HistoryRow: View {
|
||||
let entry: HistoryEntry
|
||||
private let settings = SettingsService.shared
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
// Input text
|
||||
Text(entry.input)
|
||||
.font(.system(size: settings.dialogTextSize))
|
||||
.foregroundStyle(.primary)
|
||||
.lineLimit(3)
|
||||
|
||||
// Timestamp
|
||||
HStack(spacing: 4) {
|
||||
Image(systemName: "clock")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
Text(entry.formattedDate)
|
||||
.font(.system(size: 11))
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 4)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HistoryView { input in
|
||||
print("Selected: \(input)")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user