mirror of
https://github.com/kfattic/cupsadmin.git
synced 2026-11-13 19:06:43 -05:00
Flag queues whose driver filters need Rosetta or are missing
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -210,7 +210,8 @@ struct SidebarView: View {
|
||||
List(selection: $selection) {
|
||||
Section("Printers") {
|
||||
ForEach(filtered) { printer in
|
||||
PrinterRow(printer: printer, isDefault: store.defaultPrinter == printer.name)
|
||||
PrinterRow(printer: printer, isDefault: store.defaultPrinter == printer.name,
|
||||
driverWarning: store.driverFilters[printer.name]?.headline)
|
||||
.tag(printer.name)
|
||||
.contextMenu { menu(for: printer) }
|
||||
}
|
||||
@@ -311,6 +312,8 @@ struct QuickActionItems: View {
|
||||
struct PrinterRow: View {
|
||||
let printer: PrinterSummary
|
||||
var isDefault = false
|
||||
/// "Driver needs Rosetta" / "Driver filter missing", added to the tooltip.
|
||||
var driverWarning: String?
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 8) {
|
||||
@@ -339,7 +342,7 @@ struct PrinterRow: View {
|
||||
}
|
||||
}
|
||||
.badge(printer.jobCount)
|
||||
.help(printer.stateSummary)
|
||||
.help(driverWarning.map { "\(printer.stateSummary) · \($0)" } ?? printer.stateSummary)
|
||||
.accessibilityElement(children: .combine)
|
||||
.accessibilityValue(printer.stateSummary)
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ enum JobFilter: String, CaseIterable, Identifiable {
|
||||
final class PrinterDetailModel {
|
||||
let queue: String
|
||||
private(set) var printer: IPPGroup?
|
||||
/// Intel-only or missing driver filters, from the queue's PPD.
|
||||
private(set) var driverFilters: DriverFilterReport?
|
||||
private(set) var jobs: [JobSummary] = []
|
||||
private(set) var loadError: String?
|
||||
private(set) var isWorking = false
|
||||
@@ -73,6 +75,11 @@ final class PrinterDetailModel {
|
||||
do {
|
||||
printer = try await store.client.getPrinterAttributes(queue: queue, requested: Self.headerAttributes)
|
||||
loadError = nil
|
||||
if let text = try await store.client.getPPD(queue: queue) {
|
||||
driverFilters = await Task.detached { DriverFilterCheck.check(PPD(text: text)) }.value
|
||||
} else {
|
||||
driverFilters = nil
|
||||
}
|
||||
} catch {
|
||||
loadError = String(describing: error)
|
||||
store.report("ERROR: \(queue): \(error)")
|
||||
|
||||
@@ -12,7 +12,7 @@ struct PrinterDetailView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
if let printer = model.printer {
|
||||
PrinterHeaderView(printer: printer, ppdPath: model.ppdPath)
|
||||
PrinterHeaderView(printer: printer, ppdPath: model.ppdPath, driverFilters: model.driverFilters)
|
||||
Divider()
|
||||
} else if let error = model.loadError {
|
||||
ContentUnavailableView("Can’t Load \(model.queue)", systemImage: "exclamationmark.triangle",
|
||||
@@ -35,6 +35,7 @@ struct PrinterDetailView: View {
|
||||
struct PrinterHeaderView: View {
|
||||
let printer: IPPGroup
|
||||
let ppdPath: String?
|
||||
let driverFilters: DriverFilterReport?
|
||||
|
||||
private var state: Int? { printer.int("printer-state") }
|
||||
private var accepting: Bool { printer.bool("printer-is-accepting-jobs") ?? true }
|
||||
@@ -64,6 +65,13 @@ struct PrinterHeaderView: View {
|
||||
}
|
||||
LabeledContent("Accepting jobs", value: accepting ? "Yes" : "No")
|
||||
LabeledContent("Shared", value: printer.bool("printer-is-shared") == true ? "Yes" : "No")
|
||||
if let headline = driverFilters?.headline {
|
||||
LabeledContent("Driver") {
|
||||
Label(headline, systemImage: "exclamationmark.triangle.fill")
|
||||
.symbolRenderingMode(.multicolor)
|
||||
}
|
||||
.help(driverFilters?.detail ?? headline)
|
||||
}
|
||||
}
|
||||
}
|
||||
Form {
|
||||
@@ -93,7 +101,7 @@ struct PrinterHeaderView: View {
|
||||
.formStyle(.grouped)
|
||||
.scrollDisabled(true)
|
||||
.textSelection(.enabled)
|
||||
.frame(height: 262)
|
||||
.frame(height: driverFilters?.isFlagged == true ? 300 : 262)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,8 @@ final class PrinterStore {
|
||||
private(set) var defaultPrinter: String?
|
||||
/// Driver PPD + IPP attributes per queue, for enabling Quick Actions.
|
||||
private(set) var drivers: [String: DriverContext] = [:]
|
||||
/// Filter check per queue (Intel-only or missing filters), from the cached PPDs.
|
||||
private(set) var driverFilters: [String: DriverFilterReport] = [:]
|
||||
var failure: Failure?
|
||||
|
||||
let client = CupsClient()
|
||||
@@ -201,6 +203,11 @@ final class PrinterStore {
|
||||
for printer in printers where drivers[printer.name] == nil {
|
||||
if let context = try? await DriverContext.load(client: client, queue: printer.name) {
|
||||
drivers[printer.name] = context
|
||||
if let ppd = context.ppd {
|
||||
driverFilters[printer.name] = await Task.detached { DriverFilterCheck.check(ppd) }.value
|
||||
} else {
|
||||
driverFilters[printer.name] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user