// // ContentMainBannerViewV2.swift // SodaLive // // Created by klaus on 2/20/25. // import SwiftUI import Kingfisher struct ContentMainBannerViewV2: View { let bannerList: [GetAudioContentBannerResponse] @State var currentIndex = 0 @State var timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect() @State var width: CGFloat = 0 @State var height: CGFloat = 0 var body: some View { VStack(spacing: 0) { TabView(selection: $currentIndex) { ForEach(0..<bannerList.count, id: \.self) { index in let item = bannerList[index] if let url = item.thumbnailImageUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { ContentMainBannerImageView( url: url, width: width, height: height, item: item ) } else { ContentMainBannerImageView( url: item.thumbnailImageUrl, width: width, height: height, item: item ) } } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) .frame( width: width, height: height ) HStack(spacing: 4) { ForEach(0..<bannerList.count, id: \.self) { index in Capsule() .foregroundColor( index == currentIndex ? .button : .gray90 ) .frame( width: index == currentIndex ? 18 : 6, height: 6 ) .tag(index) } } .padding(.top, 13.3) } .frame(maxWidth: .infinity) .onAppear { width = screenSize().width - 26.7 height = width * 0.53 timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect() } .onDisappear { timer.upstream.connect().cancel() } .onReceive(timer) { _ in DispatchQueue.main.async { withAnimation { if currentIndex == bannerList.count - 1 { currentIndex = 0 } else { currentIndex += 1 } } } } } } #Preview { ContentMainBannerViewV2( bannerList: [ GetAudioContentBannerResponse( type: .CREATOR, thumbnailImageUrl: "https://test-cf.sodalive.net/audition/role/7/audition_role-dc4174e1-10b5-4a97-8379-c7a9336ab230-6691-1735908236571", eventItem: nil, creatorId: 2, seriesId: nil, link: nil ) ] ) } struct ContentMainBannerImageView: View { let url: String let width: CGFloat let height: CGFloat let item: GetAudioContentBannerResponse var body: some View { KFImage(URL(string: url)) .cancelOnDisappear(true) .downsampling(size: CGSize(width: width, height: height)) .resizable() .scaledToFill() .frame(width: width, height: height) .cornerRadius(4.7) .onTapGesture { switch item.type { case .EVENT: AppState.shared.setAppStep(step: .eventDetail(event: item.eventItem!)) case .CREATOR: AppState.shared.setAppStep(step: .creatorDetail(userId: item.creatorId!)) case .SERIES: AppState.shared.setAppStep(step: .seriesDetail(seriesId: item.seriesId!)) case .LINK: if let link = item.link, link.trimmingCharacters(in: .whitespaces).count > 0, let url = URL(string: link), UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url) } } } } }