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:
@@ -1,14 +1,8 @@
|
||||
import { useCallback, useEffect } from "react";
|
||||
import {
|
||||
Alert,
|
||||
Dimensions,
|
||||
Pressable,
|
||||
Text,
|
||||
View,
|
||||
} from "react-native";
|
||||
import type { Human } from "@/api/types";
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { StatusBar } from "expo-status-bar";
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { Alert, Dimensions, Pressable, Text, View } from 'react-native';
|
||||
import type { Human } from '@/api/types';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import {
|
||||
AudioSession,
|
||||
LiveKitRoom,
|
||||
@@ -17,14 +11,14 @@ import {
|
||||
useLocalParticipant,
|
||||
useRoomContext,
|
||||
useTracks,
|
||||
} from "@livekit/react-native";
|
||||
import type { TrackReferenceOrPlaceholder } from "@livekit/components-core";
|
||||
import { Track } from "livekit-client";
|
||||
import { Mic, MicOff, PhoneOff, Video, VideoOff } from "lucide-react-native";
|
||||
import { useNetwork } from "@/hooks/use-networks";
|
||||
import { resolveHumanDisplay } from "@/lib/humans";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { RootStackScreenProps } from "@/navigation/types";
|
||||
} from '@livekit/react-native';
|
||||
import type { TrackReferenceOrPlaceholder } from '@livekit/components-core';
|
||||
import { Track } from 'livekit-client';
|
||||
import { Mic, MicOff, PhoneOff, Video, VideoOff } from 'lucide-react-native';
|
||||
import { useNetwork } from '@/hooks/use-networks';
|
||||
import { resolveHumanDisplay } from '@/lib/humans';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { RootStackScreenProps } from '@/navigation/types';
|
||||
|
||||
/**
|
||||
* Mobile huddle screen — LiveKit room with a tile grid, basic mic/camera
|
||||
@@ -35,7 +29,7 @@ import type { RootStackScreenProps } from "@/navigation/types";
|
||||
export function HuddleScreen({
|
||||
route,
|
||||
navigation,
|
||||
}: RootStackScreenProps<"Huddle">) {
|
||||
}: RootStackScreenProps<'Huddle'>) {
|
||||
const { token, serverUrl, streamName, networkId } = route.params;
|
||||
|
||||
// iOS in particular requires us to bracket the room session with
|
||||
@@ -66,10 +60,10 @@ export function HuddleScreen({
|
||||
connect={true}
|
||||
audio={true}
|
||||
video={false}
|
||||
options={{ adaptiveStream: { pixelDensity: "screen" } }}
|
||||
options={{ adaptiveStream: { pixelDensity: 'screen' } }}
|
||||
onDisconnected={leave}
|
||||
onError={(err) => {
|
||||
Alert.alert("Huddle error", err.message ?? "Failed to connect.");
|
||||
Alert.alert('Huddle error', err.message ?? 'Failed to connect.');
|
||||
leave();
|
||||
}}
|
||||
>
|
||||
@@ -119,15 +113,18 @@ function HuddleRoom({ networkId, streamName, onLeave }: HuddleRoomProps) {
|
||||
}, [room, onLeave]);
|
||||
|
||||
return (
|
||||
<SafeAreaView className="flex-1" edges={["top", "bottom"]}>
|
||||
<SafeAreaView className="flex-1" edges={['top', 'bottom']}>
|
||||
<View className="flex-row items-center justify-between px-4 pt-2 pb-3">
|
||||
<View className="flex-1">
|
||||
<Text className="text-white text-base font-semibold" numberOfLines={1}>
|
||||
<Text
|
||||
className="text-white text-base font-semibold"
|
||||
numberOfLines={1}
|
||||
>
|
||||
{streamName}
|
||||
</Text>
|
||||
<Text className="text-white/60 text-xs mt-0.5">
|
||||
{tracks.length === 1
|
||||
? "1 participant"
|
||||
? '1 participant'
|
||||
: `${tracks.length} participants`}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -139,7 +136,7 @@ function HuddleRoom({ networkId, streamName, onLeave }: HuddleRoomProps) {
|
||||
|
||||
<View className="flex-row items-center justify-center gap-4 px-4 py-4">
|
||||
<ControlButton
|
||||
label={isMicrophoneEnabled ? "Mute" : "Unmute"}
|
||||
label={isMicrophoneEnabled ? 'Mute' : 'Unmute'}
|
||||
active={isMicrophoneEnabled}
|
||||
onPress={toggleMic}
|
||||
icon={
|
||||
@@ -151,7 +148,7 @@ function HuddleRoom({ networkId, streamName, onLeave }: HuddleRoomProps) {
|
||||
}
|
||||
/>
|
||||
<ControlButton
|
||||
label={isCameraEnabled ? "Stop video" : "Start video"}
|
||||
label={isCameraEnabled ? 'Stop video' : 'Start video'}
|
||||
active={isCameraEnabled}
|
||||
onPress={toggleCamera}
|
||||
icon={
|
||||
@@ -182,7 +179,7 @@ function TileGrid({ tiles, humans }: TileGridProps) {
|
||||
// Compute a square-ish grid: 1 → 1col, 2 → 1col (stacked), 3-4 → 2col,
|
||||
// 5+ → 2col with scroll. Keeps each tile big enough on a phone screen.
|
||||
const columns = tiles.length <= 1 ? 1 : 2;
|
||||
const { width, height } = Dimensions.get("window");
|
||||
const { width, height } = Dimensions.get('window');
|
||||
const rows = Math.max(1, Math.ceil(tiles.length / columns));
|
||||
const tileWidth = (width - 16) / columns - 8;
|
||||
// Subtract approx chrome height (header + control bar ≈ 200px). This is a
|
||||
@@ -229,16 +226,12 @@ function Tile({
|
||||
return (
|
||||
<View
|
||||
className={cn(
|
||||
"flex-1 overflow-hidden rounded-2xl bg-neutral-900",
|
||||
isSpeaking && "border-2 border-emerald-400",
|
||||
'flex-1 overflow-hidden rounded-2xl bg-neutral-900',
|
||||
isSpeaking && 'border-2 border-emerald-400',
|
||||
)}
|
||||
>
|
||||
{hasVideo ? (
|
||||
<VideoTrack
|
||||
trackRef={tile}
|
||||
style={{ flex: 1 }}
|
||||
objectFit="cover"
|
||||
/>
|
||||
<VideoTrack trackRef={tile} style={{ flex: 1 }} objectFit="cover" />
|
||||
) : (
|
||||
<View className="flex-1 items-center justify-center">
|
||||
<View className="h-16 w-16 items-center justify-center rounded-full bg-neutral-700">
|
||||
@@ -261,7 +254,9 @@ function Tile({
|
||||
}
|
||||
|
||||
function trackKey(tile: TrackReferenceOrPlaceholder): string {
|
||||
const sid = isTrackReference(tile) ? tile.publication.trackSid : "placeholder";
|
||||
const sid = isTrackReference(tile)
|
||||
? tile.publication.trackSid
|
||||
: 'placeholder';
|
||||
return `${tile.participant.identity}:${tile.source}:${sid}`;
|
||||
}
|
||||
|
||||
@@ -270,7 +265,7 @@ interface ControlButtonProps {
|
||||
label: string;
|
||||
onPress: () => void;
|
||||
active?: boolean;
|
||||
tone?: "default" | "danger";
|
||||
tone?: 'default' | 'danger';
|
||||
}
|
||||
|
||||
function ControlButton({
|
||||
@@ -278,7 +273,7 @@ function ControlButton({
|
||||
label,
|
||||
onPress,
|
||||
active = false,
|
||||
tone = "default",
|
||||
tone = 'default',
|
||||
}: ControlButtonProps) {
|
||||
// Used purely for the visual state — destructive tone always wins so
|
||||
// "Leave" is unmistakable regardless of toggle state.
|
||||
@@ -287,16 +282,15 @@ function ControlButton({
|
||||
onPress={onPress}
|
||||
accessibilityLabel={label}
|
||||
className={cn(
|
||||
"h-14 w-14 items-center justify-center rounded-full",
|
||||
tone === "danger"
|
||||
? "bg-red-600 active:bg-red-700"
|
||||
'h-14 w-14 items-center justify-center rounded-full',
|
||||
tone === 'danger'
|
||||
? 'bg-red-600 active:bg-red-700'
|
||||
: active
|
||||
? "bg-white/20 active:bg-white/30"
|
||||
: "bg-white/10 active:bg-white/20",
|
||||
? 'bg-white/20 active:bg-white/30'
|
||||
: 'bg-white/10 active:bg-white/20',
|
||||
)}
|
||||
>
|
||||
{icon}
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user