feat(reports): streamline reader actions and center export dialog
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,35 +1,5 @@
|
||||
/**
|
||||
* Client-side print export for the personal report.
|
||||
*
|
||||
* Deliberately print-only: `await document.fonts.ready` then `window.print()`.
|
||||
* It never requests a server-side PDF endpoint, never launches a headless
|
||||
* browser, and never rasterizes pixels: the user's own browser and OS render
|
||||
* the PDF.
|
||||
*/
|
||||
/** Browser restrictions for the local Markdown export dialog. */
|
||||
|
||||
export interface PrintPersonalReportOptions {
|
||||
/** Title used as the browser's default PDF filename (document.title). */
|
||||
title?: string;
|
||||
}
|
||||
|
||||
/** Sanitize a report id into a safe PDF filename fragment (no path/query chars). */
|
||||
export function safeReportFilename(reportId: string): string {
|
||||
const cleaned = String(reportId ?? "")
|
||||
.replace(/[^a-zA-Z0-9_-]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "")
|
||||
.slice(0, 64);
|
||||
return cleaned.length > 0 ? `jyotisha-report-${cleaned}` : "jyotisha-report";
|
||||
}
|
||||
|
||||
export function isPrintSupported(): boolean {
|
||||
return typeof window !== "undefined" && typeof window.print === "function";
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect environments whose built-in browser cannot print reliably.
|
||||
* WeChat's in-app browser is the known case; it should ask users to open the
|
||||
* page in the system browser instead of producing a broken printout.
|
||||
*/
|
||||
export function detectPrintRestriction(userAgent?: string): {
|
||||
restricted: boolean;
|
||||
message?: string;
|
||||
@@ -43,30 +13,3 @@ export function detectPrintRestriction(userAgent?: string): {
|
||||
}
|
||||
return { restricted: false };
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for web fonts, then open the browser print dialog.
|
||||
* The page/PDF layout is computed on the user's device; nothing is uploaded.
|
||||
*/
|
||||
export async function printPersonalReport(options: PrintPersonalReportOptions = {}): Promise<void> {
|
||||
if (typeof window === "undefined" || typeof window.print !== "function") {
|
||||
return;
|
||||
}
|
||||
const fonts = typeof document !== "undefined" ? document.fonts : undefined;
|
||||
if (fonts && typeof fonts.ready?.then === "function") {
|
||||
await fonts.ready;
|
||||
}
|
||||
const previousTitle = typeof document !== "undefined" ? document.title : "";
|
||||
const requested = typeof options.title === "string" ? options.title.trim() : "";
|
||||
if (typeof document !== "undefined" && requested.length > 0) {
|
||||
// Browsers derive the default PDF filename from document.title.
|
||||
document.title = requested;
|
||||
}
|
||||
try {
|
||||
window.print();
|
||||
} finally {
|
||||
if (typeof document !== "undefined") {
|
||||
document.title = previousTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export const PERSONAL_REPORT_LEGACY_PLACEHOLDER = "旧版本报告,请重新生成";
|
||||
export const PERSONAL_REPORT_GENERATING_COPY = "正在生成报告,大约 10–30 秒";
|
||||
export const PERSONAL_REPORT_EXPORT_LABEL = "分块导出";
|
||||
export const PERSONAL_REPORT_PRINT_LABEL = "打印";
|
||||
|
||||
Reference in New Issue
Block a user