cache: move event-specific media metadata to EventCache

This commit is contained in:
William Casarin
2023-05-30 17:53:44 -07:00
parent 88b04fde09
commit bb091d072f
6 changed files with 57 additions and 33 deletions

View File

@@ -74,7 +74,8 @@ struct ImageCarousel: View {
init(state: DamusState, evid: String, urls: [MediaUrl]) { init(state: DamusState, evid: String, urls: [MediaUrl]) {
_open_sheet = State(initialValue: false) _open_sheet = State(initialValue: false)
_current_url = State(initialValue: nil) _current_url = State(initialValue: nil)
_image_fill = State(initialValue: state.previews.lookup_image_meta(evid)) let media_model = state.events.get_cache_data(evid).media_metadata_model
_image_fill = State(initialValue: media_model.fill)
self.urls = urls self.urls = urls
self.evid = evid self.evid = evid
self.state = state self.state = state
@@ -103,16 +104,17 @@ struct ImageCarousel: View {
} }
} }
.onAppear { .onAppear {
if self.image_fill == nil, if self.image_fill == nil, let size = state.events.lookup_media_size(url: url) {
let meta = state.events.lookup_img_metadata(url: url),
let size = meta.meta.dim?.size
{
let fill = ImageFill.calculate_image_fill(geo_size: geo_size, img_size: size, maxHeight: maxHeight, fillHeight: fillHeight) let fill = ImageFill.calculate_image_fill(geo_size: geo_size, img_size: size, maxHeight: maxHeight, fillHeight: fillHeight)
self.image_fill = fill self.image_fill = fill
} }
} }
} }
func video_model(_ url: URL) -> VideoPlayerModel {
return state.events.get_video_player_model(url: url)
}
func Media(geo: GeometryProxy, url: MediaUrl, index: Int) -> some View { func Media(geo: GeometryProxy, url: MediaUrl, index: Int) -> some View {
Group { Group {
switch url { switch url {
@@ -122,18 +124,20 @@ struct ImageCarousel: View {
open_sheet = true open_sheet = true
} }
case .video(let url): case .video(let url):
DamusVideoPlayer(url: url, video_size: $video_size) DamusVideoPlayer(url: url, model: video_model(url), video_size: $video_size)
.onChange(of: video_size) { size in .onChange(of: video_size) { size in
guard image_fill == nil, let size else { guard let size else { return }
return
}
let fill = ImageFill.calculate_image_fill(geo_size: geo.size, img_size: size, maxHeight: maxHeight, fillHeight: fillHeight)
image_fill = fill
state.previews.cache_image_meta(evid: evid, image_fill: fill)
if index == 0 { let fill = ImageFill.calculate_image_fill(geo_size: geo.size, img_size: size, maxHeight: maxHeight, fillHeight: fillHeight)
print("video_size changed \(size)")
if self.image_fill == nil {
print("video_size firstImageHeight \(fill.height)")
firstImageHeight = fill.height firstImageHeight = fill.height
state.events.get_cache_data(evid).media_metadata_model.fill = fill
} }
self.image_fill = fill
} }
} }
} }
@@ -150,7 +154,7 @@ struct ImageCarousel: View {
view.framePreloadCount = 3 view.framePreloadCount = 3
} }
.imageFill(for: geo.size, max: maxHeight, fill: fillHeight) { fill in .imageFill(for: geo.size, max: maxHeight, fill: fillHeight) { fill in
state.previews.cache_image_meta(evid: evid, image_fill: fill) state.events.get_cache_data(evid).media_metadata_model.fill = fill
// blur hash can be discarded when we have the url // blur hash can be discarded when we have the url
// NOTE: this is the wrong place for this... we need to remove // NOTE: this is the wrong place for this... we need to remove
// it when the image is loaded in memory. This may happen // it when the image is loaded in memory. This may happen
@@ -188,7 +192,7 @@ struct ImageCarousel: View {
} }
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.fullScreenCover(isPresented: $open_sheet) { .fullScreenCover(isPresented: $open_sheet) {
ImageView(urls: urls, disable_animation: state.settings.disable_animation) ImageView(cache: state.events, urls: urls, disable_animation: state.settings.disable_animation)
} }
.frame(height: height) .frame(height: height)
.onChange(of: selectedIndex) { value in .onChange(of: selectedIndex) { value in

View File

@@ -101,6 +101,10 @@ class RelativeTimeModel: ObservableObject {
@Published var value: String = "" @Published var value: String = ""
} }
class MediaMetaModel: ObservableObject {
@Published var fill: ImageFill? = nil
}
class EventData { class EventData {
var translations_model: TranslationModel var translations_model: TranslationModel
var artifacts_model: NoteArtifactsModel var artifacts_model: NoteArtifactsModel
@@ -108,6 +112,7 @@ class EventData {
var zaps_model : ZapsDataModel var zaps_model : ZapsDataModel
var relative_time: RelativeTimeModel = RelativeTimeModel() var relative_time: RelativeTimeModel = RelativeTimeModel()
var validated: ValidationResult var validated: ValidationResult
var media_metadata_model: MediaMetaModel
var translations: TranslateStatus { var translations: TranslateStatus {
return translations_model.state return translations_model.state
@@ -126,6 +131,7 @@ class EventData {
self.artifacts_model = .init(state: .not_loaded) self.artifacts_model = .init(state: .not_loaded)
self.zaps_model = .init(zaps) self.zaps_model = .init(zaps)
self.validated = .unknown self.validated = .unknown
self.media_metadata_model = MediaMetaModel()
self.preview_model = .init(state: .not_loaded) self.preview_model = .init(state: .not_loaded)
} }
} }
@@ -135,6 +141,7 @@ class EventCache {
private var replies = ReplyMap() private var replies = ReplyMap()
private var cancellable: AnyCancellable? private var cancellable: AnyCancellable?
private var image_metadata: [String: ImageMetadataState] = [:] private var image_metadata: [String: ImageMetadataState] = [:]
private var video_meta: [String: VideoPlayerModel] = [:]
private var event_data: [String: EventData] = [:] private var event_data: [String: EventData] = [:]
//private var thread_latest: [String: Int64] //private var thread_latest: [String: Int64]
@@ -194,6 +201,28 @@ class EventCache {
return image_metadata[url.absoluteString.lowercased()] return image_metadata[url.absoluteString.lowercased()]
} }
func lookup_media_size(url: URL) -> CGSize? {
if let img_meta = lookup_img_metadata(url: url) {
return img_meta.meta.dim?.size
}
return get_video_player_model(url: url).size
}
func store_video_player_model(url: URL, meta: VideoPlayerModel) {
video_meta[url.absoluteString] = meta
}
func get_video_player_model(url: URL) -> VideoPlayerModel {
if let model = video_meta[url.absoluteString] {
return model
}
let model = VideoPlayerModel()
video_meta[url.absoluteString] = model
return model
}
func parent_events(event: NostrEvent) -> [NostrEvent] { func parent_events(event: NostrEvent) -> [NostrEvent] {
var parents: [NostrEvent] = [] var parents: [NostrEvent] = []
@@ -257,6 +286,7 @@ class EventCache {
private func prune() { private func prune() {
events = [:] events = [:]
video_meta = [:]
event_data = [:] event_data = [:]
replies.replies = [:] replies.replies = [:]
} }

View File

@@ -66,22 +66,12 @@ enum PreviewState {
class PreviewCache { class PreviewCache {
private var previews: [String: Preview] private var previews: [String: Preview]
private var image_meta: [String: ImageFill]
func lookup(_ evid: String) -> Preview? { func lookup(_ evid: String) -> Preview? {
return previews[evid] return previews[evid]
} }
func lookup_image_meta(_ evid: String) -> ImageFill? {
return image_meta[evid]
}
func cache_image_meta(evid: String, image_fill: ImageFill) {
self.image_meta[evid] = image_fill
}
init() { init() {
self.previews = [:] self.previews = [:]
self.image_meta = [:]
} }
} }

View File

@@ -10,11 +10,11 @@ import Kingfisher
struct ImageContainerView: View { struct ImageContainerView: View {
let cache: EventCache
let url: MediaUrl let url: MediaUrl
@State private var image: UIImage? @State private var image: UIImage?
@State private var showShareSheet = false @State private var showShareSheet = false
@State private var video_size: CGSize? = nil
let disable_animation: Bool let disable_animation: Bool
@@ -47,7 +47,7 @@ struct ImageContainerView: View {
case .image(let url): case .image(let url):
Img(url: url) Img(url: url)
case .video(let url): case .video(let url):
DamusVideoPlayer(url: url, video_size: $video_size) DamusVideoPlayer(url: url, model: cache.get_video_player_model(url: url), video_size: .constant(nil))
} }
} }
} }
@@ -57,6 +57,6 @@ let test_image_url = URL(string: "https://jb55.com/red-me.jpg")!
struct ImageContainerView_Previews: PreviewProvider { struct ImageContainerView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
ImageContainerView(url: .image(test_image_url), disable_animation: false) ImageContainerView(cache: test_damus_state().events, url: .image(test_image_url), disable_animation: false)
} }
} }

View File

@@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
struct ImageView: View { struct ImageView: View {
let cache: EventCache
let urls: [MediaUrl] let urls: [MediaUrl]
@Environment(\.presentationMode) var presentationMode @Environment(\.presentationMode) var presentationMode
@@ -38,7 +39,7 @@ struct ImageView: View {
TabView(selection: $selectedIndex) { TabView(selection: $selectedIndex) {
ForEach(urls.indices, id: \.self) { index in ForEach(urls.indices, id: \.self) { index in
ZoomableScrollView { ZoomableScrollView {
ImageContainerView(url: urls[index], disable_animation: disable_animation) ImageContainerView(cache: cache, url: urls[index], disable_animation: disable_animation)
.aspectRatio(contentMode: .fit) .aspectRatio(contentMode: .fit)
.padding(.top, Theme.safeAreaInsets?.top) .padding(.top, Theme.safeAreaInsets?.top)
.padding(.bottom, Theme.safeAreaInsets?.bottom) .padding(.bottom, Theme.safeAreaInsets?.bottom)
@@ -79,6 +80,6 @@ struct ImageView: View {
struct ImageView_Previews: PreviewProvider { struct ImageView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!) let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!)
ImageView(urls: [url], disable_animation: false) ImageView(cache: test_damus_state().events, urls: [url], disable_animation: false)
} }
} }

View File

@@ -9,7 +9,7 @@ import SwiftUI
struct DamusVideoPlayer: View { struct DamusVideoPlayer: View {
var url: URL var url: URL
@StateObject var model: VideoPlayerModel = VideoPlayerModel() @ObservedObject var model: VideoPlayerModel
@Binding var video_size: CGSize? @Binding var video_size: CGSize?
var mute_icon: String { var mute_icon: String {
@@ -58,9 +58,8 @@ struct DamusVideoPlayer: View {
} }
struct DamusVideoPlayer_Previews: PreviewProvider { struct DamusVideoPlayer_Previews: PreviewProvider {
@StateObject static var model: VideoPlayerModel = VideoPlayerModel() @StateObject static var model: VideoPlayerModel = VideoPlayerModel()
@State static var video_size: CGSize? = nil
static var previews: some View { static var previews: some View {
DamusVideoPlayer(url: URL(string: "http://cdn.jb55.com/s/zaps-build.mp4")!, model: model, video_size: $video_size) DamusVideoPlayer(url: URL(string: "http://cdn.jb55.com/s/zaps-build.mp4")!, model: model, video_size: .constant(nil))
} }
} }