sojorn/go-backend/internal/handlers/function_proxy.go
Patrick Britton 3c4680bdd7 Initial commit: Complete threaded conversation system with inline replies
**Major Features Added:**
- **Inline Reply System**: Replace compose screen with inline reply boxes
- **Thread Navigation**: Parent/child navigation with jump functionality
- **Chain Flow UI**: Reply counts, expand/collapse animations, visual hierarchy
- **Enhanced Animations**: Smooth transitions, hover effects, micro-interactions

 **Frontend Changes:**
- **ThreadedCommentWidget**: Complete rewrite with animations and navigation
- **ThreadNode Model**: Added parent references and descendant counting
- **ThreadedConversationScreen**: Integrated navigation handlers
- **PostDetailScreen**: Replaced with threaded conversation view
- **ComposeScreen**: Added reply indicators and context
- **PostActions**: Fixed visibility checks for chain buttons

 **Backend Changes:**
- **API Route**: Added /posts/:id/thread endpoint
- **Post Repository**: Include allow_chain and visibility fields in feed
- **Thread Handler**: Support for fetching post chains

 **UI/UX Improvements:**
- **Reply Context**: Clear indication when replying to specific posts
- **Character Counting**: 500 character limit with live counter
- **Visual Hierarchy**: Depth-based indentation and styling
- **Smooth Animations**: SizeTransition, FadeTransition, hover states
- **Chain Navigation**: Parent/child buttons with visual feedback

 **Technical Enhancements:**
- **Animation Controllers**: Proper lifecycle management
- **State Management**: Clean separation of concerns
- **Navigation Callbacks**: Reusable navigation system
- **Error Handling**: Graceful fallbacks and user feedback

This creates a Reddit-style threaded conversation experience with smooth
animations, inline replies, and intuitive navigation between posts in a chain.
2026-01-30 07:40:19 -06:00

63 lines
1.4 KiB
Go

package handlers
import (
"io"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
type FunctionProxyHandler struct {
supabaseURL string
anonKey string
}
func NewFunctionProxyHandler() *FunctionProxyHandler {
return &FunctionProxyHandler{
supabaseURL: os.Getenv("SUPABASE_URL"),
anonKey: os.Getenv("SUPABASE_SERVICE_ROLE_KEY"), // Using service role to bypass RLS/Auth if needed, or stick to Anon
}
}
func (h *FunctionProxyHandler) ProxyFunction(c *gin.Context) {
functionName := c.Param("name")
if functionName == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "Function name is required"})
return
}
targetURL := h.supabaseURL + "/functions/v1/" + functionName
// Create new request
req, err := http.NewRequest(c.Request.Method, targetURL, c.Request.Body)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"})
return
}
// Copy headers
for k, v := range c.Request.Header {
req.Header[k] = v
}
// Override Host and add Supabase Auth
req.Header.Set("Authorization", "Bearer "+h.anonKey)
req.Header.Set("apikey", h.anonKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
c.JSON(http.StatusBadGateway, gin.H{"error": "Failed to call Supabase function"})
return
}
defer resp.Body.Close()
// Copy response headers
for k, v := range resp.Header {
c.Writer.Header()[k] = v
}
c.Writer.WriteHeader(resp.StatusCode)
io.Copy(c.Writer, resp.Body)
}