**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.
102 lines
4.4 KiB
Go
102 lines
4.4 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type UserStatus string
|
|
|
|
const (
|
|
UserStatusPending UserStatus = "pending"
|
|
UserStatusActive UserStatus = "active"
|
|
UserStatusDeactivated UserStatus = "deactivated"
|
|
)
|
|
|
|
type User struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
Email string `json:"email" db:"email"`
|
|
PasswordHash string `json:"-" db:"encrypted_password"`
|
|
SupabaseID *uuid.UUID `json:"supabase_id,omitempty" db:"supabase_id"` // Keeping for legacy/migration if needed
|
|
Status UserStatus `json:"status" db:"status"`
|
|
MFAEnabled bool `json:"mfa_enabled" db:"mfa_enabled"`
|
|
LastLogin *time.Time `json:"last_login" db:"last_login"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
DeletedAt *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
|
|
}
|
|
|
|
type Profile struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
Handle *string `json:"handle" db:"handle"`
|
|
DisplayName *string `json:"display_name" db:"display_name"`
|
|
Bio *string `json:"bio" db:"bio"`
|
|
AvatarURL *string `json:"avatar_url" db:"avatar_url"`
|
|
CoverURL *string `json:"cover_url" db:"cover_url"`
|
|
IsOfficial *bool `json:"is_official" db:"is_official"`
|
|
IsPrivate *bool `json:"is_private" db:"is_private"`
|
|
BeaconEnabled bool `json:"beacon_enabled" db:"beacon_enabled"`
|
|
Location *string `json:"location" db:"location"`
|
|
Website *string `json:"website" db:"website"`
|
|
Interests []string `json:"interests" db:"interests"`
|
|
OriginCountry *string `json:"origin_country" db:"origin_country"`
|
|
Strikes int `json:"strikes" db:"strikes"`
|
|
IdentityKey *string `json:"identity_key" db:"identity_key"`
|
|
RegistrationID *int `json:"registration_id" db:"registration_id"`
|
|
EncryptedPrivateKey *string `json:"encrypted_private_key" db:"encrypted_private_key"`
|
|
HasCompletedOnboarding bool `json:"has_completed_onboarding" db:"has_completed_onboarding"`
|
|
Role string `json:"role" db:"role"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
}
|
|
|
|
type Follow struct {
|
|
FollowerID uuid.UUID `json:"follower_id" db:"follower_id"`
|
|
FollowingID uuid.UUID `json:"following_id" db:"following_id"`
|
|
Status string `json:"status" db:"status"` // pending, accepted
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
type TrustState struct {
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
HarmonyScore int `json:"harmony_score" db:"harmony_score"`
|
|
Tier string `json:"tier" db:"tier"` // new, trusted, established
|
|
PostsToday int `json:"posts_today" db:"posts_today"`
|
|
LastPostAt *time.Time `json:"last_post_at" db:"last_post_at"`
|
|
LastHarmonyCalcAt *time.Time `json:"last_harmony_calc_at" db:"last_harmony_calc_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
}
|
|
|
|
type AuthToken struct {
|
|
Token string `json:"token" db:"token"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
Type string `json:"type" db:"type"`
|
|
ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
type MFASecret struct {
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
Secret string `json:"-" db:"secret"`
|
|
RecoveryCodes []string `json:"-" db:"recovery_codes"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
}
|
|
|
|
type WebAuthnCredential struct {
|
|
ID []byte `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
PublicKey []byte `json:"public_key" db:"public_key"`
|
|
AttestationType string `json:"attestation_type" db:"attestation_type"`
|
|
AAGUID *uuid.UUID `json:"aaguid,omitempty" db:"aaguid"`
|
|
SignCount uint32 `json:"sign_count" db:"sign_count"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
LastUsedAt time.Time `json:"last_used_at" db:"last_used_at"`
|
|
}
|
|
|
|
type OneTimePrekey struct {
|
|
KeyID int `json:"key_id" db:"key_id"`
|
|
PublicKey string `json:"public_key" db:"public_key"`
|
|
}
|