fix(validation): satisfy quality gate checks

- add root test script that runs mobile jest
- adjust hook usage to satisfy rules-of-hooks
- document validation commands for operators
This commit is contained in:
jjbrunton committed 2026-01-26 14:32:23 +00:00
1 parent 1370576dd5
commit 368399f463
7 files changed
+106 -44

No files matched your search

@@ -13,6 +13,7 @@ import Animated, {
Easing,
FadeInDown,
FadeIn,
type SharedValue,
} from "react-native-reanimated";
import { Ionicons } from "@expo/vector-icons";
import { colors, gradients, radius, shadows, typography, spacing, animations } from "../../theme";
@@ -574,8 +575,13 @@ function PreviewContent({
// Audio level visualization component
function AudioLevelBars({ isActive }: { isActive: boolean }) {
const bars = 5;
const barAnimations = Array.from({ length: bars }, () => useSharedValue(0.3));
const barAnimations = [
useSharedValue(0.3),
useSharedValue(0.3),
useSharedValue(0.3),
useSharedValue(0.3),
useSharedValue(0.3),
];
useEffect(() => {
if (isActive) {
@@ -605,22 +611,25 @@ function AudioLevelBars({ isActive }: { isActive: boolean }) {
return (
<View style={styles.audioLevelContainer}>
{barAnimations.map((anim, index) => {
const barStyle = useAnimatedStyle(() => ({
height: interpolate(anim.value, [0, 1], [8, 40]),
}));
return (
<Animated.View
key={index}
style={[styles.audioLevelBar, barStyle]}
/>
);
})}
{barAnimations.map((anim, index) => (
<AudioLevelBar key={index} anim={anim} />
))}
</View>
);
}
function AudioLevelBar({ anim }: { anim: SharedValue<number> }) {
const barStyle = useAnimatedStyle(() => ({
height: interpolate(anim.value, [0, 1], [8, 40]),
}));
return (
<Animated.View
style={[styles.audioLevelBar, barStyle]}
/>
);
}
// Record button component
function RecordButton({ onPress }: { onPress: () => void }) {
const buttonScale = useSharedValue(1);
@@ -32,22 +32,7 @@ const MessageContentComponent: React.FC<MessageContentProps> = ({
onImagePress,
onVideoFullScreen,
}) => {
// Check if message was deleted for everyone
if (item.deleted_at) {
return (
<View style={styles.deletedContainer}>
<Ionicons
name="ban-outline"
size={14}
color={colors.textTertiary}
/>
<Text style={styles.deletedText}>
{isMe ? 'You deleted this message' : 'This message was deleted'}
</Text>
</View>
);
}
const isDeleted = !!item.deleted_at;
const isVideo = item.media_type === 'video';
const isViewed = !!item.media_viewed_at;
const isRecipientHidden = !isMe && !isViewed;
@@ -58,7 +43,7 @@ const MessageContentComponent: React.FC<MessageContentProps> = ({
const [mediaError, setMediaError] = useState(false);
useEffect(() => {
if (!item.media_path || isRecipientHidden) {
if (isDeleted || !item.media_path || isRecipientHidden) {
setMediaUri(null);
return;
}
@@ -85,11 +70,27 @@ const MessageContentComponent: React.FC<MessageContentProps> = ({
};
fetchMediaUrl();
}, [item.media_path, isRecipientHidden]);
}, [item.media_path, isRecipientHidden, isDeleted]);
// Handle expired videos
const isExpired = !!item.media_expired;
// Check if message was deleted for everyone
if (isDeleted) {
return (
<View style={styles.deletedContainer}>
<Ionicons
name="ban-outline"
size={14}
color={colors.textTertiary}
/>
<Text style={styles.deletedText}>
{isMe ? 'You deleted this message' : 'This message was deleted'}
</Text>
</View>
);
}
if (isExpired && isVideo) {
return (
<View>