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.
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.
- 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 yourSingleVideoView
. 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 theSmartReelView
. - 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.
- To display a loading indicator and a video cover, you can introduce a new SwiftUI
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
}
- 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'sonReady
event. - Make use of the
WKScriptMessageHandler
protocol to receive messages from your JavaScript code and update your SwiftUI view accordingly.
- In your JavaScript code within
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
.