Merging fork with main project#67
Conversation
…a lot. off branch. oops im bad at git. added and integrated notifications sign in and account management settings seach integration. added MD support added image and file support very poorly. added edit and delete functionality. added profile viewing added save functionality. kinda broke. trying to unify refresh and backend updates so that all data is accuratly displayed on frontend.
…interactions - Added SavedStreamsContext to manage saved projects with local storage and API integration. - Updated StreamsScreen to utilize saved project IDs and display builder projects. - Enhanced UserProfileScreen to load and display followers and following lists with search functionality. - Introduced UserCard component for displaying user information and follow/unfollow actions. - Refactored ProjectCard to integrate saved state and display save counts. - Improved media URL resolution across components. - Updated API services to fetch followers and following usernames. - Enhanced UI with new modal components for followers and following lists. - Adjusted color constants for better visual consistency.
- Added BootScreen component to simulate a boot sequence with GRUB and kernel messages. - Integrated animated transitions for a realistic loading experience. - Included randomization for boot messages and delays to enhance user experience. feat: enhance ProjectCard with real-time project stats updates - Integrated project event system to handle likes and saves in real-time. - Added subscription to project events for live updates on project stats. - Implemented pending emit logic to synchronize local state with server updates. fix: improve saved project management in SavedStreamsContext - Added removeSavedProjectIds function to handle batch removal of saved projects. - Normalized project IDs to ensure unique entries in saved projects. - Enhanced error handling during project follow/unfollow operations. style: update color constants for improved visibility - Changed tint colors to a brighter green for better contrast in light and dark modes. feat: create projectEvents service for managing project-related events - Established a centralized event system for project updates, deletions, and stats. - Implemented functions to emit and subscribe to project events for better state management.
There was a problem hiding this comment.
Pull request overview
This PR merges a substantial fork into the main project, introducing end-to-end features across frontend and backend: authentication, preferences/theming, saved content management, media uploads, real-time-like event updates, and notifications.
Changes:
- Added auth + preferences + notifications + saved-content contexts on the frontend, with new screens for streams/bytes/saved/notifications.
- Extended backend API with JWT auth middleware, media upload endpoint, notifications subsystem, post-saves, builder collaboration endpoints, and SQLite schema migration helpers.
- Refreshed UI theming/color system and introduced new UI components (ProjectCard, Markdown rendering, media gallery, header/backdrop/blur elements).
Reviewed changes
Copilot reviewed 87 out of 122 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/hooks/useThemeColor.ts | Switches theme color lookup to preference-aware useAppColors. |
| frontend/hooks/useMotionConfig.ts | Adds animation timing helpers based on user preferences. |
| frontend/hooks/useAutoRefresh.ts | Adds focus/background auto-refresh behavior with preferences. |
| frontend/hooks/useAppColors.ts | Centralizes theme colors + preference-defined accent color. |
| frontend/contexts/SavedStreamsContext.tsx | Adds saved streams state with server + local fallback and batch removal. |
| frontend/contexts/SavedContext.tsx | Adds saved posts state with server + local fallback. |
| frontend/contexts/PreferencesContext.tsx | Adds persisted preferences with optional backend sync. |
| frontend/contexts/NotificationsContext.tsx | Adds notifications fetching + push token registration + unread count state. |
| frontend/contexts/AuthContext.tsx | Adds token-based auth session + sign-in/up/out flows. |
| frontend/constants/Types.ts | Expands API/UI types for auth, settings, notifications, media, and saves. |
| frontend/constants/Colors.ts | Updates palette and introduces more semantic color tokens. |
| frontend/components/ui/TopBar.tsx | Replaces RNE header with custom themed top bar UI. |
| frontend/components/ui/TabBarBackground.ios.tsx | Hardens tab overflow helper and normalizes imports. |
| frontend/components/ui/IconSymbol.tsx | Extends symbol mapping and adjusts style typing. |
| frontend/components/header.tsx | Replaces header with themed brand row + notification badge + navigation. |
| frontend/components/filter.tsx | Replaces RNE FAB filter with themed modal panel filter UI. |
| frontend/components/tests/snapshots/ThemedText-test.tsx.snap | Removes snapshot output for ThemedText test. |
| frontend/components/tests/ThemedText-test.tsx | Replaces snapshot with a simpler assertion-based test. |
| frontend/components/UserCard.tsx | Adds reusable user card with follow action. |
| frontend/components/User.tsx | Upgrades user profile display, link opening logic, and avatar viewer modal. |
| frontend/components/TopBlur.tsx | Adds top blur overlay respecting safe area and theme. |
| frontend/components/ThemedText.tsx | Enhances text variants + compact mode scaling + link tint behavior. |
| frontend/components/TagChip.tsx | Adds themed tag chip component. |
| frontend/components/StatPill.tsx | Adds stat pill UI for compact metrics display. |
| frontend/components/SectionHeader.tsx | Adds section header with optional action affordance. |
| frontend/components/ScrollToTopButton.tsx | Replaces RNE icon with themed + haptic button. |
| frontend/components/ProjectCard.tsx | Adds project card with like/save, realtime stats sync, and saved integration. |
| frontend/components/MediaGallery.tsx | Adds media rendering (images/video/svg/web fallback) with modal image view. |
| frontend/components/MarkdownText.tsx | Adds markdown rendering with safer link opening and code copy UI. |
| frontend/components/HyprBackdrop.tsx | Adds animated gradient backdrop. |
| frontend/components/CreatePost.tsx | Replaces FAB with themed creation menu for stream/byte creation routes. |
| frontend/components/Collapsible.tsx | Updates to use useAppColors instead of raw Colors + scheme branching. |
| frontend/babel.config.js | Adds Expo babel config including reanimated plugin. |
| frontend/app/streams.tsx | Adds streams feed screen with saved filter + realtime events integration. |
| frontend/app/saved-streams.tsx | Adds saved streams screen with cleanup for missing projects. |
| frontend/app/saved-library.tsx | Adds saved posts library screen using saved-post IDs. |
| frontend/app/notifications.tsx | Adds notifications list screen with delete/clear/read + deep links. |
| frontend/app/bytes.tsx | Adds bytes feed screen with “following” filter + refresh/auto-refresh. |
| frontend/app/archive-bytes.tsx | Adds user archive screen for own posts with caching optimizations. |
| frontend/app/_layout.tsx | Adds providers + auth gating + boot screen + backdrop + themed stack content styling. |
| frontend/app/(tabs)/_layout.tsx | Updates tab bar styling with preference-driven compact padding. |
| frontend/app/(auth)/sign-up.tsx | Adds sign-up screen UI and form submission. |
| frontend/app/(auth)/sign-in.tsx | Adds sign-in screen UI and form submission. |
| frontend/app/(auth)/_layout.tsx | Adds separate auth stack layout. |
| frontend/app.json | Adds plugins for image picker, secure store, and expo-video. |
| backend/go.mod | Updates Go version + DB driver + adds JWT/crypto/sqlite deps. |
| backend/api/main.go | Adds auth/media/notifications routes, better CORS, sqlite driver switch, and binding updates. |
| backend/api/internal/types/types.go | Expands types (settings, saves, media, notifications/push tokens). |
| backend/api/internal/tests/main_test.go | Updates imports/driver for modernc sqlite. |
| backend/api/internal/spec/user-api.yml | Attempts to extend spec for listing users and get-by-id. |
| backend/api/internal/handlers/utils.go | Improves JSON tag matching + adds auth user id helper. |
| backend/api/internal/handlers/user_routes.go | Adds users listing + get-by-id + follow notifications. |
| backend/api/internal/handlers/project_routes.go | Adds builder management + auth checks + save notifications. |
| backend/api/internal/handlers/post_routes.go | Adds auth checks, post saving endpoints, and save notifications. |
| backend/api/internal/handlers/notifications_service.go | Adds helper to create + push notifications. |
| backend/api/internal/handlers/notifications_routes.go | Adds push token registration + notifications CRUD + Expo push sending. |
| backend/api/internal/handlers/media_routes.go | Adds authenticated file upload endpoint and URL return payload. |
| backend/api/internal/handlers/feed_routes.go | Adds pagination validation and caps. |
| backend/api/internal/handlers/comment_routes.go | Fixes query bug, adds auth checks, adds media support & notifications. |
| backend/api/internal/handlers/auth_routes.go | Adds register/login/me endpoints with bcrypt + JWT issuance. |
| backend/api/internal/handlers/auth_middleware.go | Adds Bearer token auth middleware and same-user guard. |
| backend/api/internal/database/utils.go | Supports JSON marshaling for settings/media in update helper. |
| backend/api/internal/database/post_saves_queries.go | Adds PostSaves queries for save/unsave/list. |
| backend/api/internal/database/post_queries.go | Extends post queries to include media and computed saves. |
| backend/api/internal/database/notification_queries.go | Adds notifications/push token storage + queries + unread count. |
| backend/api/internal/database/feed_queries.go | Extends feeds to include media, saves counts, and project about_md. |
| backend/api/internal/database/db.go | Adds SQLite PRAGMAs + schema bootstrapping/migrations. |
| backend/api/internal/database/create_test_data.sql | Adds settings column population for seeded users. |
| backend/api/internal/database/create_tables.sql | Extends schema with settings/media/saves/builders/notifications and indexes. |
| backend/api/internal/database/comment_queries.go | Extends comments with media + adds generalized update helper and fixes commentId query. |
| backend/api/internal/auth/jwt.go | Adds JWT claims + secret handling with defaults. |
| README.md | Adds Windows root script quick start documentation. |
| .vscode/settings.json | Adds tsserver excludes for node_modules. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function VideoItem({ source }: VideoItemProps) { | ||
| const player = useVideoPlayer(source, (instance) => { | ||
| instance.loop = true; | ||
| }); | ||
|
|
||
| return ( | ||
| <VideoView | ||
| player={player} | ||
| style={[styles.media, styles.video]} | ||
| contentFit="contain" | ||
| nativeControls | ||
| /> | ||
| ); | ||
| } | ||
| import { resolveMediaUrl } from "@/services/api"; | ||
|
|
||
| export function MediaGallery({ media }: MediaGalleryProps) { |
There was a problem hiding this comment.
There is an import statement mid-file (after a function declaration), which is a syntax error in TypeScript/ESM. Move import { resolveMediaUrl } ... to the top import section with the other imports.
| const [saveCount, setSaveCount] = useState(project.saves ?? 0); | ||
| const pendingEmitRef = useRef<{ | ||
| likes?: number; | ||
| saves?: number; |
There was a problem hiding this comment.
pendingEmitRef is typed to only allow { likes?: number; saves?: number }, but assignments include isLiked. This will fail type-checking. Update the ref type to include isLiked?: boolean (and ensure emitProjectStats expects/accepts that field), or stop writing isLiked into this payload.
| saves?: number; | |
| saves?: number; | |
| isLiked?: boolean; |
| pendingEmitRef.current = { | ||
| ...(pendingEmitRef.current ?? {}), | ||
| likes: nextLikes, | ||
| isLiked: false, | ||
| }; |
There was a problem hiding this comment.
pendingEmitRef is typed to only allow { likes?: number; saves?: number }, but assignments include isLiked. This will fail type-checking. Update the ref type to include isLiked?: boolean (and ensure emitProjectStats expects/accepts that field), or stop writing isLiked into this payload.
| pendingEmitRef.current = { | ||
| ...(pendingEmitRef.current ?? {}), | ||
| likes: nextLikes, | ||
| isLiked: true, | ||
| }; |
There was a problem hiding this comment.
pendingEmitRef is typed to only allow { likes?: number; saves?: number }, but assignments include isLiked. This will fail type-checking. Update the ref type to include isLiked?: boolean (and ensure emitProjectStats expects/accepts that field), or stop writing isLiked into this payload.
| const handleSaveToggle = async () => { | ||
| if (!user?.username || isSaving) { | ||
| return; | ||
| } | ||
| setIsSaving(true); | ||
| try { | ||
| const nextSaved = !isSaved; | ||
| const nextCount = Math.max(0, saveCount + (nextSaved ? 1 : -1)); | ||
| await toggleSave(project.id); |
There was a problem hiding this comment.
toggleSave from SavedStreamsContext supports the unauthenticated path (SecureStore), but handleSaveToggle currently hard-blocks when !user?.username. This prevents guest saving entirely. Consider only guarding on isSaving here (or splitting server vs local behavior), and let toggleSave handle auth vs guest internally.
| if err := ensurePostCommentSchema(); err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
ensurePostCommentSchema() is called twice in a row, which is redundant and makes the initialization flow harder to reason about. Remove the duplicated call.
| if err := ensurePostCommentSchema(); err != nil { | |
| return err | |
| } |
| actorID, _ := database.GetUserIdByUsername(username) | ||
| userID, _ := database.GetUserIdByUsername(newFollow) | ||
| createAndPushNotification( | ||
| int64(userID), | ||
| int64(actorID), | ||
| "follow_user", | ||
| nil, | ||
| nil, | ||
| nil, | ||
| notificationBody(username, "followed you"), | ||
| ) |
There was a problem hiding this comment.
The notification path ignores errors and does not validate actorID/userID before using them. If either lookup fails (or returns 0), this can create notifications for the wrong user (e.g., user id 0) or fail in surprising ways. Handle errors and ensure IDs are non-zero before calling createAndPushNotification.
| actorID, _ := database.GetUserIdByUsername(username) | |
| userID, _ := database.GetUserIdByUsername(newFollow) | |
| createAndPushNotification( | |
| int64(userID), | |
| int64(actorID), | |
| "follow_user", | |
| nil, | |
| nil, | |
| nil, | |
| notificationBody(username, "followed you"), | |
| ) | |
| actorID, err := database.GetUserIdByUsername(username) | |
| if err == nil && actorID != 0 { | |
| userID, err := database.GetUserIdByUsername(newFollow) | |
| if err == nil && userID != 0 { | |
| createAndPushNotification( | |
| int64(userID), | |
| int64(actorID), | |
| "follow_user", | |
| nil, | |
| nil, | |
| nil, | |
| notificationBody(username, "followed you"), | |
| ) | |
| } | |
| } |
| postInt, _ := strconv.Atoi(postId) | ||
| post, _ := database.QueryPost(postInt) | ||
| actorID, _ := database.GetUserIdByUsername(username) | ||
| if post != nil { |
There was a problem hiding this comment.
In SavePost (and similarly in UnsavePost), the strconv.Atoi error is ignored. If post_id is malformed, postInt becomes 0 and you may query/send notifications for an unintended post. Return a 400 Bad Request when parsing fails instead of continuing.
| post: | ||
| summary: Create new user | ||
| /users/id/{user_id}: | ||
| get: | ||
| summary: Get user by ID |
There was a problem hiding this comment.
The OpenAPI YAML structure appears invalid: /users/id/{user_id} is nested under /users -> post instead of being a top-level paths entry alongside /users. This will likely break spec parsing/rendering. Move /users/id/{user_id} to the same indentation level as /users, and ensure summary/requestBody/responses blocks are correctly aligned under each operation.
| func UploadMedia(context *gin.Context) { | ||
| file, err := context.FormFile("file") | ||
| if err != nil { | ||
| RespondWithError(context, http.StatusBadRequest, "Missing file") | ||
| return | ||
| } | ||
|
|
||
| if err := os.MkdirAll(uploadDir, 0o755); err != nil { | ||
| RespondWithError(context, http.StatusInternalServerError, "Failed to prepare upload directory") | ||
| return | ||
| } | ||
|
|
||
| ext := strings.ToLower(filepath.Ext(file.Filename)) | ||
| if ext == "" { | ||
| if file.Header.Get("Content-Type") != "" { | ||
| if guessed, err := mime.ExtensionsByType(file.Header.Get("Content-Type")); err == nil && len(guessed) > 0 { | ||
| ext = guessed[0] | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The upload endpoint accepts arbitrary files without enforcing size limits, an allowlist of MIME types/extensions, or content sniffing. Since files are then served from /uploads, this can enable storage abuse and potentially serve dangerous content types. Add server-side validation (max size, allowed content types/extensions), and consider forcing safe Content-Type handling (and/or Content-Disposition) when serving uploaded files.
|
PR 6 - 7 🤷♂️ |
Full Stack Integration & Testing
Major Features
Boot Sequence Experience
BootScreencomponent with simulated GRUB and kernel messagesReal-time Project Stats
Saved Projects Management
SavedStreamsContextwith local storage integrationremoveSavedProjectIdsfunction for batch removal operationsUser Social Features
UserProfileScreenwith followers/following listsUserCardcomponent for displaying user information and follow/unfollow actionsAuthentication & Account Management
Content Features
Technical Improvements
Architecture
projectEventsservice for managing project-related eventsComponent Updates
ProjectCardto integrate saved state and display save countsStreamsScreento utilize saved project IDs and display builder projectsStyling & UX
Possible issues with: