224 lines
7 KiB
Markdown
224 lines
7 KiB
Markdown
# 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<String, int> _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<String> _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() ?? <String>{};
|
|
}
|
|
```
|
|
|
|
## 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
|