Add support for running both Jellyfin and Xtream providers simultaneously:
- User can have 1 active JF account + 1 active XC account at same time
- Tabs dynamically show/hide based on active providers
- Account switcher allows switching between multiple saved accounts
New Components:
- XtreamSession: Session management for Xtream providers
- SessionManager: Tracks both JF and XC sessions
- XtreamView/ViewModel: New Xtream tab with Live TV categories
- TabCoordinator: Dynamic tab building based on active providers
Modified Components:
- MainTabView: Injects SessionManager, rebuilds tabs on provider changes
- TabItem: Added Xtream tab definition
- MediaViewModel: Excludes Xtream channels (now in Xtream tab only)
Scripts:
- Added .claude/scripts/create-issue.sh for Gitea issue creation
Closes: jellyflood-2 (partial)
Related: jellyflood-1, jellyflood-5
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rebrand from Swiftfin to jellyflood
- Remove iOS/TestFlight/App Store references (tvOS only)
- Update logo with pink gradient (#FF1493 to #FF69B4)
- Add Xtream plugin and EPG feature highlights
- Remove translation/community links
- Simplify to personal fork documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Complete rebranding from jellypig to jellyflood including:
- Renamed all jellypig references to jellyflood
- Updated store implementations (jellypigstore -> jellyfloodstore)
- Moved jellypig tvOS to Swiftfin tvOS structure
- Updated service configurations and defaults
- Preserved all Xtream plugin support and EPG functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Features:
- Full EPG grid with channels and time slots
- 12-hour program window with auto-refresh every 5 minutes
- Duration-based cell widths (3px/min)
- Live program highlighting with progress bars
- Current time indicator (red line)
- Direct channel playback from guide
- Auto-scroll to currently airing programs
Changes:
- Add EPGViewModel for data fetching and state management
- Add EPGProgramCell, EPGChannelRow, EPGTimelineHeader, EPGCurrentTimeIndicator components
- Update ProgramGuideView with complete EPG implementation
- Make Channels default Live TV tab (was Program Guide)
- Fix channel images in EPG to match Channels view display
- Fix Live TV playback crash (audioStreams array bounds check)
- Apply dark pink background throughout app
Slash Commands:
- Add /init-dev - Initialize dev session with project context
- Add /sim - Build and launch in Apple TV simulator
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Add SwiftGen configuration for xcassets to swiftgen.yml
- Generate Images+Generated.swift for type-safe image resources
- Fixes 'Type ImageResource has no member' errors in Release builds
- Generated file includes device icons, blob icons, and tomato ratings
This was needed because the asset catalog references were missing
the generated Swift code for type-safe access.
Reverted video player back to .fullScreen presentation:
- Changed @Route(.push) back to @Route(.fullScreen)
- Added NavigationViewCoordinator wrapper back
- Changed router.popLast() back to router.dismissCoordinator()
Video player MUST use fullScreen to:
✅ Properly stop playback on dismiss
✅ Show overlay controls on first ESC
✅ Exit and stop video on second ESC
✅ Prevent video playing in background after navigation
Files reverted:
- ItemCoordinator.swift: Video player route and factory
- Overlay.swift: dismissCoordinator on confirm close
- VideoPlayer.swift: dismissCoordinator on video end
- LoadingView.swift: dismissCoordinator on cancel
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed all router.dismissCoordinator() calls to router.popLast() in video player:
- Overlay.swift: Back button when confirming close
- VideoPlayer.swift: Auto-exit when video ends
- LoadingView.swift: Cancel button during loading
dismissCoordinator() only works with .fullScreen/.modal presentations.
Since we changed video player to .push navigation, we need popLast() instead.
This fixes ESC/menu button not working during video playback.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed video player from .fullScreen to .push navigation:
- Removed NavigationViewCoordinator wrapper
- Video player now returns VideoPlayerCoordinator directly
This should allow ESC/back button to work during video playback.
MediaCoordinator kept at .fullScreen to prevent Home screen navigation bug.
Trade-offs:
✅ Video player ESC should now work
✅ Pressing back from empty channel goes to Media tab (not Home)
❌ Error dismissal still returns to Media tab (dismisses entire .fullScreen presentation)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- MediaCoordinator: Use .fullScreen for tvOS (full-screen display with navigation)
- HomeCoordinator, LibraryCoordinator, SearchCoordinator: Use .push without NavigationViewCoordinator wrappers
- Unified tvOS and iOS coordinator return types for push navigation
This fixes:
✅ Channels display full-screen (not modal popup)
✅ Login and settings use full-screen navigation
✅ Items from Home/Search display correctly
Known issues with .fullScreen presentation:
- Pressing ESC on error dismisses entire channel instead of going back one level
- Video player doesn't respond to ESC during playback
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed all modal routes to push in login and settings coordinators:
- SelectUserCoordinator: login flow, server connection, advanced settings
- UserSignInCoordinator: quick connect, security settings
- SettingsCoordinator: all settings pages (both iOS and tvOS)
- AppSettingsCoordinator: log viewer
All screens now use full-screen push navigation instead of modal popups.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed item routing from .modal to .push in HomeCoordinator, LibraryCoordinator, and SearchCoordinator. Individual media items (movies, episodes, etc.) now open full-screen instead of in modal dialogs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed MediaCoordinator routing from .modal to .push for tvOS to match native library behavior. All channels (Xtream VOD, Xtream Series, Live TV, etc.) now display in full-screen grid layout instead of a small centered modal window.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changes:
- Update bundle identifier from org.jellyfin.swiftfin to org.ashik.jellypig
- Updated in project.pbxproj (4 occurrences)
- Updated in LogManager.swift (logger label)
- Updated in DataCache.swift (cache paths)
- Fix SwiftGen build script to skip gracefully without error
- Changed "error:" to "note:" to prevent Xcode build errors
- Script now exits cleanly when SwiftGen not installed (English-only fork)
This allows the app to be signed with a personal Apple Developer account
and built successfully without SwiftGen dependency.
- Add .channel to BaseItemKind.supportedCases for proper filtering
- Implement channel API routing in ItemLibraryViewModel
- Add comprehensive debug logging to track API calls and filtering
- Support channels in MediaViewModel library views
- Fix channel items not appearing in media libraries
This enables Xtream plugin channels (VOD/Series) to display correctly
in jellypig tvOS. Channels now use proper /Channels API endpoints
instead of falling back to regular /Items API.
Related to ongoing fix for Xtream content media display.
- Modified ItemLibraryViewModel to detect channel/channelFolderItem types
- Added getChannelItems() method to use Paths.getChannelItems API for channels
- Channel folders now use channelID and folderID parameters correctly
- Modified PagingLibraryView to route .channelFolderItem to library grid view
This enables proper navigation for Jellyfin.Xtream plugin channels:
Channel → Grid of Categories → Grid of Content → Item Detail
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed the jellyfin-blob.svg gradient from blue (#1F4EA7 to #00DDFF)
to bright pink (#C8197C to #FF1493) to match the jellypig branding.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added DeviceIcons from upstream to tvOS assets catalog
- Built and installed SwiftGen 6.6.3 from source to /opt/homebrew/bin
- Build now succeeds with all ImageResource references resolved
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Renamed SwiftfinApp.swift to jellypigapp.swift
- Renamed SwiftfinStore/ to jellypigstore/
- Renamed all SwiftfinStore files to jellypigstore
- Renamed SwiftfinDefaults.swift to jellypigdefaults.swift
- Renamed VideoPlayerType+Swiftfin.swift to VideoPlayerType+jellypig.swift
- Updated all project.pbxproj file references to match new names
All file names now use lowercase jellypig for consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Revert SwiftfinApp/SwiftfinStore file name changes (files weren't renamed, only refs)
- Change SwiftGen error to warning and exit 0 instead of return 1
- Allows build to continue without SwiftGen installed (English-only fork)
- Converted all 14 tvOS icon PNG files from blue to hot pink
- Applied to app icons, top shelf images, and App Store icons
- Distinguishes jellypig from upstream Swiftfin visually
- Used Python script with Pillow for color transformation
- Removed entire jellypig iOS directory
- Removed jellypig iOS.xcscheme
- jellypig is now tvOS-only for Apple TV usage
- Focusing on Jellyfin.Xtream plugin compatibility
* off recursive
* pr feedback
* Cleanup
Instantiate the collectionType in the `if let` since failure to cast `as? BaseItemDto` should count as false as well. Only set `parameters.isRecursive` once in if/else opposed to if -> override.
* wip
* fix recursive and item kinds
* rename, fix folders
---------
Co-authored-by: Quang <quang.ha@a2:3c:68:56:26:8d.home>
Co-authored-by: Joe <jpkribs@outlook.com>
Co-authored-by: Ethan Pippin <ethanpippin2343@gmail.com>
Co-authored-by: Quang <quang.ha@QrM3P.local>