# GMPlayer Handoff Notes ## Current Project State GMPlayer is a native mobile app workspace for collecting internet video URLs and playing them directly. The project currently has: - iOS app in Swift + UIKit. - Android app in Kotlin + Jetpack Compose. - Shared requirements in `docs/requirements.md`. - Design/exported player button assets in `design-assets/player-buttons`. The root directory is not currently a Git repository in this environment, so use file inspection rather than Git history for handoff context. ## Product Flow Current main flow: 1. User enters an `http` or `https` video URL. 2. URL must end with `.m3u8` or `.mp4`. 3. Valid URLs are added to a local in-memory history list, newest first, max 3 items. 4. Tapping play/add opens a full-screen player view. ## iOS Status Main files: - `ios/GMPlayer/PlayerViewController.swift` - Main URL input and history screen. - Validates `.m3u8` and `.mp4`. - Presents `VideoPlayerViewController(url:)`. - `ios/GMPlayer/VideoPlayerViewController.swift` - Full-screen custom player based on `AVPlayer` and `AVPlayerLayer`. - Uses custom controls, not `AVPlayerViewController`. - Plays automatically on appear. - Supports close, play/pause/replay, seek backward/forward 15 seconds, progress display, and drag-to-seek. - Control overlay behavior: - Tap empty video area to show/hide controls. - When visible, controls auto-hide after 4 seconds without interaction. - Show/hide uses fade animation. - Playback buttons and progress dragging reset the auto-hide timer. - `ios/GMPlayer/MobilePlaybackControlsView.swift` - Center control group. - Supports side controls mode: - `.skip15` - `.playlist` - `.hidden` - `ios/GMPlayer/PlayerControlsConfiguration.swift` - Current side button mode is configured here. - `ios/GMPlayer/MobileProgressBarInfoView.swift` - Bottom title/time/progress area. - Height expected to be 106. - Progress bar supports horizontal scrubbing. - `ios/GMPlayer/MobileMainControllerButton.swift` - `ios/GMPlayer/MobileSkipButton.swift` - Custom button rendering using exported PNG resources. - Circular background uses `UIVisualEffectView` with `.systemUltraThinMaterialDark`. - No additional black overlay on iOS. Temporary native system player testing was removed. There should be no `SystemVideoPlayerViewController.swift`. ### iOS Assets Player button assets live in: - `ios/GMPlayer/Assets.xcassets/player_button_play.imageset` - `ios/GMPlayer/Assets.xcassets/player_button_pause.imageset` - `ios/GMPlayer/Assets.xcassets/player_button_replay.imageset` - `ios/GMPlayer/Assets.xcassets/player_button_go_backwards_15.imageset` - `ios/GMPlayer/Assets.xcassets/player_button_go_forward_15.imageset` - `ios/GMPlayer/Assets.xcassets/player_button_skip_backward.imageset` - `ios/GMPlayer/Assets.xcassets/player_button_skip_forward.imageset` App icon assets are in: - `ios/GMPlayer/Assets.xcassets/AppIcon.appiconset` ### iOS Build And Run Known working simulator: - iPhone 17 - iOS 26.5 - UDID: `68D65FB5-95B9-4E38-8552-2A1934459005` Build: ```sh xcodebuild -project ios/GMPlayer.xcodeproj -scheme GMPlayer -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' build ``` Install and launch: ```sh open -a Simulator xcrun simctl boot 68D65FB5-95B9-4E38-8552-2A1934459005 xcrun simctl install 68D65FB5-95B9-4E38-8552-2A1934459005 /Users/flyzto/Library/Developer/Xcode/DerivedData/GMPlayer-bikaarnrdbqjvfbzwmpbnythjtrj/Build/Products/Debug-iphonesimulator/GMPlayer.app xcrun simctl launch 68D65FB5-95B9-4E38-8552-2A1934459005 com.gmplayer.app ``` Last verified iOS run: - Date: 2026-06-10 - Build succeeded. - Installed and launched on iPhone 17 / iOS 26.5. Known warning: - `PlayerViewController.swift` uses deprecated `UIButton.contentEdgeInsets`; currently harmless for this scaffold. ## Android Status Main files: - `android/app/src/main/java/com/gmplayer/app/MainActivity.kt` - Main URL input and history screen. - Opens `AndroidPlayerScreen` after a valid URL is added. - `AndroidPlayerScreen` uses Android `VideoView` with Compose overlays. - Control overlay behavior is synchronized with iOS intent: - Tap video area to show/hide controls. - Auto-hide after 4 seconds when visible. - Fade in/out animation is 220ms. - Button interactions reset the timer. - Android back exits the player screen. - `android/app/src/main/java/com/gmplayer/app/MobilePlaybackControls.kt` - Center control group. - Supports side controls mode: - `Skip15` - `Playlist` - `Hidden` - Android button backgrounds include a 25% black circular layer so transparent exported icons remain visible. - `android/app/src/main/java/com/gmplayer/app/MobileMainControllerButton.kt` - `android/app/src/main/java/com/gmplayer/app/MobileProgressBarInfo.kt` - `android/app/src/main/java/com/gmplayer/app/PlayerControlsConfiguration.kt` ### Android Assets Button resources were copied from `design-assets/player-buttons` into Android resource folders. Current button names include: - `player_button_play` - `player_button_pause` - `player_button_replay` - `player_button_go_backwards_15` - `player_button_go_forward_15` - `player_button_skip_backward` - `player_button_skip_forward` ### Android Build Notes This environment currently does not have: - `android/gradlew` - global `gradle` So Android has not been compiled locally after the latest player overlay changes. Open `android/` in Android Studio or add/sync a Gradle wrapper before verifying: ```sh cd android ./gradlew :app:assembleDebug ``` ## Player UX Details iOS currently has the most complete custom player implementation: - Custom full-screen player. - Center play/pause/replay and side controls. - Bottom progress info area. - Drag-to-seek. - Auto-hide controls. - Fade transitions. Android has the matching overlay behavior at the Compose level, but playback is currently implemented with `VideoView`. If parity matters for HLS behavior and richer controls, consider moving Android playback to Media3 ExoPlayer. ## Design/Figma Context The player UI was based on the Figma file: - `Video Player For Web Mobile Community` - File key: `ApvSwPRpW7jYhJ0xUohpT4` Relevant Figma nodes previously inspected/used: - Mobile Player node: `21:4432` - Play button states: `40:99` The user exported button PNGs at `@1x`, `@2x`, and `@3x`. Figma default `@1x` export has no suffix; these were mapped into iOS imagesets and Android drawable resources. ## Important Decisions Already Made - The app should use native projects for iOS and Android. - React component generation is not needed. - iOS should use the custom player, not `AVPlayerViewController`, for the product direction. - Main page should not embed a player placeholder. - Clicking play/add should open a full-screen player. - Player should not show subtitle. - iOS control button blur uses `.systemUltraThinMaterialDark`. - Android uses a 25% black circular background behind transparent button icons for now. - Side controls should show only one set: - 15-second seek controls, or - previous/next controls, or - no side controls. ## Known Gaps / Next Steps - Android build needs Gradle wrapper or Android Studio sync. - Android playback should likely be upgraded from `VideoView` to Media3 ExoPlayer for robust `.m3u8` and `.mp4` parity. - Android progress info is currently static in the overlay and should be wired to playback position/duration. - Android drag-to-seek is not yet implemented. - iOS AirPlay, playback speed, mute, and full-screen controls were discussed earlier, but the current restored custom player only has the implemented subset described above. - History is in-memory only on both platforms; persistence has not been added. - No automated tests are currently present. ## Suggested Next Implementation Order 1. Verify Android project in Android Studio or add `gradlew`. 2. Replace Android `VideoView` with Media3 ExoPlayer. 3. Wire Android progress, duration, and drag-to-seek. 4. Add persistent history storage on both platforms. 5. Add player speed, mute, full-screen/orientation behavior, and AirPlay where required. 6. Add focused unit/UI tests for URL validation and player state transitions.