mirror of
https://github.com/DocNR/POWR.git
synced 2025-05-13 17:55:53 +00:00
289 lines
9.5 KiB
Markdown
289 lines
9.5 KiB
Markdown
![]() |
# Social Feed Implementation Plan
|
||
|
|
||
|
**Last Updated:** 2025-03-26
|
||
|
**Status:** Active
|
||
|
**Related To:** Social Features, NDK Integration, Feed Architecture
|
||
|
|
||
|
## Purpose
|
||
|
|
||
|
This document outlines the technical implementation plan for improving the social feed in the POWR app. It analyzes the best practices from both NDK and Olas implementations, providing a detailed roadmap for refactoring the current social feed architecture to be more performant, reliable, and maintainable.
|
||
|
|
||
|
## Implementation Strategy
|
||
|
|
||
|
### 1. Implement a Centralized Feed Management System
|
||
|
|
||
|
Based on both Olas and NDK's approaches:
|
||
|
|
||
|
- **Create a `FeedEntry` type** with clear support for different event kinds and content types
|
||
|
- **Implement state management using references** following NDK's pattern of using `Map` and `Set` references for better performance
|
||
|
- **Add proper event deduplication** using NDK's seen events tracking mechanism
|
||
|
|
||
|
### 2. Improve Event Subscription and Filtering
|
||
|
|
||
|
From NDK's implementation:
|
||
|
|
||
|
- **Utilize NDK's subscription options more effectively**:
|
||
|
```typescript
|
||
|
const subscription = ndk.subscribe(filters, {
|
||
|
closeOnEose: true,
|
||
|
cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST,
|
||
|
groupable: true,
|
||
|
skipVerification: false
|
||
|
});
|
||
|
```
|
||
|
|
||
|
- **Implement caching strategies** using NDK's caching mechanisms:
|
||
|
```typescript
|
||
|
// Try cache first, then relays
|
||
|
const cacheStrategy = NDKSubscriptionCacheUsage.CACHE_FIRST;
|
||
|
```
|
||
|
|
||
|
- **Use subscription grouping** to reduce relay connections for similar queries:
|
||
|
```typescript
|
||
|
// Group similar subscriptions with a delay
|
||
|
const groupableDelay = 100; // ms
|
||
|
```
|
||
|
|
||
|
### 3. Enhance Contact List Fetching
|
||
|
|
||
|
NDK offers more sophisticated contact list handling:
|
||
|
|
||
|
- **Use NDK's contact list event fetching** with explicit validation:
|
||
|
```typescript
|
||
|
// Direct method to get follows for a user
|
||
|
async followSet(opts?: NDKSubscriptionOptions): Promise<Set<Hexpubkey>> {
|
||
|
const follows = await this.follows(opts);
|
||
|
return new Set(Array.from(follows).map((f) => f.pubkey));
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- **Implement loading states and retry logic** using NDK's pattern:
|
||
|
```typescript
|
||
|
// Track loading state with cleanup on unmount
|
||
|
let isMounted = true;
|
||
|
// ...
|
||
|
return () => { isMounted = false; }
|
||
|
```
|
||
|
|
||
|
### 4. Enhanced Subscription Management
|
||
|
|
||
|
From NDK's subscription implementation:
|
||
|
|
||
|
- **Proper lifecycle management** for subscriptions:
|
||
|
```typescript
|
||
|
// Keep track of subscriptions for cleanup
|
||
|
const subscriptionRef = useRef<NDKSubscription | null>(null);
|
||
|
|
||
|
// Clean up subscription on component unmount
|
||
|
useEffect(() => {
|
||
|
return () => {
|
||
|
if (subscriptionRef.current) {
|
||
|
subscriptionRef.current.stop();
|
||
|
}
|
||
|
};
|
||
|
}, []);
|
||
|
```
|
||
|
|
||
|
- **Handle relay connection state** more effectively:
|
||
|
```typescript
|
||
|
// Monitor relay connections
|
||
|
ndk.pool.on('relay:connect', (relay: NDKRelay) => {
|
||
|
console.log(`Relay connected: ${relay.url}`);
|
||
|
});
|
||
|
```
|
||
|
|
||
|
### 5. Optimize Event Processing Pipeline
|
||
|
|
||
|
Based on NDK's efficient event handling:
|
||
|
|
||
|
- **Implement event processing with proper validation**:
|
||
|
```typescript
|
||
|
// Only process events that pass validation
|
||
|
if (!this.skipValidation) {
|
||
|
if (!ndkEvent.isValid) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- **Use NDK's event queuing and batch processing**:
|
||
|
```typescript
|
||
|
// Batch event processing for better performance
|
||
|
const updateEntries = (reason: string) => {
|
||
|
const newSlice = entriesFromIds(newEntriesRef.current);
|
||
|
// ... process in batch rather than individually
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- **Implement EOSE (End of Stored Events) handling** more effectively:
|
||
|
```typescript
|
||
|
// Handle EOSE with improved timing
|
||
|
subscription.on('eose', () => {
|
||
|
if (isMounted) {
|
||
|
setLoading(false);
|
||
|
setEose(true);
|
||
|
// Process any accumulated events after EOSE
|
||
|
updateEntries('eose');
|
||
|
}
|
||
|
});
|
||
|
```
|
||
|
|
||
|
### 6. Implement Progressive Loading
|
||
|
|
||
|
From NDK's subscription approach:
|
||
|
|
||
|
- **Use cache-first loading with fallback to relays**:
|
||
|
```typescript
|
||
|
// Try cache first for immediate feedback
|
||
|
if (ndk.cacheAdapter) {
|
||
|
const cachedEvents = await ndk.cacheAdapter.query(subscription);
|
||
|
if (cachedEvents.length > 0) {
|
||
|
// Process cached events immediately
|
||
|
processCachedEvents(cachedEvents);
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
- **Implement pagination with proper thresholds**:
|
||
|
```typescript
|
||
|
// Only fetch more when needed
|
||
|
if (hasMore && !loading && !refreshing) {
|
||
|
loadMore(oldestTimestamp - 1);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Key Architectural Improvements
|
||
|
|
||
|
1. **More Robust Feed State Management**:
|
||
|
- Use `useRef` for maintaining state references that don't trigger re-renders
|
||
|
- Implement batch updates for feed state changes
|
||
|
- Use proper cleanup and event deduplication
|
||
|
|
||
|
2. **Enhanced Subscription Management**:
|
||
|
- Use `NDKSubscription` with appropriate options
|
||
|
- Implement proper grouping and caching strategies
|
||
|
- Handle subscription lifecycle with proper cleanup
|
||
|
|
||
|
3. **Contact List Reliability**:
|
||
|
- Use multiple approaches to fetch and validate contacts
|
||
|
- Implement caching and retry logic for reliable contact detection
|
||
|
- Handle edge cases (like self-follows) appropriately
|
||
|
|
||
|
4. **Event Processing Optimization**:
|
||
|
- Implement more efficient event filtering and processing
|
||
|
- Use batch processing for events after EOSE
|
||
|
- Add proper validation and verification
|
||
|
|
||
|
5. **Performance Enhancements**:
|
||
|
- Use NDK's optimization patterns like subscription grouping
|
||
|
- Implement proper memory management for large event sets
|
||
|
- Use efficient data structures (Map/Set) for event tracking
|
||
|
|
||
|
## Implementation Plan
|
||
|
|
||
|
### Current Code Structure
|
||
|
|
||
|
The current implementation consists of:
|
||
|
|
||
|
1. **useFeedEvents.ts** - Core hook for handling feed events
|
||
|
2. **useFeedHooks.ts** - Specialized feed hooks (Following, POWR, Global)
|
||
|
3. **useFeedMonitor.ts** - For monitoring feed state and auto-refresh
|
||
|
4. **powr.tsx** - The POWR tab screen component
|
||
|
5. **following.tsx** - The Following tab screen component
|
||
|
6. **global.tsx** - The Global tab screen component
|
||
|
7. **EnhancedSocialPost.tsx** - Component for rendering feed posts
|
||
|
8. **socialFeedService.ts** - Service for interacting with Nostr
|
||
|
|
||
|
### Files to Update (Modify):
|
||
|
|
||
|
1. **useFeedEvents.ts** - Update with NDK's subscription patterns and better event processing
|
||
|
- Improve subscription lifecycle management
|
||
|
- Implement better event deduplication
|
||
|
- Add batch processing and performance optimizations
|
||
|
|
||
|
2. **useFeedHooks.ts** - Enhance contact list fetching and filter creation
|
||
|
- Implement multiple approaches for contact list fetching
|
||
|
- Improve filter creation for better relevance
|
||
|
- Remove hardcoded fallbacks in favor of more reliable mechanisms
|
||
|
|
||
|
3. **useFeedMonitor.ts** - Minor updates for integration with new feed structure
|
||
|
- Enhance refresh mechanisms
|
||
|
- Improve state tracking
|
||
|
|
||
|
4. **following.tsx** - Update to use the new feed architecture
|
||
|
- Remove debug code once implementation is stable
|
||
|
- Improve UI for feed state feedback
|
||
|
|
||
|
5. **powr.tsx** - Update to fix infinite loop issues
|
||
|
- Improve component lifecycle management
|
||
|
- Enhance performance
|
||
|
|
||
|
6. **global.tsx** - Update for consistency with other feed implementations
|
||
|
- Ensure consistent behavior across all feed tabs
|
||
|
|
||
|
7. **socialFeedService.ts** - Enhance with better relay interaction
|
||
|
- Improve subscription creation
|
||
|
- Add better event filtering
|
||
|
|
||
|
### Files to Create:
|
||
|
|
||
|
1. **useFeedState.ts** - New hook for centralized feed state management
|
||
|
```typescript
|
||
|
// Manage feed entries state with efficient updates
|
||
|
export function useFeedState() {
|
||
|
// Implementation here
|
||
|
}
|
||
|
```
|
||
|
|
||
|
2. **useFeedSubscription.ts** - New hook for subscription management
|
||
|
```typescript
|
||
|
// Handle NDK subscriptions with proper lifecycle
|
||
|
export function useFeedSubscription(filters: NDKFilter[]) {
|
||
|
// Implementation here
|
||
|
}
|
||
|
```
|
||
|
|
||
|
3. **types/feed.ts** - Enhanced type definitions for feed entries
|
||
|
```typescript
|
||
|
// More comprehensive feed entry types
|
||
|
export interface FeedEntry {
|
||
|
// Enhanced type definition
|
||
|
}
|
||
|
```
|
||
|
|
||
|
4. **utils/feedUtils.ts** - Utility functions for feed operations
|
||
|
```typescript
|
||
|
// Feed-related utility functions
|
||
|
export function deduplicateEvents() {
|
||
|
// Implementation
|
||
|
}
|
||
|
```
|
||
|
|
||
|
5. **components/feed/FeedList.tsx** - Shared component for feed rendering
|
||
|
```typescript
|
||
|
// Reusable feed list component with virtualization
|
||
|
export function FeedList({ entries, onItemPress }) {
|
||
|
// Implementation
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### Implementation Order
|
||
|
|
||
|
1. First, create the new type definitions in **types/feed.ts**
|
||
|
2. Then, implement the new hooks in **useFeedSubscription.ts** and **useFeedState.ts**
|
||
|
3. Update **useFeedEvents.ts** and **useFeedHooks.ts** with improved implementations
|
||
|
4. Create utility functions in **utils/feedUtils.ts**
|
||
|
5. Implement the shared component in **components/feed/FeedList.tsx**
|
||
|
6. Finally, update the screen components to use the new architecture
|
||
|
|
||
|
This approach allows gradual refactoring of the codebase while maintaining functionality throughout the process. Each step builds on the previous one, ultimately resulting in a more robust and efficient feed implementation.
|
||
|
|
||
|
## Related Documentation
|
||
|
|
||
|
- [Social Architecture](./architecture.md) - Overall social features architecture
|
||
|
- [Feed Filtering](./feed_filtering.md) - Rules for filtering content in social feeds
|
||
|
- [Cache Implementation](./cache_implementation.md) - Details on the social feed caching system
|
||
|
- [NDK Comprehensive Guide](../../technical/ndk/comprehensive_guide.md) - Reference for NDK implementation
|
||
|
- [NDK Subscription Analysis](../../technical/ndk/subscription_analysis.md) - Analysis of NDK subscription patterns
|
||
|
- [MVP and Targeted Rebuild](../../project/mvp_and_rebuild.md) - Overall project roadmap and priorities
|