diff --git a/smnb/components/livefeed/StoryCard.tsx b/smnb/components/livefeed/StoryCard.tsx index 6feabf0..340f413 100644 --- a/smnb/components/livefeed/StoryCard.tsx +++ b/smnb/components/livefeed/StoryCard.tsx @@ -13,14 +13,14 @@ interface StoryCardProps { className?: string; theme?: keyof typeof StoryThemes; showActions?: boolean; - onAction?: (action: 'read' | 'share' | 'bookmark', story: CompletedStory) => void; + onAction?: (action: 'read' | 'share' | 'bookmark' | 'pin' | 'unpin' | 'remove', story: CompletedStory) => void; } export default function StoryCard({ story, isFirst = false, className, - theme = isFirst ? 'highlighted' : 'default', + theme = story.isPinned ? 'pinned' : (isFirst ? 'highlighted' : 'default'), showActions = false, onAction }: StoryCardProps) { @@ -72,6 +72,13 @@ export default function StoryCard({ {story.tone} + {/* Pinned indicator */} + {story.isPinned && ( + + PINNED #{story.pinnedOrder} + + )} + {/* Thread indicators */} {story.isThreadUpdate && ( @@ -79,10 +86,52 @@ export default function StoryCard({ )} + {/* Action buttons - Pin and Remove (on hover) */} +
+ {onAction && ( + <> + {/* Pin/Unpin Button */} + + + {/* Remove Button */} + + + )} +
+ {/* Source attribution */} {story.originalItem?.subreddit && ( setIsBookmarked(!isBookmarked)} diff --git a/smnb/components/livefeed/liveFeed.tsx b/smnb/components/livefeed/liveFeed.tsx index 5c97375..a1f8dc9 100644 --- a/smnb/components/livefeed/liveFeed.tsx +++ b/smnb/components/livefeed/liveFeed.tsx @@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'; import React from 'react'; -import { useSimpleLiveFeedStore } from '@/lib/stores/livefeed/simpleLiveFeedStore'; +import { useSimpleLiveFeedStore, CompletedStory } from '@/lib/stores/livefeed/simpleLiveFeedStore'; import { Trash2 } from 'lucide-react'; import StoryCard from './StoryCard'; @@ -20,8 +20,50 @@ export default function LiveFeed({ className }: LiveFeedProps) { storyHistory, clearStoryHistory, loadStoriesFromConvex, + pinStory, + unpinStory, + removeStory, + addMultipleTestStories, } = useSimpleLiveFeedStore(); + // Sort stories with pinned ones first + const sortedStories = React.useMemo(() => { + return [...storyHistory].sort((a, b) => { + // Pinned stories first + if (a.isPinned && !b.isPinned) return -1; + if (!a.isPinned && b.isPinned) return 1; + + // If both pinned, sort by pinnedOrder + if (a.isPinned && b.isPinned) { + return (a.pinnedOrder || 0) - (b.pinnedOrder || 0); + } + + // For unpinned stories, maintain original order (newest first) + return b.timestamp.getTime() - a.timestamp.getTime(); + }); + }, [storyHistory]); + + // Handle story actions + const handleStoryAction = (action: 'read' | 'share' | 'bookmark' | 'pin' | 'unpin' | 'remove', story: CompletedStory) => { + switch (action) { + case 'pin': + pinStory(story.id); + break; + case 'unpin': + unpinStory(story.id); + break; + case 'remove': + removeStory(story.id); + break; + case 'read': + case 'share': + case 'bookmark': + // These actions can be handled later if needed + console.log(`${action} action for story:`, story.id); + break; + } + }; + // Check for reduced motion preference useEffect(() => { const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); @@ -44,9 +86,17 @@ export default function LiveFeed({ className }: LiveFeedProps) { {/* Fixed Header */}
- Live Stories {storyHistory.length > 0 ? `(${storyHistory.length})` : ''} + Live Stories {sortedStories.length > 0 ? `(${sortedStories.length})` : ''}
+ {/* Add test stories button for demonstration */} +