Created
November 25, 2023 18:38
-
-
Save mazz/f256ae5cdf373b7f5e73d5ccc914b2a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import LNPopupUI | |
import LNPopupController | |
import Combine | |
import KSPlayer | |
struct BlurView: UIViewRepresentable { | |
var style: UIBlurEffect.Style = .systemMaterial | |
func makeUIView(context: Context) -> UIVisualEffectView { | |
return UIVisualEffectView(effect: UIBlurEffect(style: style)) | |
} | |
func updateUIView(_ uiView: UIVisualEffectView, context: Context) { | |
uiView.effect = UIBlurEffect(style: style) | |
} | |
} | |
struct PopupPlayerView: View { | |
@EnvironmentObject private var appModel: AppModel | |
let imageDownloader = ImageDownloader() | |
@State private var thumbImage: UIImage? | |
let song: LivestreamModel | |
@State var playbackProgress: Float = Float.random(in: 0..<1) | |
@State var volume: Float = Float.random(in: 0..<1) | |
@State var isPlaying: Bool = true | |
init(song: LivestreamModel) { | |
self.song = song | |
} | |
var body: some View { | |
GeometryReader { geometry in | |
let safeArea = geometry.safeAreaInsets | |
VStack { | |
KSVideoPlayerView(model: song) | |
VStack(spacing: geometry.size.height * 30.0 / 896.0) { | |
ScrollView(.vertical, showsIndicators: false) { | |
VStack(spacing: 10) { | |
ForEach(1...5, id: \.self) { index in | |
GeometryReader { | |
let size = $0.size | |
RoundedRectangle(cornerRadius: 15, style: .continuous) | |
.fill(.red.gradient) | |
.frame(width: size.width, height: size.height) | |
} | |
.frame(height: 220) | |
} | |
} | |
} | |
} | |
.padding(geometry.size.height * 40.0 / 896.0) | |
} | |
.frame(minWidth: 0, | |
maxWidth: .infinity, | |
minHeight: 0, | |
maxHeight: .infinity, | |
alignment: .top) | |
.background({ | |
ZStack { | |
Image(systemName: "music.mic.circle.fill") | |
.resizable() | |
BlurView() | |
} | |
.edgesIgnoringSafeArea(.all) | |
}()) | |
} | |
.popupTitle(song.title, subtitle: song.sourceMaterial) | |
.popupImage( | |
Image(uiImage: thumbImage ?? UIImage(named: "faithful-word-logo-gray-720.png")!) | |
.resizable() | |
) | |
.popupProgress(playbackProgress) | |
.popupBarItems({ | |
HStack(spacing: 20) { | |
Button(action: { | |
isPlaying.toggle() | |
}) { | |
Image(systemName: isPlaying ? "pause.fill" : "play.fill") | |
.foregroundColor(Color("Theme")) | |
} | |
Button(action: { | |
appModel.tappedPopupPlayerClose() | |
print("Close") | |
}) { | |
Image(systemName: "xmark") | |
.foregroundColor(Color("Theme")) | |
} | |
} | |
}) | |
.onAppear { | |
Task { | |
do { | |
thumbImage = try await imageDownloader.downloadImage(from: URL(string: song.posterUrl)!) | |
// Display the image | |
// thumbImage = image | |
} catch { | |
print("Error: \(error.localizedDescription)") | |
} | |
} | |
} | |
} | |
} | |
class ImageCache { | |
private var cache: [URL: UIImage] = [:] | |
func cacheImage(_ image: UIImage, for url: URL) { | |
cache[url] = image | |
} | |
func image(for url: URL) -> UIImage? { | |
return cache[url] | |
} | |
} | |
class ImageDownloader { | |
private let imageCache = ImageCache() | |
func downloadImage(from url: URL) async throws -> UIImage { | |
if let cachedImage = imageCache.image(for: url) { | |
return cachedImage | |
} | |
let data = try await downloadImageData(from: url) | |
if let image = UIImage(data: data) { | |
// throw NSError(domain: "InvalidImageData", code: 0, userInfo: nil) | |
imageCache.cacheImage(image, for: url) | |
return image | |
} else { | |
if let image = UIImage(named: "faithful-word-logo-gray-720.png") { | |
imageCache.cacheImage(image, for: url) | |
return image | |
} else { | |
throw NSError(domain: "InvalidImageData", code: 0, userInfo: nil) | |
} | |
} | |
} | |
func downloadImageData(from url: URL) async throws -> Data { | |
let request = URLRequest(url: url) | |
let (data, _) = try await URLSession.shared.data(for: request) | |
return data | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
it is called from ContentView.