import Foundation public struct Workspace: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var rootURL: URL public var items: [WorkspaceItem] public init( id: UUID = UUID(), name: String, rootURL: URL, items: [WorkspaceItem] = [] ) { self.id = id self.name = name self.rootURL = rootURL self.items = items } } public indirect enum WorkspaceItem: Identifiable, Hashable, Codable, Sendable { case folder(WorkspaceFolder) case file(WorkspaceFile) case project(Project) case subproject(Subproject) public var id: UUID { switch self { case .folder(let folder): folder.id case .file(let file): file.id case .project(let project): project.id case .subproject(let subproject): subproject.id } } public var displayName: String { switch self { case .folder(let folder): folder.name case .file(let file): file.name case .project(let project): project.name case .subproject(let subproject): subproject.name } } } public struct WorkspaceFolder: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var url: URL public var children: [WorkspaceItem] public init( id: UUID = UUID(), name: String, url: URL, children: [WorkspaceItem] = [] ) { self.id = id self.name = name self.url = url self.children = children } } public struct WorkspaceFile: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var url: URL public var kind: WorkspaceFileKind public init( id: UUID = UUID(), name: String, url: URL, kind: WorkspaceFileKind ) { self.id = id self.name = name self.url = url self.kind = kind } } public enum WorkspaceFileKind: String, Hashable, Codable, Sendable { case markdown case attachment case other } public struct Project: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var repositoryURL: URL public var gitRepository: GitRepository public var remotes: [GitRemote] public var branches: [GitBranch] public var subprojects: [Subproject] public var usesGitLFS: Bool public init( id: UUID = UUID(), name: String, repositoryURL: URL, gitRepository: GitRepository, remotes: [GitRemote] = [], branches: [GitBranch] = [], subprojects: [Subproject] = [], usesGitLFS: Bool = false ) { self.id = id self.name = name self.repositoryURL = repositoryURL self.gitRepository = gitRepository self.remotes = remotes self.branches = branches self.subprojects = subprojects self.usesGitLFS = usesGitLFS } } public struct Subproject: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var path: String public var repositoryURL: URL public var remoteURL: URL? public init( id: UUID = UUID(), name: String, path: String, repositoryURL: URL, remoteURL: URL? = nil ) { self.id = id self.name = name self.path = path self.repositoryURL = repositoryURL self.remoteURL = remoteURL } } public struct MarkdownDocument: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var url: URL public var title: String public var content: String public var attachments: [Attachment] public init( id: UUID = UUID(), url: URL, title: String, content: String, attachments: [Attachment] = [] ) { self.id = id self.url = url self.title = title self.content = content self.attachments = attachments } } public struct Attachment: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var filename: String public var url: URL public var kind: AttachmentKind public var isGitLFSManaged: Bool public init( id: UUID = UUID(), filename: String, url: URL, kind: AttachmentKind, isGitLFSManaged: Bool = false ) { self.id = id self.filename = filename self.url = url self.kind = kind self.isGitLFSManaged = isGitLFSManaged } } public enum AttachmentKind: String, Hashable, Codable, Sendable { case image case pdf case audio case video case binary } public struct GitRepository: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var rootURL: URL public var currentBranch: GitBranch? public var remotes: [GitRemote] public var statusSummary: GitStatusSummary public init( id: UUID = UUID(), name: String, rootURL: URL, currentBranch: GitBranch? = nil, remotes: [GitRemote] = [], statusSummary: GitStatusSummary = .clean ) { self.id = id self.name = name self.rootURL = rootURL self.currentBranch = currentBranch self.remotes = remotes self.statusSummary = statusSummary } } public struct GitRemote: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var url: URL public var fetchURL: URL? public var pushURL: URL? public init( id: UUID = UUID(), name: String, url: URL, fetchURL: URL? = nil, pushURL: URL? = nil ) { self.id = id self.name = name self.url = url self.fetchURL = fetchURL self.pushURL = pushURL } } public struct GitBranch: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var name: String public var isCurrent: Bool public var upstreamName: String? public init( id: UUID = UUID(), name: String, isCurrent: Bool = false, upstreamName: String? = nil ) { self.id = id self.name = name self.isCurrent = isCurrent self.upstreamName = upstreamName } } public struct GitCommit: Identifiable, Hashable, Codable, Sendable { public var id: String public var shortHash: String public var authorName: String public var authorEmail: String public var message: String public var authoredAt: Date public init( id: String, shortHash: String, authorName: String, authorEmail: String, message: String, authoredAt: Date ) { self.id = id self.shortHash = shortHash self.authorName = authorName self.authorEmail = authorEmail self.message = message self.authoredAt = authoredAt } } public struct GitFileStatus: Identifiable, Hashable, Codable, Sendable { public var id: UUID public var path: String public var state: GitFileState public init(id: UUID = UUID(), path: String, state: GitFileState) { self.id = id self.path = path self.state = state } } public enum GitFileState: String, Hashable, Codable, Sendable { case untracked case added case modified case deleted case renamed case conflicted } public enum GitStatusSummary: String, Hashable, Codable, Sendable { case clean case dirty case conflicted case unknown }