infra: add linting and formatting for js projects #230

Merged
talksik merged 11 commits from resolve-lint-issues into main 2026-06-02 14:44:24 +00:00
talksik commented 2026-06-01 21:21:24 +00:00 (Migrated from github.com)

Closes #145

Closes #145
github-code-quality[bot] (Migrated from github.com) reviewed 2026-06-01 21:22:59 +00:00
@@ -422,14 +477,17 @@ function StreamViewInner({ path, streamParticle }: StreamViewProps) {
)}
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:22:59 +00:00

Useless conditional

This use of variable 'currentParticle' always evaluates to true.


The best fix is to remove the unnecessary conditional around currentParticleDocPath construction and always compute it directly after the existing early return checks.

In js/desktop/src/features/particles/stream-view.tsx, inside handleToggleReaction (around lines 227–233), replace:

  • conditional assignment to currentParticleDocPath using currentParticle ? ... : null
  • subsequent null check if (!currentParticleDocPath) return;

with a direct assignment using currentParticle.id. This keeps functionality unchanged because currentParticle is already guaranteed non-null by the earlier guard.

No imports, new methods, or new dependencies are required.

## Useless conditional This use of variable 'currentParticle' always evaluates to true. --- The best fix is to remove the unnecessary conditional around <code>currentParticleDocPath</code> construction and always compute it directly after the existing early return checks.</p> <p>In <code>js/desktop/src/features/particles/stream-view.tsx</code>, inside <code>handleToggleReaction</code> (around lines 227–233), replace:</p> <ul> <li>conditional assignment to <code>currentParticleDocPath</code> using <code>currentParticle ? ... : null</code></li> <li>subsequent null check <code>if (!currentParticleDocPath) return;</code></li> </ul> <p>with a direct assignment using <code>currentParticle.id</code>. This keeps functionality unchanged because <code>currentParticle</code> is already guaranteed non-null by the earlier guard.</p> <p>No imports, new methods, or new dependencies are required.
github-code-quality[bot] (Migrated from github.com) reviewed 2026-06-01 21:45:17 +00:00
@@ -164,3 +170,3 @@
{...wrapperProps}
style={{ flex: 1, justifyContent: "flex-end" }}
style={{ flex: 1, justifyContent: 'flex-end' }}
pointerEvents="box-none"
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
@@ -172,3 +178,3 @@
backgroundColor: "#1c1c1c",
backgroundColor: '#1c1c1c',
borderTopLeftRadius: 22,
borderTopRightRadius: 22,
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
@@ -190,180 +195,184 @@ export function ReactionSheet({
onRequestClose={dismiss}
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
@@ -613,3 +607,3 @@
videoFit={videoFit}
onToggleVideoFit={() =>
setVideoFit((v) => (v === "cover" ? "contain" : "cover"))
setVideoFit((v) => (v === 'cover' ? 'contain' : 'cover'))
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
@@ -647,3 +641,3 @@
bottom: insets.bottom + COMPOSE_DOCK_HEIGHT + 40,
justifyContent: "center",
justifyContent: 'center',
}}
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.


Remove only the unnecessary 'worklet'; directive in the panUp .onEnd callback (around line 338 in js/mobile/src/features/stream-view/StreamView.tsx).

Best fix without functional change:

  • Keep the gesture logic intact.
  • Keep runOnJS(openReactions)() intact.
  • Delete the single directive statement from that callback body.

No imports, methods, or new definitions are needed.

## Unknown directive Unknown directive: 'worklet'. --- Remove only the unnecessary <code>'worklet';</code> directive in the <code>panUp</code> <code>.onEnd</code> callback (around line 338 in <code>js/mobile/src/features/stream-view/StreamView.tsx</code>).</p> <p>Best fix without functional change:</p> <ul> <li>Keep the gesture logic intact.</li> <li>Keep <code>runOnJS(openReactions)()</code> intact.</li> <li>Delete the single directive statement from that callback body.</li> </ul> <p>No imports, methods, or new definitions are needed.
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
@@ -690,3 +683,4 @@
streamStatus={streamParticle.status ?? 'open'}
isCreator={isCreator}
canEditParticle={canEditCurrentParticle}
canDeleteParticle={canDeleteCurrentParticle}
github-code-quality[bot] (Migrated from github.com) commented 2026-06-01 21:45:17 +00:00

Unknown directive

Unknown directive: 'worklet'.

## Unknown directive <p>Unknown directive: 'worklet'.</p>
coderabbitai[bot] commented 2026-06-02 00:26:53 +00:00 (Migrated from github.com)

Important

Review skipped

Too many files!

This PR contains 250 files, which is 100 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d99a9a3-9b51-4a83-83bb-5f6859747ca2

📥 Commits

Reviewing files that changed from the base of the PR and between 2fe562ce2b and 89b828a576.

Files ignored due to path filters (2)
  • js/desktop/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • js/mobile/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (250)
  • js/desktop/.eslintrc.json
  • js/desktop/.prettierrc
  • js/desktop/forge.config.ts
  • js/desktop/package.json
  • js/desktop/src/App.tsx
  • js/desktop/src/api/client.ts
  • js/desktop/src/api/types.ts
  • js/desktop/src/assets.d.ts
  • js/desktop/src/autoplay_window/AutoplayApp.tsx
  • js/desktop/src/autoplay_window/renderer.tsx
  • js/desktop/src/components/app-error-boundary.tsx
  • js/desktop/src/components/audio/audio-level-bars.tsx
  • js/desktop/src/components/audio/use-audio-source.ts
  • js/desktop/src/components/autoplay-card-content.tsx
  • js/desktop/src/components/composing-indicator.tsx
  • js/desktop/src/components/confirm-destructive-overlay.tsx
  • js/desktop/src/components/copyable-email.tsx
  • js/desktop/src/components/error-fallback.tsx
  • js/desktop/src/components/in-app-autoplay-card.tsx
  • js/desktop/src/components/keybindings-overlay.tsx
  • js/desktop/src/components/link-preview-card.tsx
  • js/desktop/src/components/relative-timestamp.tsx
  • js/desktop/src/components/screen-source-picker.tsx
  • js/desktop/src/components/ui/avatar.tsx
  • js/desktop/src/components/ui/badge.tsx
  • js/desktop/src/components/ui/breadcrumb.tsx
  • js/desktop/src/components/ui/button.tsx
  • js/desktop/src/components/ui/card.tsx
  • js/desktop/src/components/ui/checkbox.tsx
  • js/desktop/src/components/ui/context-menu.tsx
  • js/desktop/src/components/ui/dialog.tsx
  • js/desktop/src/components/ui/dropdown-menu.tsx
  • js/desktop/src/components/ui/input.tsx
  • js/desktop/src/components/ui/label.tsx
  • js/desktop/src/components/ui/progress.tsx
  • js/desktop/src/components/ui/radio-group.tsx
  • js/desktop/src/components/ui/scroll-area.tsx
  • js/desktop/src/components/ui/select.tsx
  • js/desktop/src/components/ui/separator.tsx
  • js/desktop/src/components/ui/skeleton.tsx
  • js/desktop/src/components/ui/slider.tsx
  • js/desktop/src/components/ui/sonner.tsx
  • js/desktop/src/components/ui/switch.tsx
  • js/desktop/src/components/ui/tabs.tsx
  • js/desktop/src/components/ui/toggle-group.tsx
  • js/desktop/src/components/ui/toggle.tsx
  • js/desktop/src/components/ui/tooltip.tsx
  • js/desktop/src/components/ui/typography.tsx
  • js/desktop/src/components/video-audio-toggle.tsx
  • js/desktop/src/components/window-controls.tsx
  • js/desktop/src/config/env.ts
  • js/desktop/src/electron.d.ts
  • js/desktop/src/features/attachments/attachment-lightbox.tsx
  • js/desktop/src/features/auth/code-step.tsx
  • js/desktop/src/features/auth/email-step.tsx
  • js/desktop/src/features/auth/login-page.tsx
  • js/desktop/src/features/compose/attachment-strip.tsx
  • js/desktop/src/features/compose/compose-overlay.tsx
  • js/desktop/src/features/compose/compose-quota-indicator.tsx
  • js/desktop/src/features/compose/configure-stream-step.tsx
  • js/desktop/src/features/compose/markdown-editor.css
  • js/desktop/src/features/compose/markdown-editor.tsx
  • js/desktop/src/features/compose/recording-overlay.tsx
  • js/desktop/src/features/compose/text-compose-step.tsx
  • js/desktop/src/features/compose/text-editor.tsx
  • js/desktop/src/features/compose/use-recorder.ts
  • js/desktop/src/features/compose/use-screen-recorder.ts
  • js/desktop/src/features/layout.tsx
  • js/desktop/src/features/network-billing.tsx
  • js/desktop/src/features/network-root.tsx
  • js/desktop/src/features/network-selector.tsx
  • js/desktop/src/features/network-settings.tsx
  • js/desktop/src/features/particles/delete-particle-overlay.tsx
  • js/desktop/src/features/particles/deleted-particle-view.tsx
  • js/desktop/src/features/particles/fallback-particle-view.tsx
  • js/desktop/src/features/particles/folder-view.tsx
  • js/desktop/src/features/particles/media-particle-view.tsx
  • js/desktop/src/features/particles/particle-attachments.tsx
  • js/desktop/src/features/particles/particle-list-view.tsx
  • js/desktop/src/features/particles/particle-preview.tsx
  • js/desktop/src/features/particles/particle-view-resolver.tsx
  • js/desktop/src/features/particles/playback-page-indicator.tsx
  • js/desktop/src/features/particles/reaction-bar.tsx
  • js/desktop/src/features/particles/rename-stream-overlay.tsx
  • js/desktop/src/features/particles/stream-card.tsx
  • js/desktop/src/features/particles/stream-context-menu.tsx
  • js/desktop/src/features/particles/stream-members-overlay.tsx
  • js/desktop/src/features/particles/stream-presence-context.tsx
  • js/desktop/src/features/particles/stream-top-bar.tsx
  • js/desktop/src/features/particles/stream-view.tsx
  • js/desktop/src/features/particles/text-edit-overlay.tsx
  • js/desktop/src/features/particles/text-particle-view.tsx
  • js/desktop/src/features/particles/text-reaction-input.tsx
  • js/desktop/src/features/particles/transcript-overlay.tsx
  • js/desktop/src/features/settings-page.tsx
  • js/desktop/src/features/settings/audio-video-settings-page.tsx
  • js/desktop/src/firebase.ts
  • js/desktop/src/hooks/use-billing.ts
  • js/desktop/src/hooks/use-channel.ts
  • js/desktop/src/hooks/use-create-particle.ts
  • js/desktop/src/hooks/use-dock-badge.ts
  • js/desktop/src/hooks/use-download-url.ts
  • js/desktop/src/hooks/use-effective-device-id.ts
  • js/desktop/src/hooks/use-file-input.ts
  • js/desktop/src/hooks/use-link-metadata.ts
  • js/desktop/src/hooks/use-media-devices.ts
  • js/desktop/src/hooks/use-member-management.ts
  • js/desktop/src/hooks/use-network-usage.ts
  • js/desktop/src/hooks/use-networks.ts
  • js/desktop/src/hooks/use-object-url.ts
  • js/desktop/src/hooks/use-particle-attachments.ts
  • js/desktop/src/hooks/use-particle.ts
  • js/desktop/src/hooks/use-playback-keys.ts
  • js/desktop/src/hooks/use-prefetch-adjacent-media.ts
  • js/desktop/src/hooks/use-presence-positions.ts
  • js/desktop/src/hooks/use-recording-mode.ts
  • js/desktop/src/hooks/use-stream-action-keys.ts
  • js/desktop/src/hooks/use-stream-autoplay.ts
  • js/desktop/src/hooks/use-stream-keyboard-nav.ts
  • js/desktop/src/hooks/use-stream-navigation-keys.ts
  • js/desktop/src/hooks/use-stream-particles.ts
  • js/desktop/src/hooks/use-stream-playback.ts
  • js/desktop/src/hooks/use-suspend-playback.ts
  • js/desktop/src/hooks/use-transcript-playback.ts
  • js/desktop/src/huddle_window/HuddleApp.tsx
  • js/desktop/src/huddle_window/renderer.tsx
  • js/desktop/src/index.css
  • js/desktop/src/lib/constants.ts
  • js/desktop/src/lib/errors.ts
  • js/desktop/src/lib/firestore-particles.ts
  • js/desktop/src/lib/humans.ts
  • js/desktop/src/lib/image-thumbnail.ts
  • js/desktop/src/lib/keyboard.ts
  • js/desktop/src/lib/particle-path.ts
  • js/desktop/src/lib/platform/desktop-only.ts
  • js/desktop/src/lib/platform/electron.ts
  • js/desktop/src/lib/platform/index.ts
  • js/desktop/src/lib/platform/index.web.ts
  • js/desktop/src/lib/platform/types.ts
  • js/desktop/src/lib/platform/web.ts
  • js/desktop/src/lib/pusher-client.ts
  • js/desktop/src/lib/pusher-provider.tsx
  • js/desktop/src/lib/query-client.ts
  • js/desktop/src/lib/random-name.ts
  • js/desktop/src/lib/router-shell.tsx
  • js/desktop/src/lib/router-shell.web.tsx
  • js/desktop/src/lib/sentry.ts
  • js/desktop/src/lib/sentry.web.ts
  • js/desktop/src/lib/sound-effects/engine.ts
  • js/desktop/src/lib/sound-effects/sound-effects-provider.tsx
  • js/desktop/src/lib/sound-effects/sounds.ts
  • js/desktop/src/lib/sound-effects/use-sound-effect.ts
  • js/desktop/src/lib/stream-visibility.ts
  • js/desktop/src/lib/time-utils.ts
  • js/desktop/src/lib/utils.ts
  • js/desktop/src/main.ts
  • js/desktop/src/main/ipc-utils.ts
  • js/desktop/src/main/sentry.ts
  • js/desktop/src/preload.ts
  • js/desktop/src/renderer.tsx
  • js/desktop/src/screen_record_window/ScreenRecordControlApp.tsx
  • js/desktop/src/screen_record_window/renderer.tsx
  • js/desktop/src/stores/auth-store.ts
  • js/desktop/src/stores/autoplay-payload-store.ts
  • js/desktop/src/stores/autoplay-store.ts
  • js/desktop/src/stores/compose-intent-store.ts
  • js/desktop/src/stores/media-devices-store.ts
  • js/desktop/src/stores/media-settings-store.ts
  • js/desktop/src/stores/playback-pause-store.ts
  • js/desktop/src/stores/session-store.ts
  • js/desktop/src/stores/sound-effects-store.ts
  • js/desktop/src/styles/globals.css
  • js/desktop/src/web/renderer.tsx
  • js/mobile/.prettierignore
  • js/mobile/.prettierrc
  • js/mobile/eslint.config.js
  • js/mobile/package.json
  • js/mobile/src/App.tsx
  • js/mobile/src/api/client.ts
  • js/mobile/src/api/types.ts
  • js/mobile/src/components/Avatar.tsx
  • js/mobile/src/components/BottomSheet.tsx
  • js/mobile/src/components/ComposingIndicator.tsx
  • js/mobile/src/components/FlowyLogo.tsx
  • js/mobile/src/components/ListSeparator.tsx
  • js/mobile/src/components/RelativeTimestamp.tsx
  • js/mobile/src/config/env.ts
  • js/mobile/src/features/auth/SignInScreen.tsx
  • js/mobile/src/features/compose/AudioRecordingOverlay.tsx
  • js/mobile/src/features/compose/ComposeDock.tsx
  • js/mobile/src/features/compose/ReviewSheet.tsx
  • js/mobile/src/features/compose/TextComposeModal.tsx
  • js/mobile/src/features/compose/VideoRecordingOverlay.tsx
  • js/mobile/src/features/huddle/HuddleScreen.tsx
  • js/mobile/src/features/huddle/use-open-huddle.ts
  • js/mobile/src/features/networks/Drawer.tsx
  • js/mobile/src/features/networks/NetworkListScreen.tsx
  • js/mobile/src/features/settings/AccountScreen.tsx
  • js/mobile/src/features/settings/SettingsScreen.tsx
  • js/mobile/src/features/stream-view/DeletedParticleView.tsx
  • js/mobile/src/features/stream-view/EditParticleSheet.tsx
  • js/mobile/src/features/stream-view/FallbackParticleView.tsx
  • js/mobile/src/features/stream-view/MediaParticleView.tsx
  • js/mobile/src/features/stream-view/PlaybackPageIndicator.tsx
  • js/mobile/src/features/stream-view/ReactionSheet.tsx
  • js/mobile/src/features/stream-view/ReactionStack.tsx
  • js/mobile/src/features/stream-view/RenameStreamSheet.tsx
  • js/mobile/src/features/stream-view/StreamActionsSheet.tsx
  • js/mobile/src/features/stream-view/StreamMembersSheet.tsx
  • js/mobile/src/features/stream-view/StreamMetadataHeader.tsx
  • js/mobile/src/features/stream-view/StreamTopActions.tsx
  • js/mobile/src/features/stream-view/StreamView.tsx
  • js/mobile/src/features/stream-view/StreamViewScreen.tsx
  • js/mobile/src/features/stream-view/TextParticleView.tsx
  • js/mobile/src/features/stream-view/TranscriptOverlay.tsx
  • js/mobile/src/features/stream-view/stream-presence-context.tsx
  • js/mobile/src/features/stream-view/stream-safe-area.tsx
  • js/mobile/src/features/stream-view/use-exit-countdown.ts
  • js/mobile/src/features/streams/NewStreamScreen.tsx
  • js/mobile/src/features/streams/StreamCard.tsx
  • js/mobile/src/features/streams/StreamListScreen.tsx
  • js/mobile/src/features/streams/VisibilityPickerSheet.tsx
  • js/mobile/src/firebase.ts
  • js/mobile/src/hooks/use-channel.ts
  • js/mobile/src/hooks/use-event.ts
  • js/mobile/src/hooks/use-networks.ts
  • js/mobile/src/hooks/use-particle.ts
  • js/mobile/src/hooks/use-stream-particles.ts
  • js/mobile/src/hooks/use-stream-playback.ts
  • js/mobile/src/hooks/use-suspend-playback.ts
  • js/mobile/src/hooks/use-transcript-playback.ts
  • js/mobile/src/lib/errors.ts
  • js/mobile/src/lib/firestore-particles.ts
  • js/mobile/src/lib/humans.ts
  • js/mobile/src/lib/notification-routing.ts
  • js/mobile/src/lib/particle-path.ts
  • js/mobile/src/lib/push-notifications.ts
  • js/mobile/src/lib/pusher-client.ts
  • js/mobile/src/lib/pusher-provider.tsx
  • js/mobile/src/lib/query-client.ts
  • js/mobile/src/lib/random-name.ts
  • js/mobile/src/lib/recording-audio-session.ts
  • js/mobile/src/lib/stream-visibility.ts
  • js/mobile/src/lib/time-utils.ts
  • js/mobile/src/lib/upload.ts
  • js/mobile/src/lib/utils.ts
  • js/mobile/src/navigation/RootNavigator.tsx
  • js/mobile/src/navigation/types.ts
  • js/mobile/src/stores/auth-store.ts
  • js/mobile/src/stores/playback-pause-store.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch resolve-lint-issues

Comment @coderabbitai help to get the list of available commands and usage tips.

<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- This is an auto-generated comment: skip review by coderabbit.ai --> > [!IMPORTANT] > ## Review skipped > > Too many files! > > This PR contains 250 files, which is 100 over the limit of 150. > > To get a review, narrow the scope: > • coderabbit review --type committed # exclude uncommitted changes > • coderabbit review --dir <path> # limit to a subdirectory > • coderabbit review --base <branch> # compare against a closer base > > <details> > <summary>⚙️ Run configuration</summary> > > **Configuration used**: defaults > > **Review profile**: CHILL > > **Plan**: Pro Plus > > **Run ID**: `8d99a9a3-9b51-4a83-83bb-5f6859747ca2` > > </details> > > <details> > <summary>📥 Commits</summary> > > Reviewing files that changed from the base of the PR and between 2fe562ce2b29ca2ddb5a39fd3278f3f62b8f3d7b and 89b828a576cb36d05abb24e71be4367cfa8e7467. > > </details> > > <details> > <summary>⛔ Files ignored due to path filters (2)</summary> > > * `js/desktop/yarn.lock` is excluded by `!**/yarn.lock`, `!**/*.lock` > * `js/mobile/yarn.lock` is excluded by `!**/yarn.lock`, `!**/*.lock` > > </details> > > <details> > <summary>📒 Files selected for processing (250)</summary> > > * `js/desktop/.eslintrc.json` > * `js/desktop/.prettierrc` > * `js/desktop/forge.config.ts` > * `js/desktop/package.json` > * `js/desktop/src/App.tsx` > * `js/desktop/src/api/client.ts` > * `js/desktop/src/api/types.ts` > * `js/desktop/src/assets.d.ts` > * `js/desktop/src/autoplay_window/AutoplayApp.tsx` > * `js/desktop/src/autoplay_window/renderer.tsx` > * `js/desktop/src/components/app-error-boundary.tsx` > * `js/desktop/src/components/audio/audio-level-bars.tsx` > * `js/desktop/src/components/audio/use-audio-source.ts` > * `js/desktop/src/components/autoplay-card-content.tsx` > * `js/desktop/src/components/composing-indicator.tsx` > * `js/desktop/src/components/confirm-destructive-overlay.tsx` > * `js/desktop/src/components/copyable-email.tsx` > * `js/desktop/src/components/error-fallback.tsx` > * `js/desktop/src/components/in-app-autoplay-card.tsx` > * `js/desktop/src/components/keybindings-overlay.tsx` > * `js/desktop/src/components/link-preview-card.tsx` > * `js/desktop/src/components/relative-timestamp.tsx` > * `js/desktop/src/components/screen-source-picker.tsx` > * `js/desktop/src/components/ui/avatar.tsx` > * `js/desktop/src/components/ui/badge.tsx` > * `js/desktop/src/components/ui/breadcrumb.tsx` > * `js/desktop/src/components/ui/button.tsx` > * `js/desktop/src/components/ui/card.tsx` > * `js/desktop/src/components/ui/checkbox.tsx` > * `js/desktop/src/components/ui/context-menu.tsx` > * `js/desktop/src/components/ui/dialog.tsx` > * `js/desktop/src/components/ui/dropdown-menu.tsx` > * `js/desktop/src/components/ui/input.tsx` > * `js/desktop/src/components/ui/label.tsx` > * `js/desktop/src/components/ui/progress.tsx` > * `js/desktop/src/components/ui/radio-group.tsx` > * `js/desktop/src/components/ui/scroll-area.tsx` > * `js/desktop/src/components/ui/select.tsx` > * `js/desktop/src/components/ui/separator.tsx` > * `js/desktop/src/components/ui/skeleton.tsx` > * `js/desktop/src/components/ui/slider.tsx` > * `js/desktop/src/components/ui/sonner.tsx` > * `js/desktop/src/components/ui/switch.tsx` > * `js/desktop/src/components/ui/tabs.tsx` > * `js/desktop/src/components/ui/toggle-group.tsx` > * `js/desktop/src/components/ui/toggle.tsx` > * `js/desktop/src/components/ui/tooltip.tsx` > * `js/desktop/src/components/ui/typography.tsx` > * `js/desktop/src/components/video-audio-toggle.tsx` > * `js/desktop/src/components/window-controls.tsx` > * `js/desktop/src/config/env.ts` > * `js/desktop/src/electron.d.ts` > * `js/desktop/src/features/attachments/attachment-lightbox.tsx` > * `js/desktop/src/features/auth/code-step.tsx` > * `js/desktop/src/features/auth/email-step.tsx` > * `js/desktop/src/features/auth/login-page.tsx` > * `js/desktop/src/features/compose/attachment-strip.tsx` > * `js/desktop/src/features/compose/compose-overlay.tsx` > * `js/desktop/src/features/compose/compose-quota-indicator.tsx` > * `js/desktop/src/features/compose/configure-stream-step.tsx` > * `js/desktop/src/features/compose/markdown-editor.css` > * `js/desktop/src/features/compose/markdown-editor.tsx` > * `js/desktop/src/features/compose/recording-overlay.tsx` > * `js/desktop/src/features/compose/text-compose-step.tsx` > * `js/desktop/src/features/compose/text-editor.tsx` > * `js/desktop/src/features/compose/use-recorder.ts` > * `js/desktop/src/features/compose/use-screen-recorder.ts` > * `js/desktop/src/features/layout.tsx` > * `js/desktop/src/features/network-billing.tsx` > * `js/desktop/src/features/network-root.tsx` > * `js/desktop/src/features/network-selector.tsx` > * `js/desktop/src/features/network-settings.tsx` > * `js/desktop/src/features/particles/delete-particle-overlay.tsx` > * `js/desktop/src/features/particles/deleted-particle-view.tsx` > * `js/desktop/src/features/particles/fallback-particle-view.tsx` > * `js/desktop/src/features/particles/folder-view.tsx` > * `js/desktop/src/features/particles/media-particle-view.tsx` > * `js/desktop/src/features/particles/particle-attachments.tsx` > * `js/desktop/src/features/particles/particle-list-view.tsx` > * `js/desktop/src/features/particles/particle-preview.tsx` > * `js/desktop/src/features/particles/particle-view-resolver.tsx` > * `js/desktop/src/features/particles/playback-page-indicator.tsx` > * `js/desktop/src/features/particles/reaction-bar.tsx` > * `js/desktop/src/features/particles/rename-stream-overlay.tsx` > * `js/desktop/src/features/particles/stream-card.tsx` > * `js/desktop/src/features/particles/stream-context-menu.tsx` > * `js/desktop/src/features/particles/stream-members-overlay.tsx` > * `js/desktop/src/features/particles/stream-presence-context.tsx` > * `js/desktop/src/features/particles/stream-top-bar.tsx` > * `js/desktop/src/features/particles/stream-view.tsx` > * `js/desktop/src/features/particles/text-edit-overlay.tsx` > * `js/desktop/src/features/particles/text-particle-view.tsx` > * `js/desktop/src/features/particles/text-reaction-input.tsx` > * `js/desktop/src/features/particles/transcript-overlay.tsx` > * `js/desktop/src/features/settings-page.tsx` > * `js/desktop/src/features/settings/audio-video-settings-page.tsx` > * `js/desktop/src/firebase.ts` > * `js/desktop/src/hooks/use-billing.ts` > * `js/desktop/src/hooks/use-channel.ts` > * `js/desktop/src/hooks/use-create-particle.ts` > * `js/desktop/src/hooks/use-dock-badge.ts` > * `js/desktop/src/hooks/use-download-url.ts` > * `js/desktop/src/hooks/use-effective-device-id.ts` > * `js/desktop/src/hooks/use-file-input.ts` > * `js/desktop/src/hooks/use-link-metadata.ts` > * `js/desktop/src/hooks/use-media-devices.ts` > * `js/desktop/src/hooks/use-member-management.ts` > * `js/desktop/src/hooks/use-network-usage.ts` > * `js/desktop/src/hooks/use-networks.ts` > * `js/desktop/src/hooks/use-object-url.ts` > * `js/desktop/src/hooks/use-particle-attachments.ts` > * `js/desktop/src/hooks/use-particle.ts` > * `js/desktop/src/hooks/use-playback-keys.ts` > * `js/desktop/src/hooks/use-prefetch-adjacent-media.ts` > * `js/desktop/src/hooks/use-presence-positions.ts` > * `js/desktop/src/hooks/use-recording-mode.ts` > * `js/desktop/src/hooks/use-stream-action-keys.ts` > * `js/desktop/src/hooks/use-stream-autoplay.ts` > * `js/desktop/src/hooks/use-stream-keyboard-nav.ts` > * `js/desktop/src/hooks/use-stream-navigation-keys.ts` > * `js/desktop/src/hooks/use-stream-particles.ts` > * `js/desktop/src/hooks/use-stream-playback.ts` > * `js/desktop/src/hooks/use-suspend-playback.ts` > * `js/desktop/src/hooks/use-transcript-playback.ts` > * `js/desktop/src/huddle_window/HuddleApp.tsx` > * `js/desktop/src/huddle_window/renderer.tsx` > * `js/desktop/src/index.css` > * `js/desktop/src/lib/constants.ts` > * `js/desktop/src/lib/errors.ts` > * `js/desktop/src/lib/firestore-particles.ts` > * `js/desktop/src/lib/humans.ts` > * `js/desktop/src/lib/image-thumbnail.ts` > * `js/desktop/src/lib/keyboard.ts` > * `js/desktop/src/lib/particle-path.ts` > * `js/desktop/src/lib/platform/desktop-only.ts` > * `js/desktop/src/lib/platform/electron.ts` > * `js/desktop/src/lib/platform/index.ts` > * `js/desktop/src/lib/platform/index.web.ts` > * `js/desktop/src/lib/platform/types.ts` > * `js/desktop/src/lib/platform/web.ts` > * `js/desktop/src/lib/pusher-client.ts` > * `js/desktop/src/lib/pusher-provider.tsx` > * `js/desktop/src/lib/query-client.ts` > * `js/desktop/src/lib/random-name.ts` > * `js/desktop/src/lib/router-shell.tsx` > * `js/desktop/src/lib/router-shell.web.tsx` > * `js/desktop/src/lib/sentry.ts` > * `js/desktop/src/lib/sentry.web.ts` > * `js/desktop/src/lib/sound-effects/engine.ts` > * `js/desktop/src/lib/sound-effects/sound-effects-provider.tsx` > * `js/desktop/src/lib/sound-effects/sounds.ts` > * `js/desktop/src/lib/sound-effects/use-sound-effect.ts` > * `js/desktop/src/lib/stream-visibility.ts` > * `js/desktop/src/lib/time-utils.ts` > * `js/desktop/src/lib/utils.ts` > * `js/desktop/src/main.ts` > * `js/desktop/src/main/ipc-utils.ts` > * `js/desktop/src/main/sentry.ts` > * `js/desktop/src/preload.ts` > * `js/desktop/src/renderer.tsx` > * `js/desktop/src/screen_record_window/ScreenRecordControlApp.tsx` > * `js/desktop/src/screen_record_window/renderer.tsx` > * `js/desktop/src/stores/auth-store.ts` > * `js/desktop/src/stores/autoplay-payload-store.ts` > * `js/desktop/src/stores/autoplay-store.ts` > * `js/desktop/src/stores/compose-intent-store.ts` > * `js/desktop/src/stores/media-devices-store.ts` > * `js/desktop/src/stores/media-settings-store.ts` > * `js/desktop/src/stores/playback-pause-store.ts` > * `js/desktop/src/stores/session-store.ts` > * `js/desktop/src/stores/sound-effects-store.ts` > * `js/desktop/src/styles/globals.css` > * `js/desktop/src/web/renderer.tsx` > * `js/mobile/.prettierignore` > * `js/mobile/.prettierrc` > * `js/mobile/eslint.config.js` > * `js/mobile/package.json` > * `js/mobile/src/App.tsx` > * `js/mobile/src/api/client.ts` > * `js/mobile/src/api/types.ts` > * `js/mobile/src/components/Avatar.tsx` > * `js/mobile/src/components/BottomSheet.tsx` > * `js/mobile/src/components/ComposingIndicator.tsx` > * `js/mobile/src/components/FlowyLogo.tsx` > * `js/mobile/src/components/ListSeparator.tsx` > * `js/mobile/src/components/RelativeTimestamp.tsx` > * `js/mobile/src/config/env.ts` > * `js/mobile/src/features/auth/SignInScreen.tsx` > * `js/mobile/src/features/compose/AudioRecordingOverlay.tsx` > * `js/mobile/src/features/compose/ComposeDock.tsx` > * `js/mobile/src/features/compose/ReviewSheet.tsx` > * `js/mobile/src/features/compose/TextComposeModal.tsx` > * `js/mobile/src/features/compose/VideoRecordingOverlay.tsx` > * `js/mobile/src/features/huddle/HuddleScreen.tsx` > * `js/mobile/src/features/huddle/use-open-huddle.ts` > * `js/mobile/src/features/networks/Drawer.tsx` > * `js/mobile/src/features/networks/NetworkListScreen.tsx` > * `js/mobile/src/features/settings/AccountScreen.tsx` > * `js/mobile/src/features/settings/SettingsScreen.tsx` > * `js/mobile/src/features/stream-view/DeletedParticleView.tsx` > * `js/mobile/src/features/stream-view/EditParticleSheet.tsx` > * `js/mobile/src/features/stream-view/FallbackParticleView.tsx` > * `js/mobile/src/features/stream-view/MediaParticleView.tsx` > * `js/mobile/src/features/stream-view/PlaybackPageIndicator.tsx` > * `js/mobile/src/features/stream-view/ReactionSheet.tsx` > * `js/mobile/src/features/stream-view/ReactionStack.tsx` > * `js/mobile/src/features/stream-view/RenameStreamSheet.tsx` > * `js/mobile/src/features/stream-view/StreamActionsSheet.tsx` > * `js/mobile/src/features/stream-view/StreamMembersSheet.tsx` > * `js/mobile/src/features/stream-view/StreamMetadataHeader.tsx` > * `js/mobile/src/features/stream-view/StreamTopActions.tsx` > * `js/mobile/src/features/stream-view/StreamView.tsx` > * `js/mobile/src/features/stream-view/StreamViewScreen.tsx` > * `js/mobile/src/features/stream-view/TextParticleView.tsx` > * `js/mobile/src/features/stream-view/TranscriptOverlay.tsx` > * `js/mobile/src/features/stream-view/stream-presence-context.tsx` > * `js/mobile/src/features/stream-view/stream-safe-area.tsx` > * `js/mobile/src/features/stream-view/use-exit-countdown.ts` > * `js/mobile/src/features/streams/NewStreamScreen.tsx` > * `js/mobile/src/features/streams/StreamCard.tsx` > * `js/mobile/src/features/streams/StreamListScreen.tsx` > * `js/mobile/src/features/streams/VisibilityPickerSheet.tsx` > * `js/mobile/src/firebase.ts` > * `js/mobile/src/hooks/use-channel.ts` > * `js/mobile/src/hooks/use-event.ts` > * `js/mobile/src/hooks/use-networks.ts` > * `js/mobile/src/hooks/use-particle.ts` > * `js/mobile/src/hooks/use-stream-particles.ts` > * `js/mobile/src/hooks/use-stream-playback.ts` > * `js/mobile/src/hooks/use-suspend-playback.ts` > * `js/mobile/src/hooks/use-transcript-playback.ts` > * `js/mobile/src/lib/errors.ts` > * `js/mobile/src/lib/firestore-particles.ts` > * `js/mobile/src/lib/humans.ts` > * `js/mobile/src/lib/notification-routing.ts` > * `js/mobile/src/lib/particle-path.ts` > * `js/mobile/src/lib/push-notifications.ts` > * `js/mobile/src/lib/pusher-client.ts` > * `js/mobile/src/lib/pusher-provider.tsx` > * `js/mobile/src/lib/query-client.ts` > * `js/mobile/src/lib/random-name.ts` > * `js/mobile/src/lib/recording-audio-session.ts` > * `js/mobile/src/lib/stream-visibility.ts` > * `js/mobile/src/lib/time-utils.ts` > * `js/mobile/src/lib/upload.ts` > * `js/mobile/src/lib/utils.ts` > * `js/mobile/src/navigation/RootNavigator.tsx` > * `js/mobile/src/navigation/types.ts` > * `js/mobile/src/stores/auth-store.ts` > * `js/mobile/src/stores/playback-pause-store.ts` > > </details> > > You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file. > > Use the checkbox below for a quick retry: > - [ ] <!-- {"checkboxId": "e9bb8d72-00e8-4f67-9cb2-caf3b22574fe"} --> 🔍 Trigger review <!-- end of auto-generated comment: skip review by coderabbit.ai --> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing Touches</summary> <details> <summary>🧪 Generate unit tests (beta)</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `resolve-lint-issues` </details> </details> <!-- finishing_touch_checkbox_end --> <!-- tips_start --> --- <sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub> <!-- tips_end -->
talksik commented 2026-06-02 00:41:02 +00:00 (Migrated from github.com)

coderabbit review --dir js/mobile

coderabbit review --dir js/mobile
coderabbitai[bot] commented 2026-06-02 00:43:01 +00:00 (Migrated from github.com)

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# List the structure of js/mobile directory
tree js/mobile -L 4 2>/dev/null || find js/mobile -type f | head -80

echo "---"
# Check what files were changed in this PR within js/mobile
gh pr view 230 --repo flowy-live/llink --json files --jq '.files[].path' | grep "^js/mobile" || echo "No changed files in js/mobile found via API"

echo "---"
# Show the diff for js/mobile in this PR
gh pr diff 230 --repo flowy-live/llink -- js/mobile 2>/dev/null | head -300

Length of output: 3517


🏁 Script executed:

#!/bin/bash
# Check all changed files in PR `#230`
gh pr view 230 --repo flowy-live/llink --json files --jq '.files[].path'

echo "=== PR description ==="
gh pr view 230 --repo flowy-live/llink --json body --jq '.body'

echo "=== eslint config in js/mobile ==="
cat js/mobile/eslint.config.js

echo "=== package.json scripts in js/mobile ==="
cat js/mobile/package.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps({'scripts': d.get('scripts',{}), 'devDependencies': d.get('devDependencies',{})}, indent=2))"

Length of output: 6811


🏁 Script executed:

#!/bin/bash
echo "=== Check for prettier config in js/mobile ==="
find js/mobile -name ".prettierrc*" -o -name "prettier.config.*" 2>/dev/null

echo "=== tsconfig.json ==="
cat js/mobile/tsconfig.json

echo "=== babel.config.js ==="
cat js/mobile/babel.config.js

echo "=== metro.config.js ==="
cat js/mobile/metro.config.js

echo "=== tailwind.config.js ==="
cat js/mobile/tailwind.config.js

echo "=== app.config.ts ==="
cat js/mobile/app.config.ts

echo "=== index.ts ==="
cat js/mobile/index.ts

echo "=== src/App.tsx ==="
cat js/mobile/src/App.tsx

echo "=== src/api/client.ts ==="
cat js/mobile/src/api/client.ts

echo "=== src/api/types.ts ==="
cat js/mobile/src/api/types.ts

echo "=== src/config/env.ts ==="
cat js/mobile/src/config/env.ts

echo "=== src/firebase.ts ==="
cat js/mobile/src/firebase.ts

Length of output: 29333


🏁 Script executed:

#!/bin/bash
echo "=== .prettierrc ==="
cat js/mobile/.prettierrc

echo "=== eas.json ==="
cat js/mobile/eas.json

echo "=== src/lib/errors.ts ==="
cat js/mobile/src/lib/errors.ts

echo "=== src/stores/auth-store.ts ==="
cat js/mobile/src/stores/auth-store.ts

echo "=== src/navigation/RootNavigator.tsx ==="
cat js/mobile/src/navigation/RootNavigator.tsx

echo "=== src/lib/query-client.ts ==="
cat js/mobile/src/lib/query-client.ts

echo "=== src/lib/push-notifications.ts ==="
cat js/mobile/src/lib/push-notifications.ts

echo "=== src/features/auth/SignInScreen.tsx ==="
cat js/mobile/src/features/auth/SignInScreen.tsx

echo "=== nativewind-env.d.ts ==="
cat js/mobile/nativewind-env.d.ts

echo "=== global.css ==="
cat js/mobile/global.css

Length of output: 25380



@talksik — Note that PR #230 only touches js/desktop; js/mobile has no changed files in this diff. Here's a review of the current state of js/mobile:


Review: js/mobile

🔴 High — Sentry never initialized (src/App.tsx + src/lib/errors.ts)

src/lib/errors.ts exports installErrorSinks() and its own comment says it must be called from App.tsx, but App.tsx never imports or invokes it. This means captureSink and breadcrumbSink remain null for the entire app lifetime — Sentry is configured in src/config/env.ts but completely dead.

// src/App.tsx — add Sentry wiring, e.g.:
import { installErrorSinks } from '`@/lib/errors`';
import * as Sentry from '`@sentry/react-native`'; // or whichever SDK you're using

Sentry.init({ dsn: appConfig.sentryDsn, environment: appEnv });
installErrorSinks({
  capture: (err, ctx) => Sentry.captureException(err, { extra: ctx }),
  breadcrumb: (err, ctx) => Sentry.addBreadcrumb({ message: String(err), data: ctx }),
});

🟡 Medium — format script doesn't cover root-level config files

package.json:

"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\""

This misses app.config.ts, babel.config.js, metro.config.js, tailwind.config.js, eslint.config.js, and eas.json. All of these use double-quoted strings, which violates the .prettierrc setting "singleQuote": true. Suggested fix:

"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\" \"*.{ts,tsx,js,cjs,json}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\" \"*.{ts,tsx,js,cjs,json}\""

Similarly, eslint.config.js itself uses double quotes:

// current
const { defineConfig } = require("eslint/config");

// should be (after running prettier on it)
const { defineConfig } = require('eslint/config');

🟡 Medium — app.config.ts: stray blank line + missing trailing comma

app.config.ts (not covered by the current format script) has a blank line in the extra block and a missing trailing comma inside eas:

// current
extra: {
  eas: {
    projectId: "e902f7e5-e514-42bd-9591-75738e3494ed"  // ← missing trailing comma
  },
                                                         // ← stray blank line
  appEnv: APP_ENV,
},

// after prettier
extra: {
  eas: {
    projectId: 'e902f7e5-e514-42bd-9591-75738e3494ed',
  },
  appEnv: APP_ENV,
},

Both are resolved automatically once app.config.ts is included in the format glob above.


🔵 Low — Test-only export in production bundle (src/lib/push-notifications.ts)

_resetPushNotificationsModule() is documented as "Test-only" but is exported unconditionally and will be included in the production bundle. Consider guarding it:

// Only export in non-production environments
export const _resetPushNotificationsModule =
  process.env.NODE_ENV !== 'production'
    ? (): void => {
        tokenListenerSubscription?.remove();
        tokenListenerSubscription = null;
        configured = false;
      }
    : undefined;

Or move it to a test helper file that's excluded from the app bundle.


🔵 Low — Hardcoded colour in SignInScreen.tsx

// current
placeholderTextColor="`#878787`"

// prefer theme token (matches tailwind `ring` / `muted-foreground`)
import { colors } from '`@/lib/colors`'; // or however you expose theme tokens
placeholderTextColor={colors.mutedForeground}

