Skip to content

Google Drive integration + GitHub lastModifiedUtc back-fill#1478

Open
pablo-mayrgundter wants to merge 11 commits intobldrs-ai:mainfrom
pablo-mayrgundter:feature/google-drive-integration
Open

Google Drive integration + GitHub lastModifiedUtc back-fill#1478
pablo-mayrgundter wants to merge 11 commits intobldrs-ai:mainfrom
pablo-mayrgundter:feature/google-drive-integration

Conversation

@pablo-mayrgundter
Copy link
Copy Markdown
Member

Summary

  • Connections & Sources framework: New SourcesTab and ConnectProviderButton architecture for pluggable file sources; Google Drive provider with OAuth popup flow and file picker
  • Open dialog redesign: Added Sources tab (Google Drive); GitHub tab now shows recent files + browse flow rather than the file browser directly; AccountFooter component for connected account display
  • GitHub lastModifiedUtc back-fill: Two-path approach to populate the last-modified date in recent file entries:
    • OPFS path (primary): fetchLatestCommitHash now returns {hash, date}; date stored as LastModifiedGithub header in HTTP cache and forwarded via worker postMessage; Loader.js callback writes to persistence.ts
    • Hook fallback (useGithubLastModified): Direct commits API call in Share.jsx for non-OPFS browsers
    • Bug fix: useGithubLastModified was passing modelPath.filepath (no leading slash) directly to navigateBaseOnModelPath, producing a malformed ID that never matched any stored entry — silently a no-op

Test plan

  • Load a GitHub model via the file browser; confirm lastModifiedUtc is populated in the recent files list on next visit
  • Load the same model a second time (OPFS cache hit); confirm the date persists
  • Verify Google Drive OAuth connect flow opens popup and shows picker
  • yarn test passes (was previously failing on GitHubFileBrowser.test and OpenModelControl.test due to pre-existing UI changes — both fixed in this PR)
  • yarn lint passes

🤖 Generated with Claude Code

rpstohr-prim and others added 10 commits March 5, 2026 10:35
Introduces an extensible two-level architecture for connecting external
storage providers:
- Connections: auth-level bindings (Google account, GitHub account, etc.)
- Sources: specific browsable storage locations (Drive folders, repos)

Google Drive is the first fully implemented provider using Google Identity
Services (GIS) for OAuth and the native Google Picker API for file/folder
selection. Files download via OAuth-authenticated Drive API and load through
the existing OPFS/uploaded-file pipeline.

New "Sources" tab in the Open dialog lets users connect Google Drive,
add folder sources, browse files, and open BIM/CAD models directly.

Framework is designed for future providers (OneDrive, Dropbox, GitHub
migration, enterprise storage) via ConnectionProvider and SourceBrowser
interfaces.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds the two new environment variables needed for Google Drive OAuth
and Picker API alongside the existing GOOGLE_API_KEY in the esbuild
vars config chain (prod → cypress → dev).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The parseFloat branch in parse() was converting values like
"123456-abc.apps.googleusercontent.com" to the number 123456,
discarding the rest of the string. This broke GOOGLE_OAUTH2_CLIENT_ID.

Added a full-string equality check (matching the parseInt branch's
pattern) so parseFloat only applies when the entire string is numeric.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GIS fires error_callback with popup_closed while the user is still
completing authentication on some browsers. This was rejecting the
promise and showing an error before auth could complete.

Now popup_closed is ignored — real auth failures come through the
main callback with response.error instead. Also added settled guards
to prevent double-resolve/reject of the promise.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add console logging to GoogleDriveProvider for debugging auth flow
- Handle fetchUserEmail failure gracefully (still resolves connection)
- Wait 1s after popup_closed before rejecting (GIS timing issue)
- Update proxy.js cert paths for local HTTPS dev server
- Fix .gitignore typo: *.pen → *.pem
- Version bump to 1.0.1900

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents infinite spinner if GIS callback never fires by adding a 120s
overall timeout, 5s email-fetch timeout, and centralized settle helper.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
UI changes:
- URL paste section removed; Browse button moved below recent files, right-aligned
- Account title uses subtitle1/bold, left-aligned
- Dates older than 5 days display as locale date with year

Lint fixes (pre-existing):
- Extract magic numbers to named constants in GoogleDriveProvider/PickerDialog
- Replace console.log with debug() in GoogleDriveProvider
- Add JSDoc to registry, loadGisScript, generateId
- Remove async from checkStatus and pickLocation (no await needed)
- Fix empty revoke callback and stale eslint-disable directives

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- OPFS.worker.js: fetchLatestCommitHash now returns {hash, date}; the
  commit date is stored as LastModifiedGithub header in the HTTP cache
  and included in all completed postMessage events
- utils.js: downloadModel accepts an onLastModifiedGithub callback that
  fires whenever any completed message carries the date (handles both
  immediate 'exists' and deferred 'renamed' events after Promise resolves)
- Loader.js: passes callback to downloadModel; constructs sharePath via
  navigateBaseOnModelPath and calls updateRecentFileLastModified
- persistence.ts: adds updateRecentFileLastModified and
  updateRecentFileModelTitle helpers
- Share.jsx: mounts useGithubLastModified hook as a non-OPFS fallback
- connections/useGithubLastModified.js: new hook; fixes missing leading
  slash bug (filepath from routes layer has no leading slash — must
  prepend '/' before passing to navigateBaseOnModelPath)
- Tests: OPFS.worker.test.js (fetchLatestCommitHash), utils.test.js
  (onLastModifiedGithub callback cases), Loader.github.test.js
  (end-to-end sharePath + updateRecentFileLastModified),
  persistence.test.ts (updateRecentFileLastModified contract)
- Fix pre-existing test failures: GitHubFileBrowser.test (add theme
  wrapper), OpenModelControl.test (update for new tab/UI structure)
- Docs: DESIGN.md and PLAYBOOK.md updated with OPFS architecture,
  recent-files pipeline, filepath format contract, and testing patterns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 26, 2026

Deploy Preview for bldrs-share-dev ready!

Name Link
🔨 Latest commit 44d6bb6
🔍 Latest deploy log https://app.netlify.com/projects/bldrs-share-dev/deploys/69c5ae493ad2c30008008a35
😎 Deploy Preview https://deploy-preview-1478--bldrs-share-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 54 (🟢 up 1 from production)
Accessibility: 88 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@pablo-mayrgundter pablo-mayrgundter self-assigned this Mar 26, 2026
@pablo-mayrgundter pablo-mayrgundter added the enhancement New feature or request label Mar 26, 2026
Signed-off-by: Pablo Mayrgundter <pablo.mayrgundter@gmail.com>
@rpstohr-prim
Copy link
Copy Markdown

Approve

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants