carousel: switch to media carousel and include video
This commit is contained in:
@@ -54,7 +54,7 @@ enum ImageShape {
|
|||||||
|
|
||||||
// MARK: - Image Carousel
|
// MARK: - Image Carousel
|
||||||
struct ImageCarousel: View {
|
struct ImageCarousel: View {
|
||||||
var urls: [URL]
|
var urls: [MediaUrl]
|
||||||
|
|
||||||
let evid: String
|
let evid: String
|
||||||
|
|
||||||
@@ -69,8 +69,9 @@ struct ImageCarousel: View {
|
|||||||
@State private var firstImageHeight: CGFloat? = nil
|
@State private var firstImageHeight: CGFloat? = nil
|
||||||
@State private var currentImageHeight: CGFloat?
|
@State private var currentImageHeight: CGFloat?
|
||||||
@State private var selectedIndex = 0
|
@State private var selectedIndex = 0
|
||||||
|
@State private var video_size: CGSize? = nil
|
||||||
|
|
||||||
init(state: DamusState, evid: String, urls: [URL]) {
|
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))
|
_image_fill = State(initialValue: state.previews.lookup_image_meta(evid))
|
||||||
@@ -112,47 +113,79 @@ struct ImageCarousel: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var Images: some View {
|
func Media(geo: GeometryProxy, url: MediaUrl, index: Int) -> some View {
|
||||||
TabView(selection: $selectedIndex) {
|
Group {
|
||||||
|
switch url {
|
||||||
|
case .image(let url):
|
||||||
|
Img(geo: geo, url: url, index: index)
|
||||||
|
.onTapGesture {
|
||||||
|
open_sheet = true
|
||||||
|
}
|
||||||
|
case .video(let url):
|
||||||
|
DamusVideoPlayer(url: url, video_size: $video_size)
|
||||||
|
.onTapGesture {
|
||||||
|
print("video tap")
|
||||||
|
}
|
||||||
|
.onChange(of: video_size) { size in
|
||||||
|
guard image_fill == nil, let size else {
|
||||||
|
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 {
|
||||||
|
firstImageHeight = fill.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Img(geo: GeometryProxy, url: URL, index: Int) -> some View {
|
||||||
|
KFAnimatedImage(url)
|
||||||
|
.callbackQueue(.dispatch(.global(qos:.background)))
|
||||||
|
.backgroundDecode(true)
|
||||||
|
.imageContext(.note, disable_animation: state.settings.disable_animation)
|
||||||
|
.image_fade(duration: 0.25)
|
||||||
|
.cancelOnDisappear(true)
|
||||||
|
.configure { view in
|
||||||
|
view.framePreloadCount = 3
|
||||||
|
}
|
||||||
|
.imageFill(for: geo.size, max: maxHeight, fill: fillHeight) { fill in
|
||||||
|
state.previews.cache_image_meta(evid: evid, image_fill: fill)
|
||||||
|
// blur hash can be discarded when we have the url
|
||||||
|
// NOTE: this is the wrong place for this... we need to remove
|
||||||
|
// it when the image is loaded in memory. This may happen
|
||||||
|
// earlier than this (by the preloader, etc)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
||||||
|
state.events.lookup_img_metadata(url: url)?.state = .not_needed
|
||||||
|
}
|
||||||
|
image_fill = fill
|
||||||
|
if index == 0 {
|
||||||
|
firstImageHeight = fill.height
|
||||||
|
//maxHeight = firstImageHeight ?? maxHeight
|
||||||
|
} else {
|
||||||
|
//maxHeight = firstImageHeight ?? fill.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background {
|
||||||
|
Placeholder(url: url, geo_size: geo.size, num_urls: urls.count)
|
||||||
|
}
|
||||||
|
.aspectRatio(contentMode: filling ? .fill : .fit)
|
||||||
|
.tabItem {
|
||||||
|
Text(url.absoluteString)
|
||||||
|
}
|
||||||
|
.id(url.absoluteString)
|
||||||
|
.padding(0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var Medias: some View {
|
||||||
|
TabView {
|
||||||
ForEach(urls.indices, id: \.self) { index in
|
ForEach(urls.indices, id: \.self) { index in
|
||||||
let url = urls[index]
|
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
KFAnimatedImage(url)
|
Media(geo: geo, url: urls[index], index: index)
|
||||||
.callbackQueue(.dispatch(.global(qos:.background)))
|
|
||||||
.backgroundDecode(true)
|
|
||||||
.imageContext(.note, disable_animation: state.settings.disable_animation)
|
|
||||||
.image_fade(duration: 0.25)
|
|
||||||
.cancelOnDisappear(true)
|
|
||||||
.configure { view in
|
|
||||||
view.framePreloadCount = 3
|
|
||||||
}
|
|
||||||
.imageFill(for: geo.size, max: maxHeight, fill: fillHeight) { fill in
|
|
||||||
state.previews.cache_image_meta(evid: evid, image_fill: fill)
|
|
||||||
// blur hash can be discarded when we have the url
|
|
||||||
// NOTE: this is the wrong place for this... we need to remove
|
|
||||||
// it when the image is loaded in memory. This may happen
|
|
||||||
// earlier than this (by the preloader, etc)
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
|
||||||
state.events.lookup_img_metadata(url: url)?.state = .not_needed
|
|
||||||
}
|
|
||||||
image_fill = fill
|
|
||||||
if index == 0 {
|
|
||||||
firstImageHeight = fill.height
|
|
||||||
//maxHeight = firstImageHeight ?? maxHeight
|
|
||||||
} else {
|
|
||||||
//maxHeight = firstImageHeight ?? fill.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.background {
|
|
||||||
Placeholder(url: url, geo_size: geo.size, num_urls: urls.count)
|
|
||||||
}
|
|
||||||
.aspectRatio(contentMode: filling ? .fill : .fit)
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
|
|
||||||
.tabItem {
|
|
||||||
Text(url.absoluteString)
|
|
||||||
}
|
|
||||||
.id(url.absoluteString)
|
|
||||||
.padding(0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,14 +198,14 @@ struct ImageCarousel: View {
|
|||||||
open_sheet = true
|
open_sheet = true
|
||||||
}
|
}
|
||||||
.onChange(of: selectedIndex) { value in
|
.onChange(of: selectedIndex) { value in
|
||||||
selectedIndex = value
|
selectedIndex = value
|
||||||
}
|
}
|
||||||
.tabViewStyle(PageTabViewStyle())
|
.tabViewStyle(PageTabViewStyle())
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Images
|
Medias
|
||||||
|
|
||||||
// This is our custom carousel image indicator
|
// This is our custom carousel image indicator
|
||||||
CarouselDotsView(urls: urls, selectedIndex: $selectedIndex)
|
CarouselDotsView(urls: urls, selectedIndex: $selectedIndex)
|
||||||
@@ -181,8 +214,8 @@ struct ImageCarousel: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Custom Carousel
|
// MARK: - Custom Carousel
|
||||||
struct CarouselDotsView: View {
|
struct CarouselDotsView<T>: View {
|
||||||
let urls: [URL]
|
let urls: [T]
|
||||||
@Binding var selectedIndex: Int
|
@Binding var selectedIndex: Int
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -254,7 +287,8 @@ public struct ImageFill {
|
|||||||
// MARK: - Preview Provider
|
// MARK: - Preview Provider
|
||||||
struct ImageCarousel_Previews: PreviewProvider {
|
struct ImageCarousel_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ImageCarousel(state: test_damus_state(), evid: "evid", urls: [URL(string: "https://jb55.com/red-me.jpg")!,URL(string: "https://jb55.com/red-me.jpg")!])
|
let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!)
|
||||||
|
ImageCarousel(state: test_damus_state(), evid: "evid", urls: [url, url])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ import Kingfisher
|
|||||||
|
|
||||||
|
|
||||||
struct ImageContainerView: View {
|
struct ImageContainerView: View {
|
||||||
let url: URL?
|
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
|
||||||
|
|
||||||
@@ -26,8 +27,7 @@ struct ImageContainerView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
func Img(url: URL) -> some View {
|
||||||
|
|
||||||
KFAnimatedImage(url)
|
KFAnimatedImage(url)
|
||||||
.imageContext(.note, disable_animation: disable_animation)
|
.imageContext(.note, disable_animation: disable_animation)
|
||||||
.configure { view in
|
.configure { view in
|
||||||
@@ -40,12 +40,23 @@ struct ImageContainerView: View {
|
|||||||
ShareSheet(activityItems: [url])
|
ShareSheet(activityItems: [url])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
switch url {
|
||||||
|
case .image(let url):
|
||||||
|
Img(url: url)
|
||||||
|
case .video(let url):
|
||||||
|
DamusVideoPlayer(url: url, video_size: $video_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let test_image_url = URL(string: "https://jb55.com/red-me.jpg")!
|
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: test_image_url, disable_animation: false)
|
ImageContainerView(url: .image(test_image_url), disable_animation: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ImageView: View {
|
struct ImageView: View {
|
||||||
|
let urls: [MediaUrl]
|
||||||
let urls: [URL?]
|
|
||||||
|
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
|
||||||
@@ -79,6 +78,7 @@ struct ImageView: View {
|
|||||||
|
|
||||||
struct ImageView_Previews: PreviewProvider {
|
struct ImageView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ImageView(urls: [URL(string: "https://jb55.com/red-me.jpg")], disable_animation: false)
|
let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!)
|
||||||
|
ImageView(urls: [url], disable_animation: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,11 +130,11 @@ struct NoteContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if show_images && artifacts.images.count > 0 {
|
if show_images && artifacts.media.count > 0 {
|
||||||
ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.images)
|
ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.media)
|
||||||
} else if !show_images && artifacts.images.count > 0 {
|
} else if !show_images && artifacts.media.count > 0 {
|
||||||
ZStack {
|
ZStack {
|
||||||
ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.images)
|
ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.media)
|
||||||
Blur()
|
Blur()
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user