From 3d8dba12aad1a80036cf6bdf751e5305611c3a02 Mon Sep 17 00:00:00 2001 From: "douboer@gmail.com" Date: Mon, 16 Mar 2026 09:00:35 +0800 Subject: [PATCH] update at 2026-03-16 09:00:35 --- assets/bg_default.png | Bin 0 -> 31869 bytes calendar/scripts/export-kindle-background.sh | 1 + .../scripts/export-kindle-background.swift | 53 ++- calendar/src/components/AnalogClock.vue | 15 +- calendar/src/components/CalendarCard.vue | 124 +++---- calendar/src/components/QuoteCard.vue | 7 +- calendar/src/components/WeatherCard.vue | 100 +++--- calendar/src/components/WeatherGlyph.vue | 1 + calendar/src/lib/icon-assets.ts | 10 + calendar/src/style.css | 58 ++-- dash/README.md | 14 +- ...ndle-voyage-5.13.6-dual-ssh-playbook-zh.md | 5 +- ...e-voyage-5.13.6-white-screen-handoff-zh.md | 317 ++++++++++++++++++ dash/docs/layered-clock-plan.zh.md | 43 +++ dash/src/dash.sh | 107 +++++- dash/src/debug-off.sh | 6 +- dash/src/debug-on.sh | 6 +- dash/src/local/clock-index.sh | 20 +- dash/src/local/env.sh | 33 +- dash/src/local/render-clock.lua | 157 +++++++++ dash/src/local/render-clock.sh | 67 ++-- dash/src/start.sh | 4 +- dash/src/stop.sh | 56 +++- scripts/sync-layered-clock-to-kindle.sh | 3 +- 24 files changed, 974 insertions(+), 233 deletions(-) create mode 100644 assets/bg_default.png create mode 100644 dash/docs/kindle-voyage-5.13.6-white-screen-handoff-zh.md create mode 100644 dash/src/local/render-clock.lua diff --git a/assets/bg_default.png b/assets/bg_default.png new file mode 100644 index 0000000000000000000000000000000000000000..f866c48c9da35e98220995d5c42947dfa4919d52 GIT binary patch literal 31869 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 E1^W{IyZ`_I literal 0 HcmV?d00001 diff --git a/calendar/scripts/export-kindle-background.sh b/calendar/scripts/export-kindle-background.sh index 4d1038f..160af85 100644 --- a/calendar/scripts/export-kindle-background.sh +++ b/calendar/scripts/export-kindle-background.sh @@ -18,6 +18,7 @@ trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT INT TERM sleep 1 /usr/bin/swift "$CALENDAR_DIR/scripts/export-kindle-background.swift" "$URL" "$OUT_PNG" "$OUT_REGION" + node "$CALENDAR_DIR/scripts/generate-dashboard-manifest.mjs" >/dev/null cat "$OUT_REGION" diff --git a/calendar/scripts/export-kindle-background.swift b/calendar/scripts/export-kindle-background.swift index ad0e1a7..45b2c79 100644 --- a/calendar/scripts/export-kindle-background.swift +++ b/calendar/scripts/export-kindle-background.swift @@ -2,6 +2,8 @@ import AppKit import Foundation +import ImageIO +import UniformTypeIdentifiers import WebKit enum ExportError: Error, CustomStringConvertible { @@ -29,7 +31,8 @@ final class SnapshotExporter: NSObject, WKNavigationDelegate { private let pngOutputURL: URL private let regionOutputURL: URL private let completion: (Result) -> Void - private let targetSize = CGSize(width: 1024, height: 600) + // 直接按 Kindle Voyage 的系统屏保尺寸导出,避免额外旋转和补边。 + private let targetSize = CGSize(width: 1072, height: 1448) private lazy var window: NSWindow = { let window = NSWindow( @@ -129,16 +132,52 @@ final class SnapshotExporter: NSObject, WKNavigationDelegate { image.draw(in: NSRect(origin: .zero, size: targetSize)) normalizedImage.unlockFocus() - guard - let tiffRepresentation = normalizedImage.tiffRepresentation, - let bitmap = NSBitmapImageRep(data: tiffRepresentation), - let pngData = bitmap.representation(using: .png, properties: [:]) - else { + guard let sourceCGImage = normalizedImage.cgImage(forProposedRect: nil, context: nil, hints: nil) else { + throw ExportError.pngEncodingFailed(url.path) + } + + let width = Int(targetSize.width) + let height = Int(targetSize.height) + let colorSpace = CGColorSpaceCreateDeviceGray() + + // 输出 8-bit 灰度 PNG,但页面本身仍按纯白底和纯黑字设计,避免额外灰阶装饰。 + guard let context = CGContext( + data: nil, + width: width, + height: height, + bitsPerComponent: 8, + bytesPerRow: 0, + space: colorSpace, + bitmapInfo: CGImageAlphaInfo.none.rawValue + ) else { + throw ExportError.pngEncodingFailed(url.path) + } + + context.setFillColor(gray: 1, alpha: 1) + context.fill(CGRect(x: 0, y: 0, width: width, height: height)) + context.interpolationQuality = .high + context.draw(sourceCGImage, in: CGRect(x: 0, y: 0, width: width, height: height)) + + guard let grayscaleImage = context.makeImage() else { throw ExportError.pngEncodingFailed(url.path) } try FileManager.default.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true) - try pngData.write(to: url) + + guard let destination = CGImageDestinationCreateWithURL( + url as CFURL, + UTType.png.identifier as CFString, + 1, + nil + ) else { + throw ExportError.pngEncodingFailed(url.path) + } + + CGImageDestinationAddImage(destination, grayscaleImage, nil) + + guard CGImageDestinationFinalize(destination) else { + throw ExportError.pngEncodingFailed(url.path) + } } private func saveRegion(region: [String: NSNumber]) throws { diff --git a/calendar/src/components/AnalogClock.vue b/calendar/src/components/AnalogClock.vue index 24b5929..3335787 100644 --- a/calendar/src/components/AnalogClock.vue +++ b/calendar/src/components/AnalogClock.vue @@ -58,8 +58,7 @@ const stageStyle = computed(() => ({ :style="stageStyle" data-clock-region="true" > -
-