Files
Woka_Native_iOS/WOKA/Theme/ViewModel/ThemeOneVM.swift
BilalKhanWDI 33141797b8 - Added haptics for theme and language change.
- Added haptics for app load
- Added JWplayer Pods.
- Added Av player for home live stream
- Made the Explore Woka Screen.
- Made button Effect for the selection
2024-05-30 19:49:41 +05:30

340 lines
13 KiB
Swift

//
// ThemeOneVM.swift
// WOKA
//
// Created by MacBook Pro on 23/05/24.
//
import UIKit
import AVFoundation
import JWPlayerKit
class ThemeOneVM{
weak var vc : ThemeOneVC!
var cloudMovingRight = false // Flag to track the direction of movement
var isMovingRight = false // Flag to track the direction of movement
var liveStreamURL = "https://d3volyx7jx7oal.cloudfront.net/master.m3u8"
var avPlayer : AVPlayer!
var playerLayer: AVPlayerLayer!
func initView(){
AuthFunc.shareInstance.initTimePeriods()
startInitialTimer()
moveLiveTVView()
moveCloudView()
addTapGestureToMovingView()
handleTaps()
NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.reloadTheme), name: NSNotification.Name(rawValue: K.NotificationCenterReloads.reloadTheme), object: nil)
setData()
setupAvPlayer()
avPlayer.play()
avPlayer.isMuted = true
// do{
// let item = try JWPlayerItemBuilder()
// .file(URL(string:self.liveStreamURL)!)
// .title("Testing Title")
// .posterImage(URL(string: "https://img.freepik.com/free-photo/painting-mountain-lake-with-mountain-background_188544-9126.jpg")!)
// // .mediaTracks([thumbnailTrack])
// .build()
//
// // Create a config, and give it the item as a playlist.
// let config = try JWPlayerConfigurationBuilder()
// .playlist(items: [item])
// .autostart(true)
// .preload(.auto)
//// .repeatContent(true)
// .build()
// // Initialize the JWPlayer controller
// player.player.configurePlayer(with: config)
// player.interfaceBehavior = .hidden
// // Add the player's view to the container view
// player.view.translatesAutoresizingMaskIntoConstraints = false
// vc.liveTvPlayer.addSubview(player.view)
//
// // Add constraints to make the player fill the container view
// NSLayoutConstraint.activate([
// player.view.leadingAnchor.constraint(equalTo: vc.liveTvPlayer.leadingAnchor),
// player.view.trailingAnchor.constraint(equalTo: vc.liveTvPlayer.trailingAnchor),
// player.view.topAnchor.constraint(equalTo: vc.liveTvPlayer.topAnchor),
// player.view.bottomAnchor.constraint(equalTo: vc.liveTvPlayer.bottomAnchor)
// ])
//
// player.player.play()
// }catch{
//
// }
}
private func setupAvPlayer(){
/*
Av Player Setup
*/
let streamURL = URL(string: liveStreamURL)
// Create AVPlayer with the stream URL
avPlayer = AVPlayer(url: streamURL!)
// avPlayer.isMuted = true
// Create AVPlayerLayer
playerLayer = AVPlayerLayer(player: avPlayer)
playerLayer.videoGravity = .resizeAspectFill // You can set different videoGravity as per your need
playerLayer.frame = self.vc.liveTvPlayer.bounds
self.vc.liveTvPlayer.layer.addSublayer(playerLayer)
}
func setData(){
guard let data = AuthFunc.shareInstance.userData else{return}
//set the first name as the name
/*
Check User Type,
Dont show username if the user type is guest
*/
switch data.userType{
case "1": // child
vc.nameLabel.text = data.fullname?.components(separatedBy: " ").first
vc.notificationBtnn.isHidden = false
case "2" : // adult
vc.nameLabel.text = data.fullname?.components(separatedBy: " ").first
vc.notificationBtnn.isHidden = false
case "3": // Guest
vc.nameLabel.text = ""
vc.notificationBtnn.isHidden = true
break
default:
break
}
if let avatar = data.avtar{
//https://wokaland.com/admin/storage/app/public/uploads/avtar/avatar2.png?d=1716889852
vc.avatarImage.imageURL("https://wokaland.com/admin/storage/app/public/uploads/avtar/avatar2.png?d=1716889852")
}
}
// MARK: - Notification Center Handlers
@objc func reloadTheme(){
self.vc.delegate?.didPressSwitchButton(from: self.vc)
}
@objc func appDidEnterBackground() {
// Code to execute when the app enters the background
print("App entered background")
self.handleBackground()
}
@objc func appWillEnterForeground() {
// Code to execute when the app enters the foreground
print("App will enter foreground")
self.handleBackground()
}
// MARK: - Handle Tap Gesture
func handleTaps(){
//WebSeries
vc.webSeriesView.addTapGesture { [weak self] in
guard let self else {return}
ViewButtonAnimation.sharedInstance.btnTapped(in: self.vc, view: vc.webSeriesView) {
// self.vc.delegate?.didPressSwitchButton(from: self.vc)
}
}
//LiveTV
}
// MARK: - Animate Clouds and LiveTV
func moveLiveTVView() {
UIView.animate(withDuration: 6, delay: 0, options: [.allowUserInteraction], animations: { [weak self] in
guard let self else{return}
let margin: CGFloat = 30
let screenWidth = self.vc.view.frame.width
let viewWidth = self.vc.liveTVView.frame.width
let maxX = screenWidth - margin - viewWidth / 2
let minX = margin + viewWidth / 2
if isMovingRight {
vc.liveTVView.center.x = maxX // Move to the right
} else {
vc.liveTVView.center.x = minX // Move to the left
}
}, completion: { [weak self] _ in
guard let self else{return}
isMovingRight.toggle() // Toggle the direction for the next iteration
moveLiveTVView() // Recursively call moveLiveTVView to create a continuous animation
})
}
func moveCloudView() {
UIView.animate(withDuration: 23, delay: 0, options: [], animations: { [weak self] in
guard let self else{return}
if cloudMovingRight {
print("right")
vc.cloud2.center.x += 140 // Move to the right
vc.cloud1.center.x -= 140 // Move to the right
} else {
print("left")
vc.cloud2.center.x -= 140 // Move to the left
vc.cloud1.center.x += 140 // Move to the left
}
}, completion: { [weak self] _ in
guard let self else{return}
cloudMovingRight.toggle() // Toggle the direction for the next iteration
moveCloudView() // Recursively call moveView to create a continuous animation
})
}
// MARK: - LiveTV Tap Handling
private func addTapGestureToMovingView(){
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
vc.liveTVView.addGestureRecognizer(tap)
vc.liveTVView.isUserInteractionEnabled = true
}
// function which is triggered when handleTap is called
@objc func handleTap(_ sender: UITapGestureRecognizer) {
print("tapped")
let vc = self.vc.storyboard?.instantiateViewController(identifier: "PlayerVC") as! PlayerVC
DispatchQueue.main.async {
do {
// Create a JWMediaTrack with the thumbnails .vtt file
// let thumbnailTrack = try JWThumbnailTrackBuilder()
// .file(URL(string:"https://content.jwplatform.com/videos/Agy4RIje-Ysj2G4DQ.mp4")!)
// .build()
// Create a JWPlayerItem
let item = try JWPlayerItemBuilder()
.file(URL(string: self.liveStreamURL)!)
.title("Testing Title")
.posterImage(URL(string: "https://img.freepik.com/free-photo/painting-mountain-lake-with-mountain-background_188544-9126.jpg")!)
// .mediaTracks([thumbnailTrack])
.build()
// Create a config, and give it the item as a playlist.
let config = try JWPlayerConfigurationBuilder()
.playlist(items: [item])
.autostart(true)
.preload(.auto)
.repeatContent(true)
.build()
vc.config = config
}
catch {
// Handle Error
}
vc.dismissTapped = self.tapped
vc.modalPresentationStyle = .overFullScreen
self.vc.present(vc, animated: false) {
self.stopLiveStream()
vc.transitionToFullScreen(animated: true) {
print("FullScreen")
}
// vc.setDeviceOrientation(orientation: .landscapeRight)
}
// self.navigationController?.pushViewController(vc, animated: true)
}
}
func tapped(){
Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false) { _ in
self.startLiveStream()
}
print("Sadasd")
}
func startLiveStream(){
avPlayer.play()
}
func stopLiveStream(){
avPlayer.pause()
}
// MARK: - Handle Time Change
@objc func handleBackground(){
let currentTime = Date()
for period in AuthFunc.shareInstance.timePeriods {
if period.contains(currentTime: currentTime) {
let details = period.details
// Update view's background color with a gradient or single color
DispatchQueue.main.async { [weak self] in
guard let self else{return}
if period.details.dayCycle == .night{
startStarGlowAnimation()
}else{
//just hide the moon and star if its not night
!vc.moonImage.isHidden ? vc.moonImage.isHidden = true : nil
vc.star.forEach { image in
!image.isHidden ? image.isHidden = true : nil
}
}
vc.gradientView.applyGradient(colors: [details.color1, details.color2], startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: 0.8))
vc.nameLabel.textColor = details.textColor
vc.HelloLabel.textColor = details.textColor
vc.welcomeLabel.textColor = details.textColor
vc.homeGrass.image = UIImage(named: details.grass)
}
break
}
}
}
func startStarGlowAnimation() {
vc.moonImage.isHidden ? vc.moonImage.isHidden = false : nil
for (index, imageView) in vc.star.enumerated() {
//If star is hidden just unhide it for the night time
(vc.star[index].isHidden) ? (vc.star[index].isHidden = false) : nil
let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = 1.0
animation.toValue = 0.07
animation.duration = 3.0
animation.autoreverses = true
animation.repeatCount = .infinity
// Calculate delay for each animation based on index
let delay = Double(index) * 1 // Adjust the delay as needed
// Apply the delay to the animation
animation.beginTime = CACurrentMediaTime() + delay
imageView.layer.add(animation, forKey: "glowAnimation")
}
}
func startInitialTimer() {
self.handleBackground()
let now = Date()
let nextMinute = Calendar.current.nextDate(after: now, matching: DateComponents(second: 0), matchingPolicy: .nextTime)!
let timeInterval = nextMinute.timeIntervalSince(now)
// Schedule the initial timer to fire at the start of the next minute
vc.timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(startRepeatingTimer), userInfo: nil, repeats: false)
}
@objc func startRepeatingTimer() {
// Handle the minute change when the initial timer fires
self.handleBackground()
// Schedule the repeating timer to fire every minute
vc.timer = Timer.scheduledTimer(timeInterval: 60, target: self, selector: #selector(handleBackground), userInfo: nil, repeats: true)
}
}