Skip to content

feat(drive): Google Slides editing via presentations.batchUpdate #1630

Description

@newhoggy

Summary

Split out of #1615, which covered Docs and Slides together. #1615 is now the
Docs tracker (phase 1, the read surface, is #1628); this issue is the
Slides half.

The split follows #1615's own suggestion: Docs and Slides "have little in
common beyond the client scaffolding", and the Docs work has since confirmed
that — essentially none of its design carries over.

What is already free

GoogleApiClient (src/drive/api_client.rs) is the host-agnostic transport:
OAuth session, 401 refresh-and-retry, quota backoff, request logging, and
error-envelope parsing for both Google shapes. A SlidesClient is a ~50-line
wrapper — a DEFAULT_BASE_URL of https://slides.googleapis.com, a
SLIDES_API_URL env override, a distinct type so FilesApi can't be pointed
at it, and an api_name.

src/drive/docs/client.rs is now a second worked example alongside
src/drive/sheets/client.rs, so this part is mechanical. Note the four
EnvGuard sites in src/drive/test_support.rsredirect_api_hosts_to_a_dead_port
is the one whose omission is silent, because the test still passes while
talking to Google.

src/drive/docs/target.rs already refuses a presentation with its own
message ("Google Slides has no drive slides surface yet"), so that arm just
needs repointing when this lands.

What does not carry over from Docs

Almost everything above the transport:

  • Slides is an object graph, not an index model. Content lives in page
    elements (shapes, tables, images) addressed by objectId, not by a numeric
    offset into a linear body. So the UTF-16-code-unit reasoning, the structural
    flattener (src/drive/docs/structure.rs), and the whole "never compute an
    index" stance are Docs-specific — though insertText into a shape does
    take an insertion index, so the trap reappears at a smaller scale.
  • There is no body to read. A presentation read is a slide list with
    per-slide page elements, so docs read's flat element table has no direct
    analogue.
  • Tabs have no counterpart, so the "always fetch every tab" decision does
    not apply — but check whether presentations.get has its own partial-response
    trap before assuming it doesn't.

Questions to settle before implementing

  • Which verbs? replaceAllText is the index-free, safest write and the
    obvious first one (it exists on both APIs). createSlide is additive.
    deleteObject is the sharp edge and probably excluded from v1, mirroring
    how feat(drive): structural sheet edits via spreadsheets.batchUpdate #1613 excludes deletion for Sheets.
  • Does it need its own gate operation? Almost certainly slides-write, by
    the argument ADR-0073 §3 makes and
    ADR-0076 §2 makes again: an operator who granted edit, sheets-write or docs-write did so
    when Slides was unreachable, and reusing any of them would widen those grants
    with no config change and no re-consent.
  • Does the revision lease apply? presentations.batchUpdate also takes
    writeControl.requiredRevisionId. If so, ADR-0076 §3's "leased uniformly, no
    escape hatch, targetRevisionId unrepresentable" design should transfer
    wholesale — that part is shared, and it would be the strongest argument for
    doing Slides after Docs rather than before.
  • What does --dry-run report for an object-graph mutation?

Suggestion

Read/export before edit, as in Docs: a read surface first, then an ADR, then
the mutating verbs.

Refs #1615, #1628, #1639, ADR-0071 §9, ADR-0073 §1, ADR-0076

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions