You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add the Follow toggle and the document-change notification to the app #205
A person cannot see or change document-follow settings in the app. There is no email category for document changes, no per-document Follow control, and no in-app entry for the new notification.
A content_change notification carries no sender. NotificationItem treats any sender-less notification as a system alert (apps/webapp/src/components/notificationPanel/components/NotificationItem.tsx:17-18). Without a new branch, that row renders the warning triangle (:78-81) and the name "System" (:93). Its button reads "Review" in the warning variant (:137, :142). Clicking it only toasts "Check your email settings in Profile → Notifications" (:35-40).
content_change is not one of the eight notification_category enum values (apps/webapp/src/types/supabase.ts:1660-1668).
set_document_follow and get_document_follow_state do not exist yet. git grep returns no hit for either name.
The enum value and both RPCs come from the backend issues in this set.
Global category toggle.
Add email_content_changes?: boolean to NotificationPreferences (apps/webapp/src/components/settings/types.ts:36), beside email_reactions (:47).
Default it to true in the state init of NotificationsSection (apps/webapp/src/components/settings/components/NotificationsSection.tsx:317-321), beside email_reactions: false (:320).
Add one ToggleRow (:224) after the Reactions email row (:597-604), inside the preferences.email_enabled block (:579). Label "Document changes". Description "When a document you follow is edited".
Wire it through the existing debounced handlePreferenceChange (:362). No SQL change: update_notification_preferences merges the patch with || and accepts a new key (packages/supabase/scripts/07-0-notifications.sql:41-68).
RPC wrappers. Add getDocumentFollowState.ts and setDocumentFollow.ts under apps/webapp/src/api/rpc/, beside joinWorkspace.ts, and export both from apps/webapp/src/api/rpc/index.ts. Await each call.
Per-document Follow toggle.
Add one ToggleSection (apps/webapp/src/components/TipTap/toolbar/desktop/DocumentSettingsPanel.tsx:20) into the soft well (:82).
Render it for any signed-in user, so it must sit outside the owner-only branch. The owner branch is :104-126. The non-owner branch is :127-132.
The toggle description reads "Notify me when this document changes." The mute is applied in the fan-out recipient query, upstream of the notification insert. So unfollowing removes the in-app row as well as the email. "Email me…" would promise less than the switch does.
Disable it until joinedWorkspace is true (apps/webapp/src/stores/workspace.ts:35), because set_document_follow is update-only and needs the membership row.
Flip optimistically and revert on error. Follow the design-system skill for the visuals.
Widen the notification type.TNotification (apps/webapp/src/types/domain.ts:53-69) has no action_url, and both channel_id (:65) and message_id (:67) are non-nullable. Add action_url?: string | null, and let the two ids be nullable. Both fetch RPCs already return the column (packages/supabase/scripts/10-functions.sql:669, packages/supabase/scripts/07-1-notification-functions.sql:50).
In-app entry.
NotificationIcon: add a content_change entry to iconMap (apps/webapp/src/components/notificationPanel/components/NotificationIcon.tsx:7-17), using Icons.pencil (apps/webapp/src/components/icons/registry.ts:160) and the label "Document change".
NotificationItem: add the content_change click branch in handleViewNotificationbefore the isSystemNotification branch (:34-40). Mark the row read, dismiss the panel, and navigate to action_url when it differs from the current path.
isSystem (:73) drives five render sites. Take all five into account:
the warning avatar (:78-81)
the "System" name (:93)
the copy-link button gate (:103-113)
the button variant (:137)
the button text (:142)
A sender-less content_change must show the document-change icon, its document name, and a plain "View" button. It must not show the warning avatar or "Review".
Keep the copy-link button hidden for content_change. Today !isSystem (:103) already hides it. It stops hiding it once the new branch makes the row non-system. handleCopyUrl (:57) writes msg_id and chatroom from the row (:59-60). A carrier has no message, so the copied link is broken.
Acceptance
"Document changes" appears in Profile → Notifications under email, only while email notifications are on, and its state survives a page reload.
A signed-in non-owner sees the Follow toggle in the document settings panel. An anonymous visitor sees no Follow control.
The Follow toggle is disabled until the workspace join finishes, then it enables.
Turning Follow off, reloading, and reading the state back returns the same value. The same holds turning it on.
Turning Follow off leaves the member roster's last_visit_at for that user unchanged. That column falls back to workspace_members.updated_at (packages/supabase/scripts/10-8-func-workspace_members.sql:238), so a careless write shows as a fresh "Last seen".
The Follow description reads "Notify me when this document changes."
A second user edits the document. The first user's bell shows one entry with the document-change icon, no warning triangle, no "System" name, and a "View" button. Clicking it navigates to the document and clears the badge.
The copy-link button is absent on a content_change entry.
Chat notification rows and the chat digest look unchanged.
bun run --filter @docs.plus/webapp typecheck is clean.
Verified in a browser in light and dark, on desktop and on mobile, against a running dev server. Never run next build against a live dev server.
Notes
No new unit or Cypress tests. The full flow is pinned by the backend end-to-end test in the sibling issues, and a mocked duplicate here adds nothing.
Wording approved by the maintainer on 2026-09-01. The Follow description is "Notify me when this document changes." — not "Email me…", because the mute sits upstream of the notification insert and removes the in-app row too. Ruling recorded on #169.
Problem
A person cannot see or change document-follow settings in the app. There is no email category for document changes, no per-document Follow control, and no in-app entry for the new notification.
A
content_changenotification carries no sender.NotificationItemtreats any sender-less notification as a system alert (apps/webapp/src/components/notificationPanel/components/NotificationItem.tsx:17-18). Without a new branch, that row renders the warning triangle (:78-81) and the name "System" (:93). Its button reads "Review" in the warning variant (:137,:142). Clicking it only toasts "Check your email settings in Profile → Notifications" (:35-40).Part of #169.
What to do
Backend lands first. This issue adds no SQL.
content_changeis not one of the eightnotification_categoryenum values (apps/webapp/src/types/supabase.ts:1660-1668).set_document_followandget_document_follow_statedo not exist yet.git grepreturns no hit for either name.Global category toggle.
email_content_changes?: booleantoNotificationPreferences(apps/webapp/src/components/settings/types.ts:36), besideemail_reactions(:47).truein the state init ofNotificationsSection(apps/webapp/src/components/settings/components/NotificationsSection.tsx:317-321), besideemail_reactions: false(:320).ToggleRow(:224) after the Reactions email row (:597-604), inside thepreferences.email_enabledblock (:579). Label "Document changes". Description "When a document you follow is edited".handlePreferenceChange(:362). No SQL change:update_notification_preferencesmerges the patch with||and accepts a new key (packages/supabase/scripts/07-0-notifications.sql:41-68).RPC wrappers. Add
getDocumentFollowState.tsandsetDocumentFollow.tsunderapps/webapp/src/api/rpc/, besidejoinWorkspace.ts, and export both fromapps/webapp/src/api/rpc/index.ts. Await each call.Per-document Follow toggle.
ToggleSection(apps/webapp/src/components/TipTap/toolbar/desktop/DocumentSettingsPanel.tsx:20) into the soft well (:82).:104-126. The non-owner branch is:127-132.joinedWorkspaceis true (apps/webapp/src/stores/workspace.ts:35), becauseset_document_followis update-only and needs the membership row.Widen the notification type.
TNotification(apps/webapp/src/types/domain.ts:53-69) has noaction_url, and bothchannel_id(:65) andmessage_id(:67) are non-nullable. Addaction_url?: string | null, and let the two ids be nullable. Both fetch RPCs already return the column (packages/supabase/scripts/10-functions.sql:669,packages/supabase/scripts/07-1-notification-functions.sql:50).In-app entry.
NotificationIcon: add acontent_changeentry toiconMap(apps/webapp/src/components/notificationPanel/components/NotificationIcon.tsx:7-17), usingIcons.pencil(apps/webapp/src/components/icons/registry.ts:160) and the label "Document change".NotificationItem: add thecontent_changeclick branch inhandleViewNotificationbefore theisSystemNotificationbranch (:34-40). Mark the row read, dismiss the panel, and navigate toaction_urlwhen it differs from the current path.isSystem(:73) drives five render sites. Take all five into account::78-81):93):103-113):137):142)content_changemust show the document-change icon, its document name, and a plain "View" button. It must not show the warning avatar or "Review".content_change. Today!isSystem(:103) already hides it. It stops hiding it once the new branch makes the row non-system.handleCopyUrl(:57) writesmsg_idandchatroomfrom the row (:59-60). A carrier has no message, so the copied link is broken.Acceptance
last_visit_atfor that user unchanged. That column falls back toworkspace_members.updated_at(packages/supabase/scripts/10-8-func-workspace_members.sql:238), so a careless write shows as a fresh "Last seen".content_changeentry.bun run --filter @docs.plus/webapp typecheckis clean.next buildagainst a live dev server.Notes
No new unit or Cypress tests. The full flow is pinned by the backend end-to-end test in the sibling issues, and a mocked duplicate here adds nothing.