// // HistoryView.swift // App // // Created by James Magahern on 1/20/23. // import SwiftUI import UniformTypeIdentifiers struct HistoryView: View { @StateObject public var viewModel: BrowserHistory.ViewModel @State public var selectedItems = Set() private let dateFormatter = DateFormatter() .. { $0.locale = Locale.current $0.dateStyle = .medium $0.timeStyle = .short } @Environment(\.dismiss) private var dismissAction @Environment(\.horizontalSizeClass) private var horizontalSizeClass var body: some View { Table(viewModel.historyItems, selection: $selectedItems) { TableColumn("Title") { item in VStack(alignment: .leading) { Text(item.title.count > 0 ? item.title : item.url.absoluteString) .lineLimit(1) if horizontalSizeClass == .compact { Text(item.url.shortString()).font(.caption).lineLimit(1) Text(dateFormatter.string(from: item.lastVisited)) .font(.caption) .foregroundColor(.secondary) } } } TableColumn("URL", value: \.url.absoluteString) TableColumn("Last Visited") { item in Text(dateFormatter.string(from: item.lastVisited)) } } .contextMenu(forSelectionType: HistoryItem.ID.self, menu: { items in let historyItems = items.compactMap { viewModel.item(forIdentifier: $0) } Button("Copy") { UIPasteboard.general.setItems(historyItems.map { [ UTType.url.identifier : $0.url, UTType.utf8PlainText.identifier : $0.url.absoluteString, ] }) } Button("Delete") { viewModel.deleteItems(items) } }, primaryAction: { items in items.compactMap({ viewModel.item(forIdentifier: $0) }).forEach { item in UIApplication.shared.open(item.url) dismissAction() } }) .searchable(text: $viewModel.searchQuery) } } struct HistoryViewPreviewProvider: PreviewProvider { static var previews: some View { HistoryView(viewModel: BrowserHistory.shared.viewModel()) .previewLayout(.fixed(width: 480.0, height: 800.0)) } } extension URL { public func shortString() -> String { return String(absoluteString.trimmingPrefix(try! Regex("(.+)://"))) } }