Files
luma/Luma/DetailView.swift
Ole André Vadla Ravnås a6f769221f ui: List pattern types in the sidebar
Show each file's declared types under it, with a browse popover when
there are many, and reveal a type's declaration when it is chosen.
2026-10-01 20:49:11 +02:00

146 lines
6.1 KiB
Swift

import Combine
import LumaCore
import SwiftUI
struct DetailView: View {
let engine: Engine
@Binding var selection: SidebarItemID?
var body: some View {
Group {
switch selection {
case .none:
NotebookEmptyStateView(
engine: engine,
onAddNote: { addEntry(kind: .note) },
onAddPharoCell: { addEntry(kind: .pharo) })
case .some(.notebook):
NotebookView(engine: engine, selection: $selection)
case .some(.pharo):
PharoPlaygroundView(engine: engine)
case .some(.missions):
MissionsListView(engine: engine, selection: $selection)
case .some(.mission(let missionID)):
MissionView(engine: engine, missionID: missionID, selection: $selection)
.id(missionID)
case .some(.patterns):
PatternsListView(engine: engine, selection: $selection)
case .some(.pattern(let sourceID)):
PatternEditorView(sourceID: sourceID, focusedType: nil, engine: engine, selection: $selection)
.id(sourceID)
case .some(.patternType(let sourceID, let typeName)):
PatternEditorView(sourceID: sourceID, focusedType: typeName, engine: engine, selection: $selection)
.id(sourceID)
case .some(.session(let sessionID)):
if engine.sessions.contains(where: { $0.id == sessionID }) {
SessionContent(sessionID: sessionID, engine: engine) {
SessionDetailView(sessionID: sessionID, engine: engine, selection: $selection)
}
.id(sessionID)
}
case .some(.repl(let sessionID)):
if let session = engine.sessions.first(where: { $0.id == sessionID }) {
SessionContent(sessionID: sessionID, engine: engine) {
REPLView(sessionID: sessionID, engine: engine, selection: $selection)
}
.id(session.id)
}
case .some(.module(let sessionID, let moduleID)):
if let session = engine.sessions.first(where: { $0.id == sessionID }),
let module = session.lastKnownModules?.first(where: { $0.id == moduleID })
{
SessionContent(sessionID: sessionID, engine: engine) {
ModuleDetailView(sessionID: sessionID, module: module, engine: engine, selection: $selection)
}
.id(moduleID)
}
case .some(.thread(let sessionID, let threadID)):
if let session = engine.sessions.first(where: { $0.id == sessionID }),
let thread = session.lastKnownThreads?.first(where: { $0.id == threadID })
{
SessionContent(sessionID: sessionID, engine: engine) {
ThreadDetailView(sessionID: sessionID, thread: thread, engine: engine, selection: $selection)
}
.id(threadID)
}
case .some(.instrument(let sessionID, let instID)),
.some(.instrumentComponent(let sessionID, let instID, _)):
if (try? engine.store.fetchInstrument(id: instID)) != nil {
SessionContent(sessionID: sessionID, engine: engine) {
InstrumentDetailView(
instanceID: instID,
sessionID: sessionID,
engine: engine,
selection: $selection
)
}
.id(instID)
}
case .some(.itrace(let sessionID, let traceID)):
let session = engine.sessions.first(where: { $0.id == sessionID })
if let session,
let trace = (try? engine.store.fetchITraces(sessionID: sessionID))?.first(where: { $0.id == traceID })
{
SessionContent(sessionID: sessionID, engine: engine) {
ITraceDetailView(
trace: trace, session: session, engine: engine, selection: $selection)
}
.id(trace.id)
}
case .some(.insight(let sessionID, let insightID)):
if let session = engine.sessions.first(where: { $0.id == sessionID }),
(engine.insightsBySession[sessionID] ?? []).contains(where: { $0.id == insightID })
{
SessionContent(sessionID: sessionID, engine: engine) {
AddressInsightDetailView(
session: session, insightID: insightID, engine: engine, selection: $selection)
}
.id(insightID)
}
case .some(.customInstrumentDef(let defID)):
CustomInstrumentEditorView(defID: defID, path: nil, engine: engine, selection: $selection)
.id(defID)
case .some(.customInstrumentFile(let defID, let path)):
CustomInstrumentEditorView(defID: defID, path: path, engine: engine, selection: $selection)
.id(defID)
case .some(.package(let packageID)):
if let package = engine.installedPackages.first(where: { $0.id == packageID }) {
PackageDetailView(package: package, engine: engine, selection: $selection)
.id(package.id)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.background)
}
private func addEntry(kind: LumaCore.NotebookEntry.Kind) {
let entry = LumaCore.NotebookEntry(
kind: kind,
title: "",
details: "",
binaryData: nil,
processName: nil
)
engine.addNotebookEntry(entry, after: nil)
selection = .notebook
}
}