From 2cc8cfb1d012b2069530a57e57c10e97bd4520f4 Mon Sep 17 00:00:00 2001 From: Patrick Britton Date: Sun, 1 Feb 2026 14:25:27 -0600 Subject: [PATCH] Reactions tweaks --- ...eactions-implementation-troubleshooting.md | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 sojorn_docs/reactions-implementation-troubleshooting.md diff --git a/sojorn_docs/reactions-implementation-troubleshooting.md b/sojorn_docs/reactions-implementation-troubleshooting.md new file mode 100644 index 0000000..00afa0e --- /dev/null +++ b/sojorn_docs/reactions-implementation-troubleshooting.md @@ -0,0 +1,223 @@ +# Reactions Feature Implementation & Troubleshooting + +## Overview +This document covers the complete implementation and troubleshooting of the reactions feature in the Sojorn application, including both backend (Go) and frontend (Flutter) components. + +## Problem Statement +The reactions feature had multiple issues: +1. **Backend 500 errors** when toggling reactions +2. **Frontend not showing reactions** on initial load (showing `null`) +3. **UI not updating immediately** after toggling reactions +4. **Need to refresh page** to see reaction changes + +## Backend Issues & Solutions + +### Issue 1: pgx.ErrNoRows vs sql.ErrNoRows +**Problem**: The Go backend was using `sql.ErrNoRows` to check for no rows in database queries, but pgx returns `pgx.ErrNoRows`. + +**Error**: +``` +ERR DEBUG: Failed to check existing reaction - unexpected error error="no rows in result set" +``` + +**Solution**: Update error handling in `internal/repository/post_repository.go`: +```go +import ( + "github.com/jackc/pgx/v5" // Add this import +) + +// Change from: +} else if err != sql.ErrNoRows { + +// To: +} else if err != pgx.ErrNoRows { +``` + +### Issue 2: JSON Serialization Omitting Empty Fields +**Problem**: The `Post` model had `omitempty` tags on reaction fields, causing them to be omitted from JSON responses when empty. + +**Solution**: Remove `omitempty` from reaction JSON tags in `internal/models/post.go`: +```go +// Before: +Reactions map[string]int `json:"reactions,omitempty"` +MyReactions []string `json:"my_reactions,omitempty"` +ReactionUsers map[string][]string `json:"reaction_users,omitempty"` + +// After: +Reactions map[string]int `json:"reactions"` +MyReactions []string `json:"my_reactions"` +ReactionUsers map[string][]string `json:"reaction_users"` +``` + +## Frontend Issues & Solutions + +### Issue 1: UI Not Updating Immediately +**Problem**: The `_reactionCountsFor` and `_myReactionsFor` methods prioritized `post.reactions` over local state, but after toggle reactions, local state had updated data while `post.reactions` still had old data. + +**Solution**: Change priority to prefer local state for immediate updates in `lib/screens/post/threaded_conversation_screen.dart`: + +```dart +Map _reactionCountsFor(Post post) { + // Prefer local state for immediate updates after toggle reactions + final localState = _reactionCountsByPost[post.id]; + if (localState != null) { + return localState; + } + // Fall back to post model if no local state + return post.reactions ?? {}; +} + +Set _myReactionsFor(Post post) { + // Prefer local state for immediate updates after toggle reactions + final localState = _myReactionsByPost[post.id]; + if (localState != null) { + return localState; + } + // Fall back to post model if no local state + return post.myReactions?.toSet() ?? {}; +} +``` + +## Implementation Steps + +### Backend Implementation +1. **Fix Error Handling**: + ```bash + cd go-backend + # Edit internal/repository/post_repository.go + # Add pgx import and change error handling + git add . && git commit -m "Fix ToggleReaction error handling - use pgx.ErrNoRows" + ``` + +2. **Fix JSON Serialization**: + ```bash + # Edit internal/models/post.go + # Remove omitempty from reaction fields + git add . && git commit -m "Remove omitempty from reaction JSON fields" + ``` + +3. **Deploy Backend**: + ```bash + cd /opt/sojorn/go-backend + git pull origin ThreadRestoration + sudo systemctl stop sojorn-api + go build -o ../bin/api ./cmd/api + sudo systemctl start sojorn-api + ``` + +### Frontend Implementation +1. **Fix UI Update Priority**: + ```bash + cd sojorn_app + # Edit lib/screens/post/threaded_conversation_screen.dart + # Update _reactionCountsFor and _myReactionsFor methods + git add . && git commit -m "Fix reaction UI updates - prioritize local state" + ``` + +## Debugging Techniques + +### Backend Debugging +1. **Add Debug Logging**: + ```go + log.Info().Str("postID", postID).Str("userID", userID).Msg("DEBUG: No existing reaction found (expected)") + log.Error().Err(err).Str("postID", postID).Str("userID", userID).Msg("DEBUG: Failed to check existing reaction - unexpected error") + ``` + +2. **Monitor Logs**: + ```bash + sudo tail -f /var/log/syslog | grep api + ``` + +### Frontend Debugging +1. **Add Debug Logging**: + ```dart + print('DEBUG: Toggle reaction response: $response'); + print('DEBUG: Updated local reaction counts: ${_reactionCountsByPost[postId]}'); + print('DEBUG: Using local state: ${localState}'); + ``` + +2. **Check API Response**: + ```dart + final response = await api.toggleReaction(postId, emoji); + print('DEBUG: API response: $response'); + ``` + +## Testing Checklist + +### Backend Tests +- [ ] Toggle reaction returns 200 (not 500) +- [ ] Reaction is saved to database +- [ ] API response includes updated counts and user reactions +- [ ] Empty reaction fields return `{}` and `[]` instead of `null` + +### Frontend Tests +- [ ] Reactions show on initial load +- [ ] Toggle reaction updates UI immediately +- [ ] No refresh needed to see changes +- [ ] Selected emoji shows as selected +- [ ] Reaction count updates correctly + +## Common Issues & Solutions + +### Issue: "no rows in result set" Error +**Cause**: Using `sql.ErrNoRows` instead of `pgx.ErrNoRows` +**Fix**: Update error handling to use `pgx.ErrNoRows` + +### Issue: Frontend Shows `null` for Reactions +**Cause**: `omitempty` in JSON tags omits empty fields +**Fix**: Remove `omitempty` from reaction field JSON tags + +### Issue: UI Not Updating After Toggle +**Cause**: UI prioritizes old post data over updated local state +**Fix**: Change priority to prefer local state for immediate updates + +### Issue: Need to Refresh to See Changes +**Cause**: Same as above - UI not using updated local state +**Fix**: Same solution - prioritize local state + +## Key Files Modified + +### Backend +- `internal/repository/post_repository.go` - Error handling fix +- `internal/models/post.go` - JSON serialization fix + +### Frontend +- `lib/screens/post/threaded_conversation_screen.dart` - UI update priority fix + +## Verification Commands + +### Backend Verification +```bash +# Check if service is running +sudo systemctl status sojorn-api + +# Check logs for errors +sudo tail -f /var/log/syslog | grep api + +# Test API endpoint +curl -X POST "http://194.238.28.122:8080/api/v1/posts/{post-id}/reactions/toggle" \ + -H "Authorization: Bearer {jwt-token}" \ + -H "Content-Type: application/json" \ + -d '{"emoji": "❤️"}' +``` + +### Frontend Verification +```bash +# Check Flutter logs +flutter run --verbose + +# Look for debug messages +grep "DEBUG:" flutter_logs.txt +``` + +## Success Criteria +✅ **Backend**: Toggle reactions return 200, no 500 errors +✅ **Frontend**: Reactions show immediately, no refresh needed +✅ **UI**: Selected emojis display correctly +✅ **Data**: Empty reactions show as empty, not null + +## Future Improvements +1. **Optimistic Updates**: Implement proper optimistic UI updates +2. **Error Handling**: Better error messages for failed reactions +3. **Performance**: Cache reaction data to reduce API calls +4. **Real-time**: WebSocket updates for live reaction changes