Commit Graph
1290 Commits
Author SHA1 Message Date
dotCooCoo 8ecf7fa15d craft-update: self-update tests wait on handshakes instead of time
The Windows helper tests hand step_after_wait a wait that reports when
the helper reaches it and blocks until the test has reaped the stand-in
launcher, so the old-file check no longer depends on a 500 ms sleep or a
2 s observation window. The test-only wait_watch hooks are removed. The
launcher-that-keeps-running test asks the real wait with no timeout
instead of bounding the elapsed time.

The Unix restart test puts a sleep script on the helper's PATH that
reports each pause through a named pipe, and the started command reports
whether the old process was still running. A thread that waits for the
helper to exit writes to the same pipe, so a helper that dies early fails
the test instead of hanging it.
2026-11-07 20:34:29 -08:00
dotCooCoo 10d1cbb4ab craft-update: a check that answers during an installation reports the installation
A requested check still running when the user starts the installation from
the prompt answered with its own result once it finished, which replaced
Installing or Ready with UpToDate, the check error or nothing. Its answer is
now logged, and a requested check reports Installing, Ready or the recorded
helper failure, as a check started during the installation does.
2026-11-07 19:58:28 -08:00
dotCooCoo 75eacfc2a8 craft-update: an offer after a failed update clears the failure status
Updater::offer opens a prompt that carries the failed update's reason, and now sets the status to Idle, as a check that finds a release does. An app that shows CheckResultDialog while the status is not Idle no longer shows the failure card and the prompt at once.
2026-11-07 19:50:28 -08:00
dotCooCoo 53fbd5b636 craft-update: a retry after a failed helper waits for the exit and says why
A new install worker after start_pending_update gets a fresh handoff flag, so
a retry after a helper that failed while the app kept running reports through
tick and starts its helper at the exit, instead of at once. Updater::offer
carries the reason of a failed update into its prompt, as a check does.

The outcome records are read only from plain files: a link is not followed,
as is_plain_file already does for the files it moves. The tests wait for a
check's answer on its channel instead of polling with sleeps.
2026-11-07 19:44:54 -08:00
dotCooCoo 164dcf6a6d craft-update: an install still running at start_pending_update starts its own helper
start_pending_update now marks the Updater as exiting and lets go of an install
that is still running, so the worker starts its helper itself when it finishes
(or records its failure) instead of sending its outcome into a channel nobody
reads. Before, only dropping the Updater did this, so an app that called
start_pending_update in on_exit and kept the Updater alive lost the helper of
an install that finished afterwards. Drop now calls start_pending_update.

The docs of Action::Close and start_pending_update say that an app which ends
the process in on_exit loses an install still in progress.
2026-11-07 18:41:49 -08:00
dotCooCoo a1471f2cf3 craft-update: show_if alone decides whether Restart to Update closes the app
restart_to_update only asks for the close; show_if returns Action::Close
only while an update is ready, so the test of a call with no update
ready fails when that check is removed. The test of a folder in place of
an outcome record is removed: Windows refuses to open a folder, so it
passed with the plain-file check removed.
2026-11-07 18:34:39 -08:00
dotCooCoo 7bde3a7c1e craft-update: record an install worker that ends without an outcome at the exit
start_pending_update now treats a disconnected install worker as a
failed update, as tick does, so the next start says the update stopped
unexpectedly.
2026-11-07 18:09:51 -08:00
dotCooCoo 2411acae5e Merge main into fix/update-messages 2026-11-07 18:05:25 -08:00
dotCooCoo 4c29fc7cd5 craft-update: Check Again after a failed update still says why it failed
A failed update's reason is kept until a prompt that offers the update
again shows it, so a dismissed failure followed by Check Again still
explains the failure. A prompt that already showed the reason does not
repeat it.
2026-11-07 18:05:12 -08:00
058b047760 print: winprint 64e7afd4, whose Direct2D factory is multi-threaded (#605)
Windows.Data.Pdf draws a page on several of its own worker threads, which
share the print control's device context. With winprint 5f80b9b's
single-threaded factory Direct2D takes no locks, so those threads race in
d2d1.dll and the app closes while printing, most often on pages with Type 3
fonts (storytold/pdfcraft#5006, storytold/pdfcraft#2684).
storytold/winprint.rs#11 made the factory multi-threaded; it was merged as
64e7afd4.

craft-winprint-gdi moves to the same revision, so one checkout of
winprint.rs serves both; crates/gdi is unchanged between 417ac3c and
64e7afd4.

Co-authored-by: mertan-wq <235487900+mertan-wq@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 19:42:38 -06:00
dotCooCoo 8ccbe9b2ca craft-update: record every update failure at the exit and clear a stale ready prompt
An installation that finishes after the Updater is dropped now records a
helper that cannot start, and a failed installation, so the next start
reports it. start_pending_update records an installation failure it picks
up at the exit too. When a requested check finds that a started helper
failed, the open prompt no longer offers Restart to Update: it says why
the update could not be installed, and no close is asked for.
2026-11-07 17:37:59 -08:00
dotCooCoo 878d4e712c craft-update: tell the user what happened to an update
A requested check while an update downloads or waits for the app to close
now reports Installing or Ready instead of leaving the result window
blank, and an app the launcher manages reports Managed instead of calling
its version the newest.

On Windows a prepared update says "Update ready. Close {app} to install
it." rather than that it is installed. The helper records the version it
installed just before it starts the new app, and the first start of that
version reports Updated. A recorded helper failure is reported once at the
next start (InstallFailed, with Check Again), in the prompt when the
update is offered again, and to a requested check while the old app still
runs. A failure wins over a stale record of a finished update, and a new
update clears both records. Records are read up to 4 KiB.

Action::Close is now a request: the Windows helper starts only at the exit
(dropping the Updater or start_pending_update in on_exit). A close the
user cancels keeps the update ready, and Restart to Update in the prompt
or the result window (Updater::restart_to_update) asks for the close
again. A helper that cannot start at the exit is recorded and reported at
the next start.

New strings for app catalogs: "Installing update…", "Update ready. Close
{app} to install it.", "Restart to Update", "The update could not be
installed: {reason}", "{app} updated to {version}." and "{app} {version}
follows the version chosen in the launcher, so it does not update itself."
2026-11-07 17:31:45 -08:00
dotCooCoo cbd9abfdc3 craft-update: say that the drop starts the helper only when the app drops the Updater 2026-11-07 17:11:33 -08:00
dotCooCoo da46f3ca20 craft-update: an install that finishes after the updater is dropped starts its helper 2026-11-07 16:34:01 -08:00
dotCooCoo 0e856027c5 craft-update: log an install failure picked up at exit and clear the finished job 2026-11-07 16:27:51 -08:00
dotCooCoo f5f45b090c craft-update: start a waiting update helper when the app exits without Close
The Windows helper of a finished installation started only when show_if
returned Action::Close. An app that exited another way (the window's
close button, a quit while unsaved work held the close back, an OS
shutdown) dropped it, so the update never installed and the download
stayed in the cache.

Dropping the Updater now starts a helper that is still waiting, once,
including one from an installation that finished after the last tick.
Updater::start_pending_update does the same for an app that ends the
process in on_exit without dropping the Updater; Action::Close's doc
comment names it.
2026-11-07 16:23:44 -08:00
dotCooCoo df66c35b07 craft-update: keep the app running when a helper thread cannot start
spawn_detached, run_command and open_url_with_fallback started their
reaper, pipe-reader and opener threads with std::thread::spawn, which
panics when the thread cannot be created. The Windows update helper now
starts from the UI thread when the app closes, so such a panic would end
the app. Each thread now starts through std::thread::Builder: a process
that has already started keeps running and the failed wait is logged,
run_command stops the helper and returns an error, and a failed opener
thread is logged.
2026-11-07 16:19:03 -08:00
dotCooCoo 85de86be60 craft-update: start the Windows update helper when the app closes, and never restart a running app
On Windows the update helper was started as soon as the download was
ready, then waited one minute for the app to exit. An app that held
unsaved work, or a user who did not close it, outlasted that wait; the
helper then started the old exe again with no arguments, which opened a
second window of the old version and installed nothing.

- self_update::prepare_update does what update did but returns a
  Restart. On Windows the Restart records the release as installed and
  starts the helper; on macOS and Linux it does nothing, since the
  restart is already scheduled. update calls prepare_update and starts
  the Restart at once, so its callers see no change.
- Updater starts the Restart when it returns Action::Close. If the
  helper can't start, the app stays open and the prompt shows the error.
- The helper does not start any exe when the app is still running after
  its wait. A step that fails after the app exited still starts the old
  exe, as before.
2026-11-07 16:14:17 -08:00
FredApps 904f55bb21 Merge pull request #571 from dotCooCoo/feat/doc-read-cancellation
craft-doc: allow document reads to be canceled
2026-11-07 15:52:20 +01:00
FredApps 0d0638526a Merge pull request #548 from dotCooCoo/feat/doc-full-size-composite
craft-doc: read the optional full-size PhotoCraft composite
2026-11-07 15:50:02 +01:00
FredApps 946293444a Merge pull request #583 from dotCooCoo/fix/hayro-ccitt-images-feature
PDF: compile the CCITT row helper only with images
2026-11-07 15:48:27 +01:00
FredApps 57f3b0bb6c Pass read control through ICC archive lookup 2026-11-07 15:48:07 +01:00
FredApps 628c4e5ee4 Merge updated rendition test fixtures 2026-11-07 15:45:55 +01:00
FredApps c3456fbf78 Update budget test decoders to the buffered input type 2026-11-07 15:45:26 +01:00
FredApps aed25e8d34 Integrate image-only CCITT guards and combined rendition coverage 2026-11-07 15:44:44 +01:00
FredApps e26f3d1102 Integrate full-composite provenance with cancellable reads 2026-11-07 15:44:13 +01:00
FredApps f766bf10cd Merge main and preserve cancellable selective document reads 2026-11-07 15:43:45 +01:00
FredApps c8ea8be292 Merge main and preserve selected full-composite extraction 2026-11-07 15:40:03 +01:00
FredApps 2396054e77 Merge main and retain image-only CCITT guards 2026-11-07 15:39:40 +01:00
FredApps 481f66d287 Merge pull request #633 from dotCooCoo/chore/vendor-linesweeper
linesweeper: keep a copy of the crates.io 0.5.0 package in vendor/
2026-11-07 15:37:48 +01:00
FredApps d4c71662ad Merge pull request #585 from dotCooCoo/feat/doc-pcraft-icc-profile
craft-doc: read a bounded PhotoCraft ICC payload
2026-11-07 15:37:43 +01:00
FredApps 9fa0111656 Merge pull request #582 from dotCooCoo/fix/hayro-jpx-unused-import
PDF: remove an unused JPX macro import
2026-11-07 15:37:35 +01:00
FredApps 75647cb84a Merge pull request #581 from dotCooCoo/feat/doc-pcraft-document-head
craft-doc: read a caller-defined PhotoCraft document head
2026-11-07 15:37:30 +01:00
FredApps 2eac880de8 Merge pull request #580 from dotCooCoo/fix/hayro-interpret-source-digest
hayro-interpret: refresh the local image-reader digest
2026-11-07 15:37:25 +01:00
FredApps c0e0b2bb75 Merge pull request #577 from dotCooCoo/fix/language-pack-removal-record
font-store: preserve Language packs when removal cannot commit
2026-11-07 15:37:20 +01:00
FredApps dad42b6f3e Merge pull request #573 from dotCooCoo/feat/pdf-parser-cancellation
PDF: allow opening to be canceled during parsing
2026-11-07 15:37:14 +01:00
FredApps a1d91da34d Merge pull request #562 from dotCooCoo/feat/vectorcraft-pdf-preference-read
vectorcraft-format: read PDF preference with document contents
2026-11-07 15:37:07 +01:00
FredApps 57b88511b9 Merge pull request #549 from dotCooCoo/fix/doc-rendition-copy-budget
craft-doc: check rendition copy costs before decompressing
2026-11-07 15:37:02 +01:00
FredApps af6c186f1e Merge pull request #546 from dotCooCoo/feat/doc-selected-rendition
craft-doc: read a selected rendition without extracting other payloads
2026-11-07 15:36:55 +01:00
dotCooCoo c813b55bf7 craft-doc: say what the total budget counts
The max_total and Budget docs now say the budget counts bytes consumed
from gzip, and that unused lookahead from the initial gzip read (chunks
of up to 64 KiB) is not counted.
2026-11-07 06:29:48 -08:00
dotCooCoo 43224b0492 font-store: create Language pack recovery stages through the retained folder
The recovery stage is now created, opened and, when opening fails, removed through
the retained recovery directory handle. A failed open no longer leaves an empty
stage under .removing, and the removal is not recursive. A rollback failure now
names the recovery stage ID next to the pack's last known path.
2026-11-07 01:58:39 -08:00
dotCooCoo f211604aad linesweeper: the copy's README says which workflow a change here does not start
sonarcloud.yml runs on every pull request, so a change only under vendor/linesweeper starts a workflow; it does not start pdf.yml.
2026-11-06 20:51:55 -08:00
dotCooCoo f14cc7f21e linesweeper: keep a copy of the crates.io 0.5.0 package in vendor/
Add the linesweeper 0.5.0 package to vendor/ with no file changed, so
that a fix to it can reach the Craft apps through this repository
without waiting for a linesweeper release. The GitHub repository its
manifest names is archived, and its README says development moved off
GitHub.

Leave out the test font (fonts live in craft-fonts), the logo artwork,
the snapshot images and the package's repository tooling. SOURCE.json
lists each with its hash.

Add a workspace exclude, a [patch.crates-io] entry, SOURCE.json with
the archive hash and per-file hashes, NOTICE and ATTRIBUTION.md rows,
and the package's tests in the backend test script. craft-prepress's
flatten feature now builds against the copy, so Cargo.lock drops the
package's registry source and checksum.
2026-11-06 19:05:18 -08:00
Helen Kwok fd5e2feff6 web-api: drop a timed-out call, and give screenshot() one data field (#620)
A call that timed out left the app's request future running, so an app that releases a request when its future is dropped (the desktop ControlRequest abandons a request nobody waits for) ran the call late, after the page had been told it failed. call() now drives the request future itself and drops it when the timer wins.

The desktop control protocols name the base64 PNG of ui.screenshot differently (pngBase64, png_base64, png, base64), so screenshot() gave the page a different shape in each app. It now also puts the PNG in data and leaves the app's own field where it is.

The timer handle is kept as the environment returned it: Node returns an object, not a number, so a numeric id never cleared the timer and it fired after its closure was dropped.
2026-11-06 16:54:07 +01:00
FredApps 4859d8621d Merge pull request #625 from storytold/house-rules
Copy the shared house rules into AGENTS.md
2026-11-06 11:58:27 +01:00
FredApps 33da2e96ca Copy the shared house rules into AGENTS.md.
The deny-list paragraph and the chrono calendar exception now live in the Rust rules. CLAUDE.md imports AGENTS.md, and the workspace-lints requirement stays with the new-crate notes.
2026-11-06 11:42:42 +01:00
ashandClaude Opus 5.5 a3e0b5a944 craft-print: a job can be cancelled until it starts reaching the spooler (#622)
* craft-print: a job can be cancelled until it starts reaching the spooler

On Windows a job asks the printer's driver for its capabilities before
anything is sent. A networked printer in power save can hold that query
for a long time, and an app had no way to give up on the job without
risking it printing later (storytold/wordcraft#5710; CodeRabbit on
storytold/wordcraft#5732).

A Cancel token, passed to the new submit_cancellable, moves a job from
pending to cancelled or to sending. The job checks it at the last point
before anything reaches the spooler: on Windows after the driver has
answered, before the job file is written; on macOS and Linux before lp
starts. A cancelled job returns an error and is never sent; a job already
being sent completes. submit and submit_with_progress are unchanged, and
Error keeps its one variant so callers that match on it still compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-print: a job turns to sending with the provider held; the job file waits for it

Review: marked as sending before it took the PrintTicket provider, a job
could then wait behind another job's driver call that a sleeping printer
held, and an app that waits only for jobs being sent would wait on it.
The job now turns to sending only once it holds the provider, right
before printing, and writes its file only after that, so a cancelled job
leaves no copy of the document behind.

A test-only hold in the driver call lets the Windows spooler test cancel
a job while its driver doesn't answer: the cancel wins and, once the
driver answers, the job stops instead of reaching the paused queue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-print: the DEVMODE conversion comes before a job turns to sending

CodeRabbit on #622: winprint converts the ticket to a DEVMODE, a driver
call a sleeping printer can stall, before it creates the native job, so
a job stalled there had already turned to sending and couldn't be
cancelled. The conversion now runs first, with the provider held, while
the job can still be cancelled; the provider stays held until the first
copy's own conversion, so no other job comes between them.

Tests: the Windows spooler test also cancels a job held in that
conversion; the CUPS test gives a spooler that can't start, so any
attempt to start it would change the error. README: cancellation in the
progress section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-print: clarify cancellation during winprint conversion repeat

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 21:32:35 -05:00
ashandClaude Opus 5.5 b0b6a9d712 craft-font-catalog: run the Unix font-folder tests only on Unix (#621)
* craft-font-catalog: run the Unix font-folder tests only on Unix

Five tests build an Os::Unix FontEnv from Unix paths (/home/me, <dir>/sys/fonts</dir>).
Windows doesn't treat those paths as absolute, so the tests failed there. Production code
is unaffected: on Windows FontEnv::from_process picks Os::Windows, whose folders never go
through the Unix path logic. FontEnv's docs now say its paths follow the host's path rules.

The font-store workflow, which already triggers on crates/font-catalog, now also runs
craft-font-catalog's clippy and tests on Linux and Windows.

Refs #619

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-font-catalog: keep the store override and no-store tests on Windows

These assertions don't depend on Unix path rules, so they now sit in their own
ungated test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* craft-font-catalog: verify store override precedence

Exercise the override with platform defaults present on every OS variant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 21:30:54 -05:00
FredApps e653048a18 Merge pull request #618 from arnav-hiwarkar/fix/print-queues-without-driver-queries
craft-print: printer_queues lists the queues without asking any driver
2026-11-06 01:35:22 +01:00
arnav-hiwarkarandClaude Opus 5.5 81c2488a09 craft-print: document spooler_list
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 05:07:25 +05:30