Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Cloud: live cross-device and cross-tab sync

Đang mở
#796 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
42/100
Loại issue
Tính năng
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
firebase, typescript
Lĩnh vực
cloud, databases, frontend

Hướng nghiên cứu

Start with dependency #793, then read src/hooks/useWorkspaceManager.ts:445-475 and the existing filesystem and version-counter paths. Check src/hooks/useTabEditorManager.ts, especially synchronous reads and mounted-tab handling, before mapping the Firestore manifest entry point. Done means the acceptance criteria pass, including in-place refresh, conflict copies, cleanup, deletes, and scoped mutation coverage of at least 80%.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

enhancement

Summary

Propagate cloud drive changes between devices and browser tabs without a reload, using a Firestore
onSnapshot listener on the single manifest document.

This is essentially free given the chosen data model — and it is the main reason text lives in
Firestore rather than Cloud Storage, which has no change-notification mechanism at all.

Why one listener, not N

The listener subscribes to users/{uid}/drive/manifest only — one small document. A content
change bumps that file's hash and rev in the manifest, the listener fires with a tiny payload,
and the client fetches only the content documents that actually changed. Subscribing to the whole
content collection would re-deliver full file bodies on every keystroke-debounced save.

The in-place mutation constraint

src/hooks/useWorkspaceManager.ts:445-475 refreshes a workspace by mutating the filesystem object
in place and deliberately not calling setState. The comment at lines 470-473 explains why:
recreating the object would recreate compositeFileSystem, which resets the shell's current
working directory (issue #280). Sync-driven refresh must follow the same rule — mutate the
cache in place and signal the UI through the existing version counter on AdaptedFileSystem,
not by replacing the filesystem.

Conflict handling

Last-write-wins by rev, but never silently discard the loser. If a remote change would
overwrite unsaved or newer local content, write a conflict copy (e.g. main.lua alongside
main (conflict 2026-08-24).lua) and tell the user. Silent overwrite across devices is the
failure mode most likely to lose a student's work.

Acceptance criteria

  • A change made on device A appears on device B without a reload
  • A change in one browser tab appears in another tab
  • The listener subscribes to the manifest document only, not the content collection
  • Only changed content documents are re-fetched
  • The filesystem is mutated in place; the shell's cwd is preserved across a sync event
  • An open editor tab reflects remote changes without losing cursor position unnecessarily
  • A conflicting concurrent edit produces a conflict copy, not a silent overwrite
  • The listener is torn down on sign-out and on workspace unmount (no leaks, no orphaned reads)
  • Deletes propagate as well as writes
  • Scoped mutation coverage >= 80%

Implementation notes

  • Firestore's persistentLocalCache delivers a cache-first snapshot then a server snapshot; make
    sure the initial cached snapshot does not read as a spurious remote change.
  • Echo suppression: the client's own writes come back through the listener. Compare against the
    pending write set / rev so local saves do not round-trip as remote edits.
  • src/hooks/useTabEditorManager.ts loads tab content synchronously via
    filesystemRef.current.readFile(path) and mounts at most 5 editors (MRU virtualisation) —
    check how a remote update to a mounted vs unmounted tab behaves.
  • Watch read costs: each snapshot delivering changed documents costs reads. One manifest document
    plus only-changed content is the cheap shape; verify against the emulator's usage output.

Depends on

  • #793

Related

  • #280 - workspace refresh must not reset the shell cwd

Branching

This issue is part of the Cloud Accounts & Storage
milestone, which uses feat/cloud as its integration branch.

Branch from feat/cloud, and open the PR against feat/cloud. Never against main.

Create the branch (the --base flag also sets the default PR target for this branch):

gh issue develop <number> --base feat/cloud --checkout

Open the PR:

python3 scripts/issue-review.py <number> --base feat/cloud \
  --summary "<summary>" --test-plan "<test-plan>"

feat/cloud merges to main in a single PR once the milestone is complete.

Why both flags are required: gh issue develop without --base branches from the repository
default branch (main), and scripts/issue-review.py falls back to main when --base is
omitted — both for the gh pr create target and for the changed-file list in the PR body.

Ngôn ngữ chính
TypeScript
Star
1
Fork
0
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của jcollard/LuaInTheWeb

Tất cả issue của jcollard/LuaInTheWeb

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.