diff --git a/assets/webui/index.html b/assets/webui/index.html
index d340de3..096776f 100644
--- a/assets/webui/index.html
+++ b/assets/webui/index.html
@@ -684,7 +684,7 @@
-
+
diff --git a/assets/webui/ofdgo_print.js b/assets/webui/ofdgo_print.js
index 0397d7d..f833ddb 100644
--- a/assets/webui/ofdgo_print.js
+++ b/assets/webui/ofdgo_print.js
@@ -37,7 +37,9 @@ export class PrintDialog {
this.side = 0;
this.sequence++;
this.el.Form.reset();
- this.mode = null;
+ this.orientation = this.el.Orientation.value;
+ this.duplexBeforeBooklet = this.el.Duplex.value;
+ this.scalingBeforeBooklet = this.el.Scaling.value;
try {
const saved = JSON.parse(localStorage.getItem("ofdgo.print.v2") || "null");
for (const [name, value] of Object.entries(saved || {})) {
@@ -46,6 +48,7 @@ export class PrintDialog {
else if (node && typeof value === "string") node.value = value;
}
} catch {}
+ this.mode = this.el.Mode.value;
if (this.el.BookletSheets.value === "0") this.el.BookletSheets.value = "";
this.el.Scope.value = context.selection.length ? "selected" : "all";
this.el.Scope.querySelector('option[value="selected"]').disabled = !context.selection.length;
@@ -64,12 +67,16 @@ export class PrintDialog {
this.loading = true;
this.controls();
this.el.Printer.innerHTML = this.printerOptions;
+ const browser = this.el.Printer.querySelector('option[value="browser"]');
+ browser.disabled = !!this.nativeHost || typeof window.print !== "function";
+ if (browser.disabled) this.el.Printer.value = "pdf";
try {
if (this.nativeHost) {
- this.el.Printer.querySelector('option[value="browser"]').textContent = "系统打印";
+ browser.textContent = "系统打印";
const capabilities = await this.nativeHost.call("print.capabilities", {});
if (!this.current(sequence)) return;
this.capabilities = capabilities;
+ browser.disabled = !capabilities.systemDialog;
const printers = capabilities.direct ? await this.nativeHost.call("print.printers", {}) : [];
if (!this.current(sequence)) return;
for (const printer of printers) this.el.Printer.add(new Option(printer.name, `device:${printer.name}`));
@@ -114,7 +121,7 @@ export class PrintDialog {
this.el.Orientation.value = profile.options.orientation;
this.el.Copies.max = Math.min(999, profile.maxCopies || 999);
this.el.Copies.value = 1;
- this.el.Grayscale.checked = !profile.color;
+ this.el.Grayscale.checked = profile.options.color === "grayscale";
this.el.Grayscale.disabled = !profile.color;
this.el.Properties.hidden = !profile.properties;
} else this.el.Grayscale.disabled = false;
@@ -125,11 +132,12 @@ export class PrintDialog {
async properties() {
if (!this.isDevice() || this.running || this.loading) return;
+ const sequence = this.sequence;
this.loading = true;
this.controls();
try { await this.nativeHost.call("print.properties", {printer:this.el.Printer.value.slice(7)}); }
- catch (error) { this.el.Status.textContent = error.message; }
- finally { this.loading = false; if (this.current()) await this.choosePrinter(); }
+ catch (error) { if (this.current(sequence)) this.el.Status.textContent = error.message; }
+ finally { if (this.current(sequence)) { this.loading = false; await this.choosePrinter(); } }
}
deviceOptions() {
@@ -150,7 +158,7 @@ export class PrintDialog {
return value;
};
let [paperWidth, paperHeight] = el.Paper.value === "source" ? [0, 0] : el.Paper.value === "custom" ? [number("Width"), number("Height")] : el.Paper.value.split(",").map(Number);
- if (el.Orientation.value === "landscape" && paperWidth < paperHeight) [paperWidth, paperHeight] = [paperHeight, paperWidth];
+ if (el.Orientation.value === "landscape") [paperWidth, paperHeight] = [paperHeight, paperWidth];
if (profile) [paperWidth, paperHeight] = [profile.width, profile.height];
const scope = el.Scope.value;
const [rows, columns] = el.Grid.value.split(",").map(Number);
@@ -164,9 +172,9 @@ export class PrintDialog {
margins:{top:number("MarginTop"), right:number("MarginRight"), bottom:number("MarginBottom"), left:number("MarginLeft")},
...(profile ? {printableArea:{x:profile.printableArea.x, y:profile.printableArea.y, w:profile.printableArea.width, h:profile.printableArea.height}} : {}),
copies:this.isDevice() ? number("Copies") : 1, collate:el.Collation.checked, duplex,
- scale:number("Scale") / 100, rotate:el.Rotate.checked, reverse:el.Reverse.checked !== (manual && el.Sides.value === "back" && el.BackReverse.checked), parity:el.Parity.value, sides:el.Sides.value,
+ scale:el.Scale.disabled ? 1 : number("Scale") / 100, rotate:el.Rotate.checked, reverse:el.Reverse.checked !== (manual && el.Sides.value === "back" && el.BackReverse.checked), parity:el.Parity.value, sides:el.Sides.value,
backRotate:manual && el.BackRotate.checked,
- rows, columns, pageOrder:el.PageOrder.value, gap:number("Gap"), binding:el.Binding.value, bookletSheets:el.BookletSheets.value ? number("BookletSheets") : 0, overlap:number("Overlap"),
+ rows, columns, pageOrder:el.PageOrder.value, gap:el.Gap.disabled ? 0 : number("Gap"), binding:el.Binding.value, bookletSheets:!el.BookletSheets.disabled && el.BookletSheets.value ? number("BookletSheets") : 0, overlap:el.Overlap.disabled ? 0 : number("Overlap"),
...(el.Mode.value === "booklet" ? {sheetFrom:el.SheetFrom.value ? number("SheetFrom") : 0, sheetTo:el.SheetTo.value ? number("SheetTo") : 0} : {}),
contents:el.Contents.value, grayscale:el.Grayscale.checked, borders:el.Borders.checked, cropMarks:el.CropMarks.checked, raster:el.Raster.checked, dpi:number("DPI"), tileOnlyLarge:el.TileOnlyLarge.checked, labels:el.Labels.checked
};
@@ -201,6 +209,7 @@ export class PrintDialog {
const rows = {device:this.isDevice(), sides:el.Duplex.value !== "simplex", manual:isManual, range:el.Scope.value === "range", paper:el.Paper.value === "custom", scale:el.Scaling.value === "custom" || mode === "poster", multiple:mode === "multiple", gap:mode === "multiple" || mode === "booklet", booklet:mode === "booklet", poster:mode === "poster"};
for (const row of el.Panel.querySelectorAll("[data-print-row]")) {
row.hidden = !rows[row.dataset.printRow];
+ for (const input of row.querySelectorAll("input, select")) input.disabled = row.hidden;
}
el.Scaling.disabled = mode === "poster" || mode === "booklet";
el.DPI.disabled = !el.Raster.checked && !el.Grayscale.checked;
@@ -246,7 +255,8 @@ export class PrintDialog {
current(sequence = this.sequence) { return this.el.Panel.open && sequence === this.sequence && this.context && !this.context.tab.closed; }
async preview(index) {
- if (!this.layout || this.running || index < 0 || index >= this.layout.sides.length) return;
+ if (!this.layout || this.running) return;
+ if (!Number.isInteger(index) || index < 0 || index >= this.layout.sides.length) { this.controls(); return; }
const sequence = this.sequence, preview = this.previewSequence = (this.previewSequence || 0) + 1;
this.side = index;
this.controls();
@@ -266,7 +276,7 @@ export class PrintDialog {
this.previewURL = url;
this.el.Preview.replaceChildren(img);
this.resize();
- } catch (error) { if (this.current(sequence)) { this.el.Status.textContent = error.message; this.layout = null; this.controls(); } }
+ } catch (error) { if (this.current(sequence) && preview === this.previewSequence) { this.el.Status.textContent = error.message; this.layout = null; this.controls(); } }
}
resize() {
@@ -336,7 +346,7 @@ export class PrintDialog {
if (!this.current(sequence)) throw new DOMException("打印已取消", "AbortError");
this.previousTitle = document.title;
document.title = context.name;
- this.waiting = job.deviceOptions ? "native" : "browser";
+ this.waiting = this.nativeHost ? "native" : "browser";
this.controls();
this.el.Status.textContent = job.deviceOptions ? "正在提交打印作业" : "正在打开打印窗口";
if (job.deviceOptions) {
@@ -353,6 +363,7 @@ export class PrintDialog {
const capabilities = await this.nativeHost.call("print.capabilities", {});
if (!this.current(sequence)) throw new DOMException("打印已取消", "AbortError");
if (!capabilities.systemDialog) throw new Error("当前运行时不支持系统打印");
+ if (!capabilities.dialogCompletion) this.waiting = "browser";
await this.nativeHost.call("print.dialog", {kind:"system"});
if (this.current(sequence) && capabilities.dialogCompletion) this.finishPrint();
} else if (typeof window.print === "function") window.print();