**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.
91 lines
3.8 KiB
Go
91 lines
3.8 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Post struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
AuthorID uuid.UUID `json:"author_id" db:"author_id"`
|
|
CategoryID *uuid.UUID `json:"category_id" db:"category_id"`
|
|
Body string `json:"body" db:"body"`
|
|
Status string `json:"status" db:"status"` // active, flagged, removed
|
|
ToneLabel *string `json:"tone_label" db:"tone_label"`
|
|
CISScore *float64 `json:"cis_score" db:"cis_score"`
|
|
ImageURL *string `json:"image_url" db:"image_url"`
|
|
VideoURL *string `json:"video_url" db:"video_url"`
|
|
ThumbnailURL *string `json:"thumbnail_url" db:"thumbnail_url"`
|
|
DurationMS int `json:"duration_ms" db:"duration_ms"`
|
|
BodyFormat string `json:"body_format" db:"body_format"` // plain, markdown
|
|
BackgroundID *string `json:"background_id" db:"background_id"`
|
|
Tags []string `json:"tags" db:"tags"`
|
|
IsBeacon bool `json:"is_beacon" db:"is_beacon"`
|
|
BeaconType *string `json:"beacon_type" db:"beacon_type"`
|
|
Location any `json:"location,omitempty" db:"location"` // geography(POINT)
|
|
Lat *float64 `json:"lat,omitempty"`
|
|
Long *float64 `json:"long,omitempty"`
|
|
Confidence float64 `json:"confidence_score" db:"confidence_score"`
|
|
IsActiveBeacon bool `json:"is_active_beacon" db:"is_active_beacon"`
|
|
AllowChain bool `json:"allow_chain" db:"allow_chain"`
|
|
ChainParentID *uuid.UUID `json:"chain_parent_id" db:"chain_parent_id"`
|
|
Visibility string `json:"visibility" db:"visibility"`
|
|
ExpiresAt *time.Time `json:"expires_at" db:"expires_at"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
EditedAt *time.Time `json:"edited_at,omitempty" db:"edited_at"`
|
|
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
|
|
|
// Joined fields (Scan targets)
|
|
AuthorHandle string `json:"-" db:"author_handle"`
|
|
AuthorDisplayName string `json:"-" db:"author_display_name"`
|
|
AuthorAvatarURL string `json:"-" db:"author_avatar_url"`
|
|
LikeCount int `json:"like_count" db:"like_count"`
|
|
CommentCount int `json:"comment_count" db:"comment_count"`
|
|
IsLiked bool `json:"is_liked" db:"is_liked"`
|
|
|
|
// Nested objects for JSON API
|
|
Author *AuthorProfile `json:"author,omitempty"`
|
|
IsSponsored bool `json:"is_sponsored,omitempty"`
|
|
}
|
|
|
|
type AuthorProfile struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Handle string `json:"handle"`
|
|
DisplayName string `json:"display_name"`
|
|
AvatarURL string `json:"avatar_url"`
|
|
}
|
|
|
|
type PostMetrics struct {
|
|
PostID uuid.UUID `json:"post_id" db:"post_id"`
|
|
LikeCount int `json:"like_count" db:"like_count"`
|
|
SaveCount int `json:"save_count" db:"save_count"`
|
|
ViewCount int `json:"view_count" db:"view_count"`
|
|
CommentCount int `json:"comment_count" db:"comment_count"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
}
|
|
|
|
type Category struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
Slug string `json:"slug" db:"slug"`
|
|
Name string `json:"name" db:"name"`
|
|
Description *string `json:"description" db:"description"`
|
|
IsSensitive bool `json:"is_sensitive" db:"is_sensitive"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
type Comment struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
PostID string `json:"post_id" db:"post_id"`
|
|
AuthorID uuid.UUID `json:"author_id" db:"author_id"`
|
|
Body string `json:"body" db:"body"`
|
|
Status string `json:"status" db:"status"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
|
}
|
|
|
|
type TagResult struct {
|
|
Tag string `json:"tag"`
|
|
Count int `json:"count"`
|
|
}
|