What looks good

  • ESLint config (eslint.config.js) — expo flat config + eslint-config-prettier layering is correct; @typescript-eslint/no-unused-vars with ^_ ignore patterns is a good default.
  • .prettierrc settings are sensible and consistent with js/desktop.
  • src/lib/errors.ts error-classification and user-message logic is thorough.
  • src/stores/auth-store.ts sign-out ordering (stop sync → unregister token → call API → clear local) is correct.
  • src/lib/query-client.ts 401 → invalidateSession centralisation is clean.
  • Firebase long-polling opt-in (experimentalAutoDetectLongPolling: true) is the right call for React Native.
  • Push notification token-sync architecture (only active while authenticated) is well thought out.
<!-- This is an auto-generated reply by CodeRabbit --> > [!TIP] > For best results, initiate chat on the files or code changes. <details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ```shell #!/bin/bash # List the structure of js/mobile directory tree js/mobile -L 4 2>/dev/null || find js/mobile -type f | head -80 echo "---" # Check what files were changed in this PR within js/mobile gh pr view 230 --repo flowy-live/llink --json files --jq '.files[].path' | grep "^js/mobile" || echo "No changed files in js/mobile found via API" echo "---" # Show the diff for js/mobile in this PR gh pr diff 230 --repo flowy-live/llink -- js/mobile 2>/dev/null | head -300 ``` Length of output: 3517 --- 🏁 Script executed: ```shell #!/bin/bash # Check all changed files in PR `#230` gh pr view 230 --repo flowy-live/llink --json files --jq '.files[].path' echo "=== PR description ===" gh pr view 230 --repo flowy-live/llink --json body --jq '.body' echo "=== eslint config in js/mobile ===" cat js/mobile/eslint.config.js echo "=== package.json scripts in js/mobile ===" cat js/mobile/package.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps({'scripts': d.get('scripts',{}), 'devDependencies': d.get('devDependencies',{})}, indent=2))" ``` Length of output: 6811 --- 🏁 Script executed: ```shell #!/bin/bash echo "=== Check for prettier config in js/mobile ===" find js/mobile -name ".prettierrc*" -o -name "prettier.config.*" 2>/dev/null echo "=== tsconfig.json ===" cat js/mobile/tsconfig.json echo "=== babel.config.js ===" cat js/mobile/babel.config.js echo "=== metro.config.js ===" cat js/mobile/metro.config.js echo "=== tailwind.config.js ===" cat js/mobile/tailwind.config.js echo "=== app.config.ts ===" cat js/mobile/app.config.ts echo "=== index.ts ===" cat js/mobile/index.ts echo "=== src/App.tsx ===" cat js/mobile/src/App.tsx echo "=== src/api/client.ts ===" cat js/mobile/src/api/client.ts echo "=== src/api/types.ts ===" cat js/mobile/src/api/types.ts echo "=== src/config/env.ts ===" cat js/mobile/src/config/env.ts echo "=== src/firebase.ts ===" cat js/mobile/src/firebase.ts ``` Length of output: 29333 --- 🏁 Script executed: ```shell #!/bin/bash echo "=== .prettierrc ===" cat js/mobile/.prettierrc echo "=== eas.json ===" cat js/mobile/eas.json echo "=== src/lib/errors.ts ===" cat js/mobile/src/lib/errors.ts echo "=== src/stores/auth-store.ts ===" cat js/mobile/src/stores/auth-store.ts echo "=== src/navigation/RootNavigator.tsx ===" cat js/mobile/src/navigation/RootNavigator.tsx echo "=== src/lib/query-client.ts ===" cat js/mobile/src/lib/query-client.ts echo "=== src/lib/push-notifications.ts ===" cat js/mobile/src/lib/push-notifications.ts echo "=== src/features/auth/SignInScreen.tsx ===" cat js/mobile/src/features/auth/SignInScreen.tsx echo "=== nativewind-env.d.ts ===" cat js/mobile/nativewind-env.d.ts echo "=== global.css ===" cat js/mobile/global.css ``` Length of output: 25380 --- </details> --- `@talksik` — Note that PR `#230` only touches `js/desktop`; `js/mobile` has no changed files in this diff. Here's a review of the current state of `js/mobile`: --- ## Review: `js/mobile` ### 🔴 High — Sentry never initialized (`src/App.tsx` + `src/lib/errors.ts`) `src/lib/errors.ts` exports `installErrorSinks()` and its own comment says it must be called from `App.tsx`, but `App.tsx` never imports or invokes it. This means `captureSink` and `breadcrumbSink` remain `null` for the entire app lifetime — Sentry is configured in `src/config/env.ts` but completely dead. ```tsx // src/App.tsx — add Sentry wiring, e.g.: import { installErrorSinks } from '`@/lib/errors`'; import * as Sentry from '`@sentry/react-native`'; // or whichever SDK you're using Sentry.init({ dsn: appConfig.sentryDsn, environment: appEnv }); installErrorSinks({ capture: (err, ctx) => Sentry.captureException(err, { extra: ctx }), breadcrumb: (err, ctx) => Sentry.addBreadcrumb({ message: String(err), data: ctx }), }); ``` --- ### 🟡 Medium — `format` script doesn't cover root-level config files `package.json`: ```json "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\"" ``` This misses `app.config.ts`, `babel.config.js`, `metro.config.js`, `tailwind.config.js`, `eslint.config.js`, and `eas.json`. All of these use double-quoted strings, which violates the `.prettierrc` setting `"singleQuote": true`. Suggested fix: ```json "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md}\" \"*.{ts,tsx,js,cjs,json}\"", "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,css,md}\" \"*.{ts,tsx,js,cjs,json}\"" ``` Similarly, `eslint.config.js` itself uses double quotes: ```js // current const { defineConfig } = require("eslint/config"); // should be (after running prettier on it) const { defineConfig } = require('eslint/config'); ``` --- ### 🟡 Medium — `app.config.ts`: stray blank line + missing trailing comma `app.config.ts` (not covered by the current format script) has a blank line in the `extra` block and a missing trailing comma inside `eas`: ```ts // current extra: { eas: { projectId: "e902f7e5-e514-42bd-9591-75738e3494ed" // ← missing trailing comma }, // ← stray blank line appEnv: APP_ENV, }, // after prettier extra: { eas: { projectId: 'e902f7e5-e514-42bd-9591-75738e3494ed', }, appEnv: APP_ENV, }, ``` Both are resolved automatically once `app.config.ts` is included in the format glob above. --- ### 🔵 Low — Test-only export in production bundle (`src/lib/push-notifications.ts`) `_resetPushNotificationsModule()` is documented as "Test-only" but is exported unconditionally and will be included in the production bundle. Consider guarding it: ```ts // Only export in non-production environments export const _resetPushNotificationsModule = process.env.NODE_ENV !== 'production' ? (): void => { tokenListenerSubscription?.remove(); tokenListenerSubscription = null; configured = false; } : undefined; ``` Or move it to a test helper file that's excluded from the app bundle. --- ### 🔵 Low — Hardcoded colour in `SignInScreen.tsx` ```tsx // current placeholderTextColor="`#878787`" // prefer theme token (matches tailwind `ring` / `muted-foreground`) import { colors } from '`@/lib/colors`'; // or however you expose theme tokens placeholderTextColor={colors.mutedForeground} ``` --- ### ✅ What looks good - ESLint config (`eslint.config.js`) — expo flat config + `eslint-config-prettier` layering is correct; `@typescript-eslint/no-unused-vars` with `^_` ignore patterns is a good default. - `.prettierrc` settings are sensible and consistent with `js/desktop`. - `src/lib/errors.ts` error-classification and user-message logic is thorough. - `src/stores/auth-store.ts` sign-out ordering (stop sync → unregister token → call API → clear local) is correct. - `src/lib/query-client.ts` 401 → `invalidateSession` centralisation is clean. - Firebase long-polling opt-in (`experimentalAutoDetectLongPolling: true`) is the right call for React Native. - Push notification token-sync architecture (only active while authenticated) is well thought out.
talksik (Migrated from github.com) reviewed 2026-06-02 00:50:02 +00:00
talksik (Migrated from github.com) commented 2026-06-02 00:50:02 +00:00

