infra: add linting and formatting for js projects (#230)

* wip

* wip

* wip

* format

* wip(mobile): lint and format

* cleanup

* nits

* nits

* idiomatic react

* nit

* format all root files
This commit was merged in pull request #230.
This commit is contained in:
Arjun Patel
2026-06-02 07:44:24 -07:00
committed by GitHub
parent 2fe562ce2b
commit a8a0b7db1b
258 changed files with 7822 additions and 5195 deletions
+66 -85
View File
@@ -1,43 +1,37 @@
import { useCallback, useEffect, useState } from "react";
import { Pressable, Text, View } from "react-native";
import { Mic, Type as TypeIcon, Video as VideoIcon } from "lucide-react-native";
import * as Haptics from "expo-haptics";
import { useCallback, useEffect, useState } from 'react';
import { Pressable, Text, View } from 'react-native';
import { Mic, Type as TypeIcon, Video as VideoIcon } from 'lucide-react-native';
import * as Haptics from 'expo-haptics';
import { useCameraPermissions, useMicrophonePermissions } from 'expo-camera';
import { toast } from 'sonner-native';
import { cn } from '@/lib/utils';
import { useEvent } from '@/hooks/use-event';
import { usePlaybackPauseStore } from '@/stores/playback-pause-store';
import { useAuthStore } from '@/stores/auth-store';
import { createTextParticle, uploadMediaParticle } from '@/lib/upload';
import type { ParticlePath } from '@/lib/particle-path';
import {
useCameraPermissions,
useMicrophonePermissions,
} from "expo-camera";
import { toast } from "sonner-native";
import { cn } from "@/lib/utils";
import { useEvent } from "@/hooks/use-event";
import { usePlaybackPauseStore } from "@/stores/playback-pause-store";
import { useAuthStore } from "@/stores/auth-store";
import {
createTextParticle,
uploadMediaParticle,
} from "@/lib/upload";
import type { ParticlePath } from "@/lib/particle-path";
import {
useStreamComposingBroadcast,
useStreamComposingBroadcastOptional,
type ComposingMode,
} from "@/features/stream-view/stream-presence-context";
import { TextComposeModal } from "./TextComposeModal";
import { VideoRecordingOverlay } from "./VideoRecordingOverlay";
import { AudioRecordingOverlay } from "./AudioRecordingOverlay";
import { ReviewSheet } from "./ReviewSheet";
} from '@/features/stream-view/stream-presence-context';
import { TextComposeModal } from './TextComposeModal';
import { VideoRecordingOverlay } from './VideoRecordingOverlay';
import { AudioRecordingOverlay } from './AudioRecordingOverlay';
import { ReviewSheet } from './ReviewSheet';
type RecordingMode = "video" | "audio";
type RecordingMode = 'video' | 'audio';
type ComposeUiState =
| { kind: "idle" }
| { kind: "recording"; mode: RecordingMode }
| { kind: 'idle' }
| { kind: 'recording'; mode: RecordingMode }
| {
kind: "review";
kind: 'review';
mode: RecordingMode;
uri: string;
durationMs: number;
}
| {
kind: "uploading";
kind: 'uploading';
mode: RecordingMode;
uri: string;
durationMs: number;
@@ -47,7 +41,7 @@ interface SubmitMediaParams {
fileUri: string;
mimeType: string;
durationMs: number;
source: "camera" | "screen";
source: 'camera' | 'screen';
}
interface ComposeDockProps {
@@ -75,8 +69,8 @@ export function ComposeDock({
}: ComposeDockProps) {
const userId = useAuthStore((s) => s.user?.id);
const [mode, setMode] = useState<RecordingMode>("video");
const [ui, setUi] = useState<ComposeUiState>({ kind: "idle" });
const [mode, setMode] = useState<RecordingMode>('video');
const [ui, setUi] = useState<ComposeUiState>({ kind: 'idle' });
const [textOpen, setTextOpen] = useState(false);
const [camPerm, requestCamPerm] = useCameraPermissions();
@@ -85,7 +79,7 @@ export function ComposeDock({
// Tell StreamView to fully unmount its expo-video player while we record.
// That player otherwise holds the iOS AVAudioSession and crashes the camera.
const setComposing = usePlaybackPauseStore((s) => s.setComposing);
const isComposing = ui.kind !== "idle" || textOpen;
const isComposing = ui.kind !== 'idle' || textOpen;
useEffect(() => {
setComposing(isComposing);
return () => setComposing(false);
@@ -98,13 +92,13 @@ export function ComposeDock({
if (forVideo) {
const cam = camPerm?.granted ? camPerm : await requestCamPerm();
if (!cam.granted) {
toast.error("Camera permission is required to record video.");
toast.error('Camera permission is required to record video.');
return false;
}
}
const mic = micPerm?.granted ? micPerm : await requestMicPerm();
if (!mic.granted) {
toast.error("Microphone permission is required to record.");
toast.error('Microphone permission is required to record.');
return false;
}
return true;
@@ -113,46 +107,45 @@ export function ComposeDock({
);
const startRecording = useEvent(async () => {
if (ui.kind !== "idle") return;
const ok = await ensurePermissions(mode === "video");
if (ui.kind !== 'idle') return;
const ok = await ensurePermissions(mode === 'video');
if (!ok) return;
void Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
setUi({ kind: "recording", mode });
setUi({ kind: 'recording', mode });
});
const handleRecordingComplete = useCallback(
({ uri, durationMs }: { uri: string; durationMs: number }) => {
void Haptics.selectionAsync();
setUi((prev) => {
const m = "mode" in prev ? prev.mode : mode;
return { kind: "review", mode: m, uri, durationMs };
const m = 'mode' in prev ? prev.mode : mode;
return { kind: 'review', mode: m, uri, durationMs };
});
},
[mode],
);
const handleRecordingCancel = useCallback(() => {
setUi({ kind: "idle" });
setUi({ kind: 'idle' });
}, []);
const sendReview = useEvent(async () => {
if (ui.kind !== "review" || !userId) return;
if (ui.kind !== 'review' || !userId) return;
const captured = ui;
setUi({
kind: "uploading",
kind: 'uploading',
mode: captured.mode,
uri: captured.uri,
durationMs: captured.durationMs,
});
try {
const mimeType =
captured.mode === "audio" ? "audio/mp4" : "video/mp4";
const mimeType = captured.mode === 'audio' ? 'audio/mp4' : 'video/mp4';
if (submitMedia) {
await submitMedia({
fileUri: captured.uri,
mimeType,
durationMs: captured.durationMs,
source: "camera",
source: 'camera',
});
} else {
const particleId = await uploadMediaParticle({
@@ -161,13 +154,13 @@ export function ComposeDock({
fileUri: captured.uri,
mimeType,
durationMs: captured.durationMs,
source: "camera",
source: 'camera',
createdByHumanId: userId,
});
onParticleCreated?.(particleId);
}
void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
setUi({ kind: "idle" });
setUi({ kind: 'idle' });
} catch (err) {
void Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
setUi(captured);
@@ -175,11 +168,11 @@ export function ComposeDock({
}
});
const retake = useCallback(() => setUi({ kind: "idle" }), []);
const cancelReview = useCallback(() => setUi({ kind: "idle" }), []);
const retake = useCallback(() => setUi({ kind: 'idle' }), []);
const cancelReview = useCallback(() => setUi({ kind: 'idle' }), []);
const submitText = useEvent(async (content: string) => {
if (!userId) throw new Error("Not signed in.");
if (!userId) throw new Error('Not signed in.');
if (submitTextOverride) {
await submitTextOverride(content);
} else {
@@ -195,9 +188,7 @@ export function ComposeDock({
});
const dockHidden =
ui.kind === "review" ||
ui.kind === "uploading" ||
ui.kind === "recording";
ui.kind === 'review' || ui.kind === 'uploading' || ui.kind === 'recording';
return (
<>
@@ -209,18 +200,18 @@ export function ComposeDock({
>
<Pressable
onPress={() =>
setMode((m) => (m === "video" ? "audio" : "video"))
setMode((m) => (m === 'video' ? 'audio' : 'video'))
}
disabled={ui.kind !== "idle"}
disabled={ui.kind !== 'idle'}
accessibilityLabel={`Switch to ${
mode === "video" ? "audio" : "video"
mode === 'video' ? 'audio' : 'video'
} mode`}
className={cn(
"h-11 w-11 items-center justify-center rounded-full bg-white/15",
ui.kind !== "idle" && "opacity-40",
'h-11 w-11 items-center justify-center rounded-full bg-white/15',
ui.kind !== 'idle' && 'opacity-40',
)}
>
{mode === "video" ? (
{mode === 'video' ? (
<VideoIcon color="white" size={20} strokeWidth={1.6} />
) : (
<Mic color="white" size={20} strokeWidth={1.6} />
@@ -230,24 +221,22 @@ export function ComposeDock({
<View className="items-center">
<Pressable
onPress={startRecording}
disabled={ui.kind !== "idle"}
disabled={ui.kind !== 'idle'}
accessibilityLabel={`Record ${mode}`}
className="h-20 w-20 items-center justify-center rounded-full bg-white"
>
<View className="h-6 w-6 rounded bg-black" />
</Pressable>
<Text className="text-white/60 mt-2 text-xs">
Tap to record
</Text>
<Text className="text-white/60 mt-2 text-xs">Tap to record</Text>
</View>
<Pressable
onPress={() => setTextOpen(true)}
disabled={ui.kind !== "idle"}
disabled={ui.kind !== 'idle'}
accessibilityLabel="Compose text"
className={cn(
"h-11 w-11 items-center justify-center rounded-full bg-white/15",
ui.kind !== "idle" && "opacity-40",
'h-11 w-11 items-center justify-center rounded-full bg-white/15',
ui.kind !== 'idle' && 'opacity-40',
)}
>
<TypeIcon color="white" size={20} strokeWidth={1.6} />
@@ -256,8 +245,8 @@ export function ComposeDock({
</View>
) : null}
{ui.kind === "recording" ? (
ui.mode === "video" ? (
{ui.kind === 'recording' ? (
ui.mode === 'video' ? (
<VideoRecordingOverlay
onComplete={handleRecordingComplete}
onCancel={handleRecordingCancel}
@@ -271,17 +260,13 @@ export function ComposeDock({
) : null}
<ReviewSheet
open={ui.kind === "review" || ui.kind === "uploading"}
uri={
ui.kind === "review" || ui.kind === "uploading" ? ui.uri : null
}
mode={
ui.kind === "review" || ui.kind === "uploading" ? ui.mode : null
}
open={ui.kind === 'review' || ui.kind === 'uploading'}
uri={ui.kind === 'review' || ui.kind === 'uploading' ? ui.uri : null}
mode={ui.kind === 'review' || ui.kind === 'uploading' ? ui.mode : null}
durationMs={
ui.kind === "review" || ui.kind === "uploading" ? ui.durationMs : 0
ui.kind === 'review' || ui.kind === 'uploading' ? ui.durationMs : 0
}
sending={ui.kind === "uploading"}
sending={ui.kind === 'uploading'}
onSend={sendReview}
onRetake={retake}
onCancel={cancelReview}
@@ -305,15 +290,11 @@ function useComposingBroadcast({
textOpen: boolean;
silent: boolean;
}) {
let broadcast: ReturnType<typeof useStreamComposingBroadcast> | null;
try {
broadcast = useStreamComposingBroadcast();
} catch {
broadcast = null;
}
// null when the dock is rendered outside a stream (no presence provider).
const broadcast = useStreamComposingBroadcastOptional();
const mode: ComposingMode | null =
ui.kind === "recording" ? "recording" : textOpen ? "typing" : null;
ui.kind === 'recording' ? 'recording' : textOpen ? 'typing' : null;
useEffect(() => {
if (silent || !broadcast) return;