Skip to content

Instantly share code, notes, and snippets.

@VonC
Created October 7, 2023 19:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VonC/0115dc1ea6db4f4d1e8acdc061a2c35c to your computer and use it in GitHub Desktop.
Save VonC/0115dc1ea6db4f4d1e8acdc061a2c35c to your computer and use it in GitHub Desktop.
77248619 Swift + Swift UI - Fix bugs in TikTok clone on IOS app 'Hustles'

Based on the code snippets provided, it appears that your iOS application uses SwiftUI to create a TikTok-like user interface for playing YouTube videos. The videos are embedded within a WKWebView and the relevant UI components are built using SwiftUI.

Issue:

Screen flashes white then black as the video loads, and the desired outcome is to have the video cover show with a loading icon until the video is ready to play.

Proposed Solution

  1. Video Cover and Loading Indicator:
    • To display a loading indicator and a video cover, you can introduce a new SwiftUI View that overlays on top of your SingleVideoView. This overlay view can contain a loading indicator and an image view for displaying the video cover.
    • Utilize the ZStack to stack the overlay view on top of the SmartReelView.
    • Hide the overlay view once the video is ready to play. This can be done by checking the isPlaying state or by introducing a new state to specifically handle the loading status.
struct LoadingOverlayView: View {
    var body: some View {
        VStack {
            ActivityIndicator(isAnimating: .constant(true), style: .large)
            ImageView()  // Assume this view displays your video cover
        }
    }
}
var body: some View {
    ZStack {
        Color.black //so background always black
        
        SmartReelView(link: link, isPlaying: $isVideoPlaying, isChangingTime: $isChangingTime, totalLength: $totalLength, currentTime: $currentTime, viewIsShowing: $viewIsShowing)
        
        if !isVideoPlaying {
            LoadingOverlayView()
        }
        
        Button("", action: {}).disabled(true)  //disable any interaction with youtube video
        
        Color.gray.opacity(0.001)
            .onTapGesture {
                isVideoPlaying.toggle()  //play pause video
            }
    }
    // ... rest of your code
}
  1. JavaScript Interactions:
    • In your JavaScript code within SmartReelView, you may consider introducing a mechanism to notify your Swift code when the video is ready to play. This can be done using the YouTube Iframe Player API's onReady event.
    • Make use of the WKScriptMessageHandler protocol to receive messages from your JavaScript code and update your SwiftUI view accordingly.
function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        width: '100%',
        videoId: '\(link)',
        playerVars: { 'playsinline': 1, 'controls': 0},
        events: {
            'onReady': function(event) {
                // Notify your Swift code that the video is ready
                window.webkit.messageHandlers.observe.postMessage("ready");
            },
            'onStateChange': function(event) {
                if (event.data === YT.PlayerState.ENDED) {      //restart video on end
                    player.seekTo(0);
                    player.playVideo();
                }
            }
        }
    });
}
class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler  {
    var parent: SmartReelView

    init(_ parent: SmartReelView) {
        self.parent = parent
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "observe" && message.body as! String == "ready" {
            // Update your SwiftUI view to hide the loading overlay
            DispatchQueue.main.async {
                self.parent.isPlaying = true
            }
        }
    }
    
    // ... rest of your code
}

That would create a new overlay view to handle the loading indicator and video cover, along with tweaking the JavaScript and Swift interaction to hide the overlay once the video is ready to play. It is essential to ensure that the video cover image is available and properly displayed within the ImageView.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment