Repository navigation
Conversation
Adds provider-neutral craft-ui cloud integration, following the same pattern as wordcraft, deckcraft, and designcraft. craft-ui upgraded from 5c874d51 to 289d562 (rev that carries the cloud feature). craft-cloud, craft-cloud-client, and collabcraft-share added at the matching revs. crates/ui-egui: - CloudApp implementation for PdfCraftApp: PDF-only writes_as, full encode via save_full_bytes, open via open_bytes, close by tab index. Presence is viewer-only: no real-time co-editing is claimed. - paint_on helper in icons.rs for painting SVG icons from a Painter without a Ui (required by CloudApp::paint_icon contract). - cloud.rs and cloud_tests.rs: state machine tests with an in-memory service covering account, conflict, writes_as enforcement, and kind. - lib.rs: CloudFiles, ShareDialog, PresenceBar fields; cloud::pump call added to logic(). - chrome.rs: cloud controls (who badge, share button) placed in the right-to-left section of tab_strip, left of theme/help, no overlap. apps/pdfcraft (desktop): - cloud.rs: blocking worker thread, device-flow sign-in with 300s timeout, conditional writes with etag, Fault::Conflict on 409/412, token file beside app settings (0o600 on Unix), platform-specific browser open (cmd on Windows, open on macOS, xdg-open on Linux). - main.rs: wires cloud::service and collabcraft_share into app.cloud and app.share; absent PDFCRAFT_CLOUD_URL leaves the app local-only. apps/pdfcraft-web (browser): - cloud.rs: async wasm_bindgen_futures transport, same-origin cookie session, no device flow, logout via POST to /auth/logout. - main.rs: wires Service::new(ctx) and CollabCraft::from_env into the app; graceful when not served from a CollabCraft origin.
Two security hardening fixes to the CollabCraft desktop transport. write_private (Unix): replace std::fs::write + set_permissions with OpenOptions::mode(0o600) so the file is created owner-only from the instant of its first inode, closing the write-then-chmod race window. A second set_permissions call tightens any file an older version wrote under a loose umask. Windows path unchanged (AppData is owner-scoped). token_for_service: load_token no longer ignores the stored service URL. The extracted token_for_service helper compares the saved service origin to the currently configured one (normalising trailing slashes). A mismatch logs a warning and returns None, preventing a saved session from being forwarded to a different deployment after the URL env-var changes. Tests added in apps/pdfcraft/src/cloud.rs: - token_accepted_when_service_matches_exactly - token_accepted_when_trailing_slash_differs - token_rejected_when_service_url_changes - token_rejected_when_service_field_absent - empty_token_is_treated_as_absent - write_private_creates_file_with_mode_0600 (Unix) - write_private_tightens_existing_file_with_loose_permissions (Unix)
egui::Ui::new dropped the layer_id parameter in 0.36; remove the extra argument from paint_on in icons.rs. theme::bold does not exist; use FontFamily::Name(semibold) which matches pdfcraft's heading style for cloud column headings.
cloud::start() was only called from open_page() (the File > Open dialog). In the browser build the session rides the same-origin cookie set at craft.quasarke.net login. Without start() in the update loop the app never submitted Job::Account, so app.cloud.account stayed None, the title-bar account badge showed Sign in, and all capability-gated controls (Share, Talk, provider-linked checks) never appeared. Calling start() from update() is idempotent: it guards with asked_account and acts only once. open_page() still calls it too; the second call is a no-op. The new test verifies the account arrives without an explicit start() call, covering the browser cookie path.
After the bootstrap fix (start() in update()), two routing bugs appeared: Sign-out loop: Job::SignOut called window.location().reload(), which reloaded the PDFCraft page, triggering start() -> Job::Account -> Unauthenticated -> offer_login() -> /auth/login immediately. Fixed by navigating to / instead of reloading; the root page has no automatic credential check. Callback landing: the CollabCraft OIDC callback always redirects to / (server limitation, pinned rev 80bfaec). Opening login in a popup window keeps the user on the PDFCraft page. A setInterval closure watches for the popup to close, then stores 'pdfcraft:auth_done' in egui's ephemeral memory and requests a repaint. The update loop consumes the flag, marks a 'popup_retry' (so a cancelled popup does not immediately reopen), and calls sign_in() to force a fresh Job::Account. When the popup is blocked by the browser the transport falls back to the original full-page redirect to /auth/login. Also fix a compile error in the test suite: open_page_lists_root_when_linked referenced cloud.folders which does not exist on CloudFiles; corrected to cloud.mine.loaded. Add sign_out_does_not_leave_unauthenticated_fault which asserts that after sign-out the re-check returns NotLinked (link prompt) rather than Unauthenticated (login redirect), documenting the protocol that prevents the sign-out loop. Co-authored-by: Cursor <cursoragent@cursor.com>
cloud_mut() is a CloudApp trait method; CloudApp is not in scope in update(), which lives in the root lib.rs module. Accessing self.cloud.status directly avoids the missing trait import and is equivalent since PdfCraftApp implements CloudApp with &mut self.cloud. Co-authored-by: Cursor <cursoragent@cursor.com>
web-sys Window::closed() is fallible in this version. Use unwrap_or(true) so a JS error treats the popup as closed. Co-authored-by: Cursor <cursoragent@cursor.com>
…trip entry points - Add CloudPage enum (Open, SaveAs) and cloud_page field to PdfCraftApp - Render craft_ui::cloud::open_page in CentralPanel when cloud_page = Open - Render craft_ui::cloud::save_page in CentralPanel when cloud_page = SaveAs - cloud_page_shell wraps pages with scrollable frame, heading, and Back button - Auto-dismiss Open page once a new document tab appears after cloud open - Implement go_to_save_as() so conflict modal can redirect to cloud Save As - file.save routes to cloud::save() when document has a cloud origin (etag write) - file.open_cloud and file.save_as_cloud commands added to File menu - Commands absent (not just dimmed) when no cloud service is connected - Tab strip Open button becomes popup (local/cloud) when cloud is available - Accessibility/regression tests: visible headings, Back button, command availability, cloud open/save exercised from UI state path, etag write verified, go_to_save_as tested
…minimal_pdf, fix FnOnce in shapes_from_page
… rendered text shape
Co-authored-by: Cursor <cursoragent@cursor.com>
Unblocks ui-egui catalog tests for cloud menu labels and command ids. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Pins craft-esign UI and collab-craft client; host worker submits envelopes beside cloud Open/Save. Co-authored-by: Cursor <cursoragent@cursor.com>
…ument. Co-authored-by: Cursor <cursoragent@cursor.com>
Fold esign-ui into the upstream cloud PR so Request signatures ships with Open/Save/Share. Co-authored-by: Cursor <cursoragent@cursor.com>
2 tasks
Author
|
Request signatures (CollabCraft e-sign UI) is now on this branch: merge of |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Integrate CollabCraft cloud Open/Save/Share/presence for PDFCraft.
Note: Diff is huge mostly from i18n
.tsvline churn, not new feature surface. Needs rebase — conflicting; consider dropping accidental i18n rewrites before review.Related to storytold/craft-libs#123 (Add collab-craft repo and accept transfer).