coderabbit autofix to simplify the comment

coderabbit autofix to simplify the comment
talksik commented 2026-06-02 00:57:57 +00:00 (Migrated from github.com)
gh pr diff 230 --repo flowy-live/llink -- js/mobile 2>/dev/null | head -300

coderabbit review --dir ./js/mobile

> ```shell > gh pr diff 230 --repo flowy-live/llink -- js/mobile 2>/dev/null | head -300 > ``` coderabbit review --dir ./js/mobile
talksik commented 2026-06-02 00:59:18 +00:00 (Migrated from github.com)

@coderabbit review --dir ./js/mobile

@coderabbit review --dir ./js/mobile
coderabbitai[bot] commented 2026-06-02 01:01:02 +00:00 (Migrated from github.com)

Tip

For best results, initiate chat on the files or code changes.

@talksik — The full js/mobile review was already posted just above in this thread (my previous reply). Here's a quick summary of the findings in case it's easier to scan:

Severity Finding
🔴 High Sentry never initialized — installErrorSinks() is never called from App.tsx, so all error/breadcrumb sinks remain null
🟡 Medium format script glob misses root-level config files (app.config.ts, babel.config.js, metro.config.js, etc.) — they violate .prettierrc's singleQuote: true
🟡 Medium app.config.ts has a missing trailing comma + stray blank line (auto-fixed once included in the format glob)
🔵 Low _resetPushNotificationsModule() is a test-only export shipped in the production bundle
🔵 Low Hardcoded colour #878787 in SignInScreen.tsx — should use a theme token

The full code snippets and suggested fixes are in my previous comment. Let me know if you'd like me to dive deeper into any specific area or file!

<!-- This is an auto-generated reply by CodeRabbit --> > [!TIP] > For best results, initiate chat on the files or code changes. `@talksik` — The full `js/mobile` review was already posted just above in this thread (my previous reply). Here's a quick summary of the findings in case it's easier to scan: | Severity | Finding | |----------|---------| | 🔴 High | Sentry never initialized — `installErrorSinks()` is never called from `App.tsx`, so all error/breadcrumb sinks remain `null` | | 🟡 Medium | `format` script glob misses root-level config files (`app.config.ts`, `babel.config.js`, `metro.config.js`, etc.) — they violate `.prettierrc`'s `singleQuote: true` | | 🟡 Medium | `app.config.ts` has a missing trailing comma + stray blank line (auto-fixed once included in the format glob) | | 🔵 Low | `_resetPushNotificationsModule()` is a test-only export shipped in the production bundle | | 🔵 Low | Hardcoded colour `#878787` in `SignInScreen.tsx` — should use a theme token | The full code snippets and suggested fixes are in my previous comment. Let me know if you'd like me to dive deeper into any specific area or file!
Sign in to join this conversation.