import Foundation // Credentials for connecting to the PDS struct PDSCredentials: Sendable { var serverURL: String var username: String var password: String init?(serverURL: String, username: String, password: String) { // Validate inputs guard !serverURL.isEmpty, !username.isEmpty, !password.isEmpty else { return nil } self.serverURL = serverURL self.username = username self.password = password } } // Invite code model struct InviteCode: Identifiable, Sendable { var id: String var code: String { id } // For compatibility with the view var uses: [CodeUse]? var createdAt: Date var disabled: Bool var isDisabled: Bool { disabled } // For backwards compatibility } // Invite use model struct CodeUse: Codable, Identifiable, Sendable { var id: String { usedBy } var usedBy: String var usedAt: String } // User model class PDSUser: Identifiable, Hashable, Sendable, ObservableObject { let id: String // DID let joinedAt: Date let avatar: URL? @Published var handle: String @Published var displayName: String @Published var description: String @Published var isActive: Bool = true init(id: String, handle: String, displayName: String, description: String, joinedAt: Date, avatar: URL?, isActive: Bool = true) { self.id = id self.handle = handle self.displayName = displayName self.description = description self.joinedAt = joinedAt self.avatar = avatar self.isActive = isActive } // Add Hashable conformance func hash(into hasher: inout Hasher) { hasher.combine(id) } static func == (lhs: PDSUser, rhs: PDSUser) -> Bool { lhs.id == rhs.id } } // Auth state enum AuthState: Sendable { case loggedOut case loggedIn } // View state enum ViewTab: Sendable { case inviteCodes case userList }