Commit Graph

77 Commits

Author SHA1 Message Date
Gustavo Henrique Santos Souza de Miranda c28b9ac565 fix: force fresh reconnect when returning after idle period
The WebSocket can go stale during inactivity without triggering any error
status (channel still shows 'joined' but socket is dead). Now when the user
returns after 60+ seconds of inactivity, the connection is torn down and
re-established to guarantee a fresh WebSocket. This ensures CRDT broadcasts
actually reach other clients after returning from idle.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 19:14:14 -03:00
Gustavo Henrique Santos Souza de Miranda fa8437d03a fix: broadcast full CRDT state on connect and when new user joins
CRDT broadcasts are fire-and-forget, so any updates missed during a
disconnection were permanently lost. Now when a client connects (or
reconnects), it broadcasts its full Yjs doc state. When an existing client
sees a new user join, it also broadcasts its full state. Yjs merges
handle deduplication automatically, so this converges all clients.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 19:06:20 -03:00
Gustavo Henrique Santos Souza de Miranda 2d0c3b6df6 fix: reduce auto-save frequency to avoid excessive writes
Increase CRDT DB persist debounce from 2s to 30s since it's only needed for
crash recovery (CRDT handles real-time sync). Increase LocalStorage draft
save debounce from 1s to 5s.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 18:58:54 -03:00
Gustavo Henrique Santos Souza de Miranda ec053d8126 fix: stop state ping-pong by removing broadcastStateRefresh from auto-persist
The CRDT auto-persist was broadcasting state-refresh after each save, causing
other clients to fetch from DB and overwrite their local variables/characters
with stale values. Since CRDT already syncs nodes/edges via yjs-update
broadcasts, the state-refresh from auto-persist was redundant and destructive.
Manual save still broadcasts state-refresh as intended.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 18:46:59 -03:00
Gustavo Henrique Santos Souza de Miranda cd73b31739 fix: improve realtime connection resilience with auto-reconnect and activity-based lifecycle
Add connection timeout (15s) to handle stale initial subscribes, inactivity
pause (5min) to save resources when idle, and automatic resume on user activity
or tab focus. The heartbeat now detects unhealthy channel states and consecutive
failures to trigger reconnects. Unexpected CLOSED status also triggers reconnect
instead of staying disconnected silently.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 18:20:41 -03:00
Gustavo Henrique Santos Souza de Miranda eb86ccd291 feat: notify collaborators to refresh from DB after save
Instead of relying on Yjs broadcast serialization (which has delivery
issues), use a lightweight state-refresh broadcast event. When any
client persists (manual save or CRDT auto-persist), it broadcasts
state-refresh. Other clients fetch the latest flowchart_data from the
database and update their local state and CRDT.

Added isSuppressed flag to CRDTManager to prevent broadcast/persist
loops during initialization and refresh operations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 16:36:43 -03:00
Gustavo Henrique Santos Souza de Miranda cdaae6b965 feat: broadcast full CRDT state to other clients after manual save
When a user saves, the full Yjs document state is broadcast so all
connected clients converge, even if they missed incremental updates.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 16:12:58 -03:00
Gustavo Henrique Santos Souza de Miranda 34815d70ee fix: resolve CRDT collaboration sync by registering broadcast listener before channel subscribe
The yjs-update broadcast listener was added after the Supabase channel
was already subscribed, which meant it never received messages. Moved
the listener registration to the builder chain before .subscribe()
(matching how cursor/node-lock listeners work), and removed the broken
isRemoteUpdateRef guard that caused ReferenceErrors preventing local
changes from reaching the CRDT.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 16:08:32 -03:00
Gustavo Henrique Santos Souza de Miranda 315e34e25e feat: [US-053] - Revert changes from audit trail
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 02:57:36 -03:00
Gustavo Henrique Santos Souza de Miranda f06a30b2bf feat: [US-052] - Activity history sidebar
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 02:53:31 -03:00
Gustavo Henrique Santos Souza de Miranda 6ef5cfc7fa feat: [US-051] - Audit trail recording
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 02:46:52 -03:00
Gustavo Henrique Santos Souza de Miranda 4a85d7a64b feat: [US-049] - Node editing lock indicators
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 02:43:06 -03:00
Gustavo Henrique Santos Souza de Miranda ccb05e3a3e feat: [US-050] - Join/leave notifications
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 21:08:05 -03:00
Gustavo Henrique Santos Souza de Miranda 7fe10544a1 feat: [US-047] - Live cursor positions on canvas
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 21:03:17 -03:00
Gustavo Henrique Santos Souza de Miranda b6d85b1a47 fix: add isSaving prop and back-to-dashboard navigation to Toolbar
Add isSaving as a prop so the save button properly shows disabled/spinner
state. Add a back arrow link to /dashboard for editor navigation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 20:55:07 -03:00
Gustavo Henrique Santos Souza de Miranda 8f6cff52a9 fix: correct OptionConditionEditor props in ChoiceNode
ChoiceNode was passing incompatible props (optionId, optionLabel, onSave,
onRemove, onCancel) to OptionConditionEditor which expects (condition,
onChange, onClose). This caused a build failure preventing the component
tree from rendering.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 20:54:54 -03:00
Gustavo Henrique Santos Souza de Miranda 6bc4e32fde fix: remove CRDT observer feedback loop causing drag issues
The Yjs map observers were calling notifyNodesChange/notifyEdgesChange
for local changes, creating a feedback loop that reset React Flow state
mid-drag. Remote notifications are already handled by the connectChannel
handler, so the observers only need to schedule persistence.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 20:54:45 -03:00
Gustavo Henrique Santos Souza de Miranda fa336f05d9 fix: restore missing utilities, context menu, and props from failed merge
The merge at bcbad57 lost utility functions, type definitions, and
handlers from the developing branch. This restores: imports (useRef,
useEffect, ConditionalEdge, ContextMenu), constants (AUTOSAVE_DEBOUNCE_MS),
types (ContextMenuState, ConditionEditorState), utility functions
(fromReactFlowNodes, fromReactFlowEdges, saveDraft, loadDraft, clearDraft,
flowchartDataEquals, isValidFlowchartData, convertToRenpyFormat), context
menu handlers, proper FlowchartEditorProps (userId, userDisplayName,
isOwner), ReactFlow container height (h-screen), and fixes stale closure
dependency arrays for characters/variables.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 20:54:29 -03:00
Gustavo Henrique Santos Souza de Miranda bcbad57aa9 Merge branch 'developing' into ralph/collaboration-and-character-variables 2026-01-23 15:59:17 -03:00
Gustavo Henrique Santos Souza de Miranda 6b7b27236f feat: [US-048] - Integrate Yjs CRDT for conflict-free node/edge synchronization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:46:39 -03:00
Gustavo Henrique Santos Souza de Miranda f92fc1ad01 feat: [US-046] - Presence indicators for active collaborators
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:42:07 -03:00
Gustavo Henrique Santos Souza de Miranda 37031c3889 feat: [US-044] - Project sharing and collaborator management
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:36:58 -03:00
Gustavo Henrique Santos Souza de Miranda 2e313a0264 feat: [US-045] - Supabase Realtime channel and connection management
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:28:23 -03:00
Gustavo Henrique Santos Souza de Miranda 0d72471f8f feat: [US-064] - Export validation for undefined references
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:21:09 -03:00
Gustavo Henrique Santos Souza de Miranda 8cdba7f858 fix: wrongfull jsx without single parent 2026-01-23 15:17:08 -03:00
Gustavo Henrique Santos Souza de Miranda 190e25228b fix: accepted git conflicts 2026-01-23 12:42:51 -03:00
Gustavo Henrique Santos Souza de Miranda a3e1d1cea2 feat: [US-063] - Import characters/variables from another project
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 10:47:38 -03:00
Gustavo Henrique Santos Souza de Miranda b570dca1b8 feat: [US-062] - Auto-migration of existing free-text values
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 10:42:40 -03:00
Gustavo Henrique Santos Souza de Miranda 92d892fb73 feat: [US-061] - Choice option condition variable dropdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 10:36:16 -03:00
Gustavo Henrique Santos Souza de Miranda b4b9f8cec9 feat: [US-060] - Edge condition variable dropdown
Replace the variableName text input in edge conditions with a
Combobox-based variable selector. Adds ConditionEditor modal
that opens on edge click, with type-aware operators (comparison
for numeric, == and != for string/boolean) and type-adaptive
value inputs (number, text, or boolean toggle).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 10:30:42 -03:00
Gustavo Henrique Santos Souza de Miranda 5493adf44a feat: [US-059] - Variable node variable dropdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 10:25:57 -03:00
Gustavo Henrique Santos Souza de Miranda 285320a4fe feat: [US-057] - Variable management UI in project settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:34:15 -03:00
Gustavo Henrique Santos Souza de Miranda 2ef605c0ca feat: [US-056] - Character management UI in project settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:31:42 -03:00
Gustavo Henrique Santos Souza de Miranda 11e8daf67c feat: [US-065] - Searchable combobox component
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:27:32 -03:00
Gustavo Henrique Santos Souza de Miranda d9c42f4cf7 feat: [US-054] - Character and Variable TypeScript types
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:23:53 -03:00
Gustavo Henrique Santos Souza de Miranda 4fbc564944 feat: [US-042] - Password reset modal on token arrival
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:51:52 -03:00
Gustavo Henrique Santos Souza de Miranda e8a6942cfe feat: [US-041] - Change password for logged-in user
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:49:25 -03:00
Gustavo Henrique Santos Souza de Miranda ff52df2c28 feat: [US-040] - Conditionals on choice options
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:47:39 -03:00
Gustavo Henrique Santos Souza de Miranda dd8fcb79cf fix: redirect root page to dashboard instead of default Next.js template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:31:48 -03:00
Gustavo Henrique Santos Souza de Miranda 2d57e6d337 fix: wrap useSearchParams() in Suspense boundary for login and signup pages
Next.js App Router requires components using useSearchParams() to be
wrapped in a Suspense boundary for static generation. Split login and
signup pages into server component wrappers with Suspense and client
form components.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:21:36 -03:00
Gustavo Henrique Santos Souza de Miranda b9d778b379 feat: [US-039] - Loading and error states
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:06:43 -03:00
Gustavo Henrique Santos Souza de Miranda b3f7a57623 feat: [US-038] - Unsaved changes warning
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:03:34 -03:00
Gustavo Henrique Santos Souza de Miranda f8f8048e53 feat: [US-037] - Export to Ren'Py JSON format
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:26:25 -03:00
Gustavo Henrique Santos Souza de Miranda ee0a6f9424 feat: [US-036] - Import project from .vnflow file
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:23:02 -03:00
Gustavo Henrique Santos Souza de Miranda 78479f3234 feat: [US-035] - Export project as .vnflow file
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:20:18 -03:00
Gustavo Henrique Santos Souza de Miranda 01f5428dd9 feat: [US-034] - Save project to database
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:17:33 -03:00
Gustavo Henrique Santos Souza de Miranda f6ab24c5b3 feat: [US-033] - Auto-save to LocalStorage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:14:49 -03:00
Gustavo Henrique Santos Souza de Miranda c431b212ac feat: [US-032] - Display conditions on edges
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:11:28 -03:00
Gustavo Henrique Santos Souza de Miranda fda0903872 feat: [US-031] - Condition editor modal
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:08:37 -03:00
Gustavo Henrique Santos Souza de Miranda 5b404cbe92 feat: [US-030] - Right-click context menu
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 18:04:54 -03:00