diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index 79cf19a..0ec7fb2 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -3,3 +3,4 @@ {"id":"int-d8dc4ec5","kind":"field_change","created_at":"2026-05-25T01:25:35.590554Z","actor":"dirtydishes","issue_id":"dreamio-tnv","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Added bundle metadata to Info.plist and validated processed app bundle identifier."}} {"id":"int-a86e17e0","kind":"field_change","created_at":"2026-05-25T02:34:54.605755Z","actor":"dirtydishes","issue_id":"dreamio-evt","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented debug-only WKWebView inspection, token-safe playback diagnostics, navigation logging, validation build, and turn documentation."}} {"id":"int-4d73c126","kind":"field_change","created_at":"2026-05-25T03:20:17.439589Z","actor":"dirtydishes","issue_id":"dreamio-l68","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented native direct-stream bridge, classification, MobileVLCKit backend wiring, CocoaPods workflow docs, and turn documentation. Full iOS build is blocked locally by missing CocoaPods and iPhoneOS SDK."}} +{"id":"int-3dbe205a","kind":"field_change","created_at":"2026-05-25T03:23:00.515861Z","actor":"dirtydishes","issue_id":"dreamio-2lp","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Fixed Swift raw string escaping and guarded MobileVLCKit import for builds before pod install."}} diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index fdf5733..1c6ced4 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,3 +1,4 @@ +{"_type":"issue","id":"dreamio-2lp","title":"Fix native playback build blockers","description":"Correct Swift string escaping for the injected stream bridge and allow the VLC backend source to compile before MobileVLCKit is installed by guarding the import with canImport.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T03:22:52Z","created_by":"dirtydishes","updated_at":"2026-05-25T03:23:00Z","started_at":"2026-05-25T03:23:00Z","closed_at":"2026-05-25T03:23:00Z","close_reason":"Fixed Swift raw string escaping and guarded MobileVLCKit import for builds before pod install.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"dreamio-l68","title":"Add native playback for direct debrid streams","description":"Implement a WKWebView JavaScript bridge that detects direct-file debrid media URLs and routes unsupported containers to a native player backend, initially MobileVLCKit, while preserving normal Stremio Web playback for compatible streams.","status":"closed","priority":1,"issue_type":"feature","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T03:13:19Z","created_by":"dirtydishes","updated_at":"2026-05-25T03:20:17Z","started_at":"2026-05-25T03:13:28Z","closed_at":"2026-05-25T03:20:17Z","close_reason":"Implemented native direct-stream bridge, classification, MobileVLCKit backend wiring, CocoaPods workflow docs, and turn documentation. Full iOS build is blocked locally by missing CocoaPods and iPhoneOS SDK.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"dreamio-tnv","title":"Fix iOS bundle identifier install failure","description":"Xcode built Dreamio.app without a valid CFBundleIdentifier, causing device install to fail with CoreDeviceError 3000/3002. Investigate project bundle settings, fix the source configuration, validate the app bundle Info.plist, and document the change.","status":"closed","priority":1,"issue_type":"bug","assignee":"dirtydishes","owner":"dishes@dpdrm.com","created_at":"2026-05-25T01:23:00Z","created_by":"dirtydishes","updated_at":"2026-05-25T01:25:36Z","started_at":"2026-05-25T01:23:07Z","closed_at":"2026-05-25T01:25:36Z","close_reason":"Added bundle metadata to Info.plist and validated processed app bundle identifier.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"dreamio-4yn","title":"Build WKWebView MVP shell","description":"Create the first Dreamio MVP implementation: a minimal iOS WKWebView wrapper around hosted Stremio Web, with configuration, launch behavior, diagnostics, and documentation for real-device viability testing.","acceptance_criteria":"App project exists; WKWebView loads hosted Stremio Web; external/new-window navigation is handled; basic diagnostics and manual test documentation exist; quality gates are run or documented.","status":"closed","priority":1,"issue_type":"feature","owner":"dishes@dpdrm.com","created_at":"2026-05-24T14:55:12Z","created_by":"dirtydishes","updated_at":"2026-05-24T14:59:44Z","closed_at":"2026-05-24T14:59:44Z","close_reason":"Implemented the MVP WKWebView iOS shell, added run and validation documentation, and recorded current validation limits.","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/Dreamio/DreamioWebViewController.swift b/Dreamio/DreamioWebViewController.swift index b07e657..e7c8823 100644 --- a/Dreamio/DreamioWebViewController.swift +++ b/Dreamio/DreamioWebViewController.swift @@ -54,7 +54,7 @@ final class DreamioWebViewController: UIViewController { private var lastNativePlaybackURL: URL? private static let streamCandidateScript = WKUserScript( - source: """ + source: #""" (() => { if (window.__dreamioStreamBridgeInstalled) { return; @@ -181,7 +181,7 @@ final class DreamioWebViewController: UIViewController { inspectMedia(document); })(); - """, + """#, injectionTime: .atDocumentStart, forMainFrameOnly: false ) diff --git a/Dreamio/VLCNativePlaybackBackend.swift b/Dreamio/VLCNativePlaybackBackend.swift index 44ca5bc..2ed0132 100644 --- a/Dreamio/VLCNativePlaybackBackend.swift +++ b/Dreamio/VLCNativePlaybackBackend.swift @@ -1,24 +1,34 @@ import UIKit + +#if canImport(MobileVLCKit) import MobileVLCKit +#endif final class VLCNativePlaybackBackend: NSObject, NativePlaybackBackend { let view = UIView() var onReady: (() -> Void)? var onFailure: ((Error) -> Void)? +#if canImport(MobileVLCKit) private let mediaPlayer = VLCMediaPlayer() +#endif override init() { super.init() +#if canImport(MobileVLCKit) mediaPlayer.delegate = self +#endif view.backgroundColor = .black } func prepare(in viewController: UIViewController) { +#if canImport(MobileVLCKit) mediaPlayer.drawable = view +#endif } func play(request: NativePlaybackRequest) { +#if canImport(MobileVLCKit) let media = VLCMedia(url: request.playbackURL) var headers = ["Referer": request.referer] if let userAgent = request.userAgent { @@ -36,14 +46,20 @@ final class VLCNativePlaybackBackend: NSObject, NativePlaybackBackend { mediaPlayer.media = media mediaPlayer.play() +#else + onFailure?(NativePlaybackError.backendUnavailable) +#endif } func stop() { +#if canImport(MobileVLCKit) mediaPlayer.stop() mediaPlayer.media = nil +#endif } } +#if canImport(MobileVLCKit) extension VLCNativePlaybackBackend: VLCMediaPlayerDelegate { func mediaPlayerStateChanged(_ aNotification: Notification) { switch mediaPlayer.state { @@ -56,3 +72,4 @@ extension VLCNativePlaybackBackend: VLCMediaPlayerDelegate { } } } +#endif diff --git a/docs/turns/2026-05-24-native-debrid-playback.html b/docs/turns/2026-05-24-native-debrid-playback.html index 02cf2e5..45865d8 100644 --- a/docs/turns/2026-05-24-native-debrid-playback.html +++ b/docs/turns/2026-05-24-native-debrid-playback.html @@ -275,6 +275,33 @@ diff --git a/Podfile b/Podfile
  • Consider adding a tiny XCTest target for classifier behavior once the project has a test bundle.
  • + +
    +

    New Changes as of 2026-05-24 23:22 EDT

    +

    Summary of changes: Fixed the Swift build errors reported after the first handoff by converting the injected stream bridge into a raw multiline Swift string and guarding the MobileVLCKit import with canImport(MobileVLCKit).

    +

    Why this change was made: Swift was interpreting JavaScript regex backslashes as Swift string escapes, and the app could not compile from Dreamio.xcodeproj before CocoaPods had installed and linked MobileVLCKit. The fallback keeps the project buildable enough to show a native-player unavailable error until the workspace is set up with pods.

    +

    Code diffs: Plain diff fallback is used for the same reason noted above: @pierre/diffs is present as a library but has no runnable CLI exposed in this repo.

    +
    diff --git a/Dreamio/DreamioWebViewController.swift b/Dreamio/DreamioWebViewController.swift
    +-        source: """
    ++        source: #"""
    + ...
    +-        """,
    ++        """#,
    +
    +diff --git a/Dreamio/VLCNativePlaybackBackend.swift b/Dreamio/VLCNativePlaybackBackend.swift
    ++#if canImport(MobileVLCKit)
    + import MobileVLCKit
    ++#endif
    + ...
    ++#if canImport(MobileVLCKit)
    +     private let mediaPlayer = VLCMediaPlayer()
    ++#endif
    + ...
    ++#else
    ++        onFailure?(NativePlaybackError.backendUnavailable)
    ++#endif
    +

    Related issues or PRs: Follow-up to Beads issue dreamio-l68.

    +