cache: move event-specific media metadata to EventCache
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 = [:]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = [:]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user