diff --git a/.agents/tasks/prd-mobile-refactor.json b/.agents/tasks/prd-mobile-refactor.json
index 80cd09c..a134fcd 100644
--- a/.agents/tasks/prd-mobile-refactor.json
+++ b/.agents/tasks/prd-mobile-refactor.json
@@ -113,7 +113,7 @@
{
"id": "US-004",
"title": "Refactor oversized hooks/services/utils",
- "status": "in_progress",
+ "status": "done",
"dependsOn": [
"US-001"
],
@@ -125,13 +125,13 @@
"All previous exports remain available or are re-exported from the original entry point"
],
"startedAt": "2026-01-26T14:22:32.363863+00:00",
- "completedAt": null,
- "updatedAt": "2026-01-26T14:22:32.363979+00:00"
+ "completedAt": "2026-01-26T14:28:08.569075+00:00",
+ "updatedAt": "2026-01-26T14:28:08.568972+00:00"
},
{
"id": "US-005",
"title": "Validate refactor quality gates",
- "status": "open",
+ "status": "in_progress",
"dependsOn": [
"US-002",
"US-003",
@@ -142,7 +142,10 @@
"Run `npm test`, `npm run lint`, and `npm run typecheck` successfully",
"Example: all tests pass without modifications to test expectations",
"Negative case: if a check fails, refactor is incomplete and must be fixed before completion"
- ]
+ ],
+ "startedAt": "2026-01-26T14:28:10.644821+00:00",
+ "completedAt": null,
+ "updatedAt": "2026-01-26T14:28:10.644945+00:00"
}
]
}
diff --git a/.ralph/activity.log b/.ralph/activity.log
index 23ed54e..8d87bb2 100644
--- a/.ralph/activity.log
+++ b/.ralph/activity.log
@@ -1,6 +1,7 @@
# Activity Log
## Run Summary
+- 2026-01-26 14:28:08 | run=20260126-140911-55357 | iter=2 | mode=build | story=US-004 | duration=336s | status=success
- 2026-01-26 14:22:30 | run=20260126-140911-55357 | iter=1 | mode=build | story=US-003 | duration=799s | status=success
- 2026-01-25 21:09:07 | run=20260125-204012-65223 | iter=25 | mode=build | story=US-003 | duration=0s | status=error
- 2026-01-25 21:09:04 | run=20260125-204012-65223 | iter=24 | mode=build | story=US-003 | duration=0s | status=error
@@ -101,3 +102,11 @@
[2026-01-26 14:26:13] Ran tests and build for US-004
[2026-01-26 14:26:51] Updated progress log for US-004
[2026-01-26 14:27:24] Committed US-004 changes
+[2026-01-26 14:28:08] ITERATION 2 end (duration=336s)
+[2026-01-26 14:28:10] ITERATION 3 start (mode=build story=US-005)
+[2026-01-26 14:28:59] Start US-005 validation run (manual log; helper missing)
+[2026-01-26 14:29:29] Added root test script for US-005
+[2026-01-26 14:30:41] Fixed lint hook violations for US-005
+[2026-01-26 14:31:01] Ran npm test, lint, typecheck, build for US-005
+[2026-01-26 14:31:14] Added AGENTS.md operational notes
+[2026-01-26 14:32:00] Re-ran npm test after lint fixes
diff --git a/.ralph/runs/run-20260126-140911-55357-iter-2.md b/.ralph/runs/run-20260126-140911-55357-iter-2.md
new file mode 100644
index 0000000..50cd408
--- /dev/null
+++ b/.ralph/runs/run-20260126-140911-55357-iter-2.md
@@ -0,0 +1,32 @@
+# Ralph Run Summary
+
+- Run ID: 20260126-140911-55357
+- Iteration: 2
+- Mode: build
+- Story: US-004: Refactor oversized hooks/services/utils
+- Started: 2026-01-26 14:22:32
+- Ended: 2026-01-26 14:28:08
+- Duration: 336s
+- Status: success
+- Log: /Users/jjbrunton/Projects/Sauci/.ralph/runs/run-20260126-140911-55357-iter-2.log
+
+## Git
+- Head (before): 70449659cf1ded7041b71ecf07aa2e7bc76f8346
+- Head (after): 1370576dd59180f3b13e0a8d99255dfa96210d60
+
+### Commits
+- 1370576 chore(ralph): log commit action
+- 6957502 chore(ralph): update progress logs
+- 5a9defb refactor(swipe): split useSwipeScreen helpers
+
+### Changed Files (commits)
+- .agents/tasks/prd-mobile-refactor.json
+- .ralph/activity.log
+- .ralph/progress.md
+- .ralph/runs/run-20260126-140911-55357-iter-1.md
+- apps/mobile/src/features/swipe/hooks/useSwipeScreen.ts
+- apps/mobile/src/features/swipe/utils/useSwipeScreen-helpers.ts
+
+### Uncommitted Changes
+- .ralph/activity.log
+
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..d7f9a3d
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,7 @@
+# AGENTS
+
+## Verification
+- npm test (runs mobile Jest suite)
+- npm run lint
+- npm run typecheck
+- npm run build
diff --git a/apps/mobile/src/components/questions/QuestionCardAudio.tsx b/apps/mobile/src/components/questions/QuestionCardAudio.tsx
index b634fcc..96179c2 100644
--- a/apps/mobile/src/components/questions/QuestionCardAudio.tsx
+++ b/apps/mobile/src/components/questions/QuestionCardAudio.tsx
@@ -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 (
- {barAnimations.map((anim, index) => {
- const barStyle = useAnimatedStyle(() => ({
- height: interpolate(anim.value, [0, 1], [8, 40]),
- }));
-
- return (
-
- );
- })}
+ {barAnimations.map((anim, index) => (
+
+ ))}
);
}
+function AudioLevelBar({ anim }: { anim: SharedValue }) {
+ const barStyle = useAnimatedStyle(() => ({
+ height: interpolate(anim.value, [0, 1], [8, 40]),
+ }));
+
+ return (
+
+ );
+}
+
// Record button component
function RecordButton({ onPress }: { onPress: () => void }) {
const buttonScale = useSharedValue(1);
diff --git a/apps/mobile/src/features/chat/components/MessageContent.tsx b/apps/mobile/src/features/chat/components/MessageContent.tsx
index 5135631..d5d6a36 100644
--- a/apps/mobile/src/features/chat/components/MessageContent.tsx
+++ b/apps/mobile/src/features/chat/components/MessageContent.tsx
@@ -32,22 +32,7 @@ const MessageContentComponent: React.FC = ({
onImagePress,
onVideoFullScreen,
}) => {
- // Check if message was deleted for everyone
- if (item.deleted_at) {
- return (
-
-
-
- {isMe ? 'You deleted this message' : 'This message was deleted'}
-
-
- );
- }
-
+ 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 = ({
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 = ({
};
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 (
+
+
+
+ {isMe ? 'You deleted this message' : 'This message was deleted'}
+
+
+ );
+ }
+
if (isExpired && isVideo) {
return (
diff --git a/package.json b/package.json
index 7e0073b..89747ac 100755
--- a/package.json
+++ b/package.json
@@ -7,13 +7,14 @@
"apps/supabase",
"packages/*"
],
- "scripts": {
- "dev": "turbo dev",
- "build": "turbo build",
- "lint": "turbo lint",
- "clean": "turbo clean",
- "typecheck": "turbo typecheck"
- },
+ "scripts": {
+ "dev": "turbo dev",
+ "build": "turbo build",
+ "lint": "turbo lint",
+ "test": "npm --workspace apps/mobile test",
+ "clean": "turbo clean",
+ "typecheck": "turbo typecheck"
+ },
"devDependencies": {
"pg": "^8.17.2",
"turbo": "^2.3.3",