Automated changelog | Oct 17 - Oct 24 | 48 hours (6 active days)
🎨 Display Settings Persistence & Synchronization
Backend: Display Settings Entity
Generic Key-Value Settings Storage
- Created
DisplaySettingentity with polymorphic user/project association - Fields:
projectId,userId(nullable for project-wide settings),settingKey,settingValue,isDefault - Unique compound index on
(projectId, userId, settingKey)for fast lookups - Additional indexes on
(projectId, userId)and(projectId, settingKey)for query optimization - Registered in TypeORM data source and GraphQL module
Frontend: DisplaySettingsNotifier (State Management)
Reactive Display Settings Architecture
- Created
DisplaySettingsNotifierextendingStateNotifier<int>for version-based reactivity - Wraps
DisplaySettingsRepositorywith increment-on-change pattern - Type-safe getter methods:
getString(),getDouble(),getBool(),getInt() - Convenience accessors for all settings:
- Shot List:
shotListRowHeight,shotListColumnsLayout,shotListDisplayMode,shotListOverlayOpacity - Storyboard:
storyboardLinearSize,storyboardGridSize - System:
systemSidebarExpanded,systemTheme
- Shot List:
- Provider:
displaySettingsNotifierProviderfor global state access - Asynchronous update with
notifySettingsChanged()triggering UI rebuilds
Frontend: Display Settings Integration
Refactoring for Persistence Support
- Selected project now persists across app restarts
- Deleted redundant
ShotListDisplayStateclass (91 lines removed) - Migrated all 13 widget files to use
DisplaySettingsNotifierfor reactive updates:shot_list_display_popup.dart: Direct settings UI controlshot_row.dart,scene_row.dart,banner_row.dart: Row rendering with settingsshot_list_header.dart: Column layout with settingsshot_list_reorder.dart: Drag-and-drop with settings-aware sizingresize_row_service.dart: Dynamic row height adjustmentshot_list.dart,selected_row.dart: Settings propagation
- Services refactored:
shot_list_display_service.dart: Complete removal ofShotListDisplayStatedependenciesprojects_service.dart: RemovedloadFromSettings()method
Display Settings Defaults
Configuration Constants
- Default values defined in
DisplaySettingKeys:shotListRowHeight: 50.0 pixels (changed from 52.0)shotListColumnsLayout: ‘fit’ mode (changed from ‘default’)shotListDisplayMode: ‘list’ viewshotListOverlayOpacity: 0.5 transparency
- Fallback chain: cached value → explicit default → DisplaySettingKeys.defaults → empty/zero
📋 Shot List Enhancements
Column Management System
Column Reordering
- Added
reorderShotListColumnsAPI endpoint for drag-and-drop column ordering - Frontend endpoint:
PUT /projects/{id}/shot-list-columns/reorder - Body:
{ columnIds: string[] }with desired column order - Enables user customization of column layout
Column Visibility Persistence
- Added
updateShotListColumnAPI endpoint for visibility and sizing configuration - Frontend endpoint:
PUT /projects/{id}/shot-list-columns/{columnId} - Body:
{ isVisible: boolean, extent: number, position: number } - Column visibility settings now persist per-project
Column Width to Extent Migration
- Renamed
columnWidth→extentinShotListColumnentity for semantic clarity - Database migration
ShotListColumnsUpdatehandles column rename with data preservation - Extent represents flexible sizing (pixels, percentage, or flex units)
Custom Column Options
- Added
customOptionsJSONB field toShotListColumnfor extensible metadata - Supports arbitrary key-value pairs for custom column types
- Enables future column types without schema changes
New Shot Column: Lens
Lens Field Addition
- Added
lensJSONB field to Shot entity for lens specifications - Supports structured data: focal length, aperture, lens model, etc.
- Migration
AddLensToShotsadds column with JSONB type - Enables detailed cinematography planning and equipment tracking
Shot List Performance & Data Integrity
Row Height Configuration
- Added
rowHeightfield toShotListDisplaySettingsentity (decimal, default: 50.0) - Per-project row height persistence for consistent shot list rendering
Row Color Support
- Added
rowColorId(integer) to bothShotListItemandBannerentities - Enables visual organization and categorization in shot lists
- Migration
AddShotListColorSupportadds color columns
Deferred Foreign Key Constraints
- Migration
DeferShotListParentConstraintaddsDEFERRABLE INITIALLY DEFERREDto parent_id FK - Enables cross-chunk operations in CineSync transactions without intermediate constraint violations
- Critical for bulk shot list reordering and hierarchy updates
- Constraint comment: “Deferred FK constraint allows cross-chunk operations in CineSync transactions”
📁 Media Explorer & File Management
File Entity Parent-Child Architecture
Hierarchical File Relationships
- Removed
thumbnailFileIdin favor of generic parent-child structure - Added
parentId(UUID, nullable) for hierarchical file organization - Added
fileTypeenum (ORIGINAL, THUMBNAIL) distinguishing file roles - Self-referential relations:
parent(ManyToOne) andchildren(OneToMany) - CASCADE delete on parent ensures orphaned file cleanup
Polymorphic File Associations
Media Explorer Entity Linking
- Added polymorphic fields for flexible file-entity associations:
entityType: String (e.g., ‘shot’, ‘scene’, ‘character’)entityId: String (UUID of associated entity)fileCategory: String (e.g., ‘reference’, ‘storyboard’, ‘thumbnail’)sortOrder: Integer for drag-and-drop ordering (default: 0)
Database Indexes for Performance
idx_files_entity_associationon(entityType, entityId, fileCategory)for entity file queriesidx_files_sort_orderon(entityType, entityId, fileCategory, sortOrder)for ordered listsidx_files_parent_idonparentIdfor parent-child traversal
File Storage Enhancements
CDN URL Support
- Added
thumbnailCdnUrlfield to File entity for direct CDN links - Reduces origin server load for thumbnail delivery
- Migration
AddThumbnailCdnUrlToFilesadds column as text (nullable)
Frontend: Media Explorer API Integration
New API Endpoints in ApiEndpoints
- Shot List Columns:
getShotListColumns,updateShotListColumn,createShotListColumn,deleteShotListColumn,reorderShotListColumns - Media Explorer:
getProjectFiles,getFilesByEntity,associateFileWithEntity,updateFileSortOrder,getStorageAnalytics,deleteFile,bulkDeleteFiles - All endpoints registered in
endpointsForValidationlist for documentation/validation
✍️ Script Editor Refactoring
Performance Improvements
Real-Time Formatting Speed Optimization
- Optimized Fountain format detection algorithms for faster character-by-character processing
- Reduced latency between typing and format application
- Improved responsiveness during rapid typing scenarios
- Enhanced SuperEditor integration for smoother editing experience
Persistence & Sync Stability
Enhanced CineSync Integration
- Improved document state synchronization reliability
- Better handling of concurrent edits and conflict resolution
- Reduced sync errors during rapid document modifications
- Stabilized offline-to-online transition behavior
- Enhanced error recovery mechanisms for failed sync operations
Code Quality & Maintenance
Major Cleanup
- Refactored core script editor components for better maintainability
- Removed redundant code and deprecated patterns
- Improved code organization and separation of concerns
- Enhanced type safety and null safety compliance
- Simplified state management flows
- Better error handling and logging throughout editor lifecycle
🎬 Storyboard Feature (In Progress - 30%)
Storyboard View System
Multiple View Modes
- Created
StoryboardViewsnavigation widget with 4 view types:- Linear View: Horizontal timeline-style storyboard
- Grid View: Grid layout for storyboard panels
- Script View: Script-integrated storyboard view
- Scene View: Scene-focused storyboard organization
- Route-based view detection via GoRouter path analysis
- Responsive design with mobile/desktop layouts
Linear Storyboard Implementation
LinearStoryboardViewwidget for horizontal panel layoutLinearStoryboardTopMenuBarfor view controls and actions- Scroll-based navigation with fade effects
- Display settings integration:
storyboardLinearSize: Configurable panel size (default: 200.0 pixels)storyboardGridSize: Grid view sizing (default: 150.0 pixels)
Storyboard Screens
- Renamed
storyboard_screen.dart→storyboard_grid_screen.dartfor clarity - Created
storyboard_linear_screen.dartfor linear timeline view - Route structure:
/storyboard,/storyboard/grid,/storyboard/script,/storyboard/scene
UI Components Created
StoryboardPanelWidget: Individual storyboard frame displayStoryboardDisplayPopup: Settings and configuration dialogSelectStoryboardSceneDialog: Scene selection interfacestoryboard_display_state.dart: State management for storyboard views
Hotkeys Integration
- Added
storyboardtoHotkeysFeatureScreenenum - Scene number navigation support via
storyboardSceneProvider - Scroll controller integration for keyboard-driven panel navigation
Feature Status: 30% Complete
- ✅ Basic UI structure and navigation
- ✅ Display settings persistence
- ✅ Multiple view type routing
- ✅ Linear view implementation
- 🚧 Grid view (partial)
- ⏳ Script integration view (planned)
- ⏳ Scene view (planned)
- ⏳ Panel editing and drawing tools
- ⏳ Image upload and management
- ⏳ Export functionality
🔐 Authentication & Token Management
Refresh Token Lifecycle Management
Automatic Token Cleanup
cleanupUserRefreshTokens(): Keeps only 15 most recent tokens per user (configurable)- Called automatically during
generateRefreshToken()to prevent token bloat - Multi-device support: 15 tokens allows 15 concurrent sessions per user
- Orders by
createdAt DESCand deletes oldest tokens beyond threshold
Expiration-Based Cleanup
cleanupExpiredRefreshTokens(): Deletes all tokens whereexpiresAt <= now- Uses TypeORM
LessThanOrEqual()operator for efficient query - Returns deletion count:
{ deleted: number } - Intended for scheduled cron job or periodic cleanup
Monitoring & Observability
getRefreshTokenStats(): Comprehensive token statistics- Total token count across all users
- Expired token count (non-active)
- Per-user active token breakdown:
{ userId, count }[] - Uses aggregation query with
COUNT()andGROUP BYfor scalability
Token Revocation Strategy Change
Hard Delete vs Soft Delete
- Changed
revokeRefreshToken()from UPDATE (isRevoked=true) to DELETE - Changed
revokeAllUserRefreshTokens()from soft delete to hard delete - Reduces database size and query complexity
- Improves compliance with data minimization principles
- Expired/revoked tokens no longer accumulate in database
Frontend: Simplified Token Refresh
Removal of TokenRefreshService Dependency
- Removed
TokenRefreshServicefromApiClientconstructor and interceptors AuthInterceptor: Removed proactive token refresh before requestsTokenRefreshInterceptor: Implements direct refresh without service layer dependency
📊 GraphQL & Sync System
CineSync Delta Operations
Display Settings Sync Implementation
- Full CRUD support for
DISPLAY_SETTINGentity type in delta operations - UPDATE operation: Find-or-create pattern with
manager.findOne()followed bymanager.save() - DELETE operation: Direct deletion with
manager.delete({ projectId, userId, settingKey }) - Server-side UUID generation for offline-created settings reaching server
- Transaction-wrapped operations ensure consistency
🧪 Testing & Development Workflow
Script Editor Integration Test (New)
Comprehensive Chaotic Typing Test
- Created
script_editor_test.dartintegration test using Patrol framework - Tests SuperEditor with realistic chaotic user behavior patterns
- Validates Fountain formatting system end-to-end
Test Scenario Coverage:
- Chaotic Scene Order: Scenes typed in intentional wrong order (Scene 3 → Scene 2 → Scene 1)
- Cut-Paste Operations: Tests selection, cut (Cmd+X), navigation, and paste operations
- Keyboard Navigation: Validates Cmd+Up/Down document navigation
- Content Reordering: Verifies editor handles content reorganization during active typing
Fountain Formatting Validation:
- Scene Headings: Auto-detection (INT./EXT.) and forced format (dot prefix)
- Transitions: Both prefix (>) and suffix (:) styles
- Centered Text: Tests > < wrapper syntax
- Lyrics: Tilde () prefix formatting
- Bold Text: Double asterisk (**) wrapper within centered text
- Character Names: Auto-detection and proper spacing
- Parentheticals: Dialog modifier formatting
- Dialogue: Multi-character conversation flow
Special Formatting Tests:
- Line-level prefixes: Scene headings (.), Transitions (>), Lyrics ()
- Wrapped syntax: Centered (> <), Bold (**), Director notes ([[ ]])
- Multi-step formatting: Centered + Bold combination
- Complex content: URLs, special characters, underscores in character names
Test Data Complexity:
- 3 interconnected scenes with dialogue, action, transitions
- Character names with special formatting (V.O., underscores)
- Technical terminology (URLs, protocol names, system commands)
- Mixed case sensitivity testing
- Multi-paragraph action blocks
Test Infrastructure:
- Uses
LiveTestWidgetsFlutterBindingFramePolicy.fullyLivefor real-time interaction - Avoids
pumpAndSettle()after focus to handle infinite cursor animation - Programmatic node selection and cursor positioning via DocumentPosition
- Clipboard verification for final document export
- 4-minute timeout for complex typing scenario
- Project switching logic with “Autotest” workspace detection
Validation Approach:
- Programmatic formatting map with expected results
- Line-by-line content matching and verification
- Button action simulation for special formatters
- Text selection validation for inline formatting
- Document structure integrity checks