diff --git a/damus/Components/ImageCarousel.swift b/damus/Components/ImageCarousel.swift index 20be57cb..c95cbe68 100644 --- a/damus/Components/ImageCarousel.swift +++ b/damus/Components/ImageCarousel.swift @@ -77,13 +77,14 @@ class CarouselModel: ObservableObject { // MARK: - Image Carousel @MainActor -struct ImageCarousel: View { +struct ImageCarousel: View { var urls: [MediaUrl] let evid: NoteId let state: DamusState @ObservedObject var model: CarouselModel + let content: ((_ dismiss: @escaping (() -> Void)) -> Content)? init(state: DamusState, evid: NoteId, urls: [MediaUrl]) { self.urls = urls @@ -91,6 +92,16 @@ struct ImageCarousel: View { self.state = state let media_model = state.events.get_cache_data(evid).media_metadata_model self._model = ObservedObject(initialValue: CarouselModel(image_fill: media_model.fill)) + self.content = nil + } + + init(state: DamusState, evid: NoteId, urls: [MediaUrl], @ViewBuilder content: @escaping (_ dismiss: @escaping (() -> Void)) -> Content) { + self.urls = urls + self.evid = evid + self.state = state + let media_model = state.events.get_cache_data(evid).media_metadata_model + self._model = ObservedObject(initialValue: CarouselModel(image_fill: media_model.fill)) + self.content = content } var filling: Bool { @@ -201,7 +212,16 @@ struct ImageCarousel: View { } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) .fullScreenCover(isPresented: $model.open_sheet) { - FullScreenCarouselView(video_controller: state.video, urls: urls, settings: state.settings, selectedIndex: $model.selectedIndex) + if let content { + FullScreenCarouselView(video_controller: state.video, urls: urls, settings: state.settings, selectedIndex: $model.selectedIndex) { + content({ // Dismiss closure + model.open_sheet = false + }) + } + } + else { + FullScreenCarouselView(video_controller: state.video, urls: urls, settings: state.settings, selectedIndex: $model.selectedIndex) + } } .frame(height: height) .onChange(of: model.selectedIndex) { value in @@ -297,7 +317,7 @@ struct ImageCarousel_Previews: PreviewProvider { static var previews: some View { let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!) let test_video_url: MediaUrl = .video(URL(string: "http://cdn.jb55.com/s/zaps-build.mp4")!) - ImageCarousel(state: test_damus_state, evid: test_note.id, urls: [test_video_url, url]) + ImageCarousel(state: test_damus_state, evid: test_note.id, urls: [test_video_url, url]) .environmentObject(OrientationTracker()) } } diff --git a/damus/Components/TruncatedText.swift b/damus/Components/TruncatedText.swift index 62c909cb..8fca6895 100644 --- a/damus/Components/TruncatedText.swift +++ b/damus/Components/TruncatedText.swift @@ -9,7 +9,12 @@ import SwiftUI struct TruncatedText: View { let text: CompatibleText - let maxChars: Int = 280 + let maxChars: Int + + init(text: CompatibleText, maxChars: Int = 280) { + self.text = text + self.maxChars = maxChars + } var body: some View { let truncatedAttributedString: AttributedString? = text.attributed.truncateOrNil(maxLength: maxChars) diff --git a/damus/Views/Events/TextEvent.swift b/damus/Views/Events/TextEvent.swift index 1570dcc0..c1bedb6d 100644 --- a/damus/Views/Events/TextEvent.swift +++ b/damus/Views/Events/TextEvent.swift @@ -19,8 +19,11 @@ struct EventViewOptions: OptionSet { static let nested = EventViewOptions(rawValue: 1 << 7) static let top_zap = EventViewOptions(rawValue: 1 << 8) static let no_mentions = EventViewOptions(rawValue: 1 << 9) + static let no_media = EventViewOptions(rawValue: 1 << 10) + static let truncate_content_very_short = EventViewOptions(rawValue: 1 << 11) static let embedded: EventViewOptions = [.no_action_bar, .small_pfp, .wide, .truncate_content, .nested] + static let embedded_text_only: EventViewOptions = [.no_action_bar, .small_pfp, .wide, .truncate_content, .nested, .no_media, .truncate_content_very_short] } struct TextEvent: View { diff --git a/damus/Views/Images/FullScreenCarouselView.swift b/damus/Views/Images/FullScreenCarouselView.swift index 38290bf5..7e11ff57 100644 --- a/damus/Views/Images/FullScreenCarouselView.swift +++ b/damus/Views/Images/FullScreenCarouselView.swift @@ -7,7 +7,7 @@ import SwiftUI -struct FullScreenCarouselView: View { +struct FullScreenCarouselView: View { let video_controller: VideoController let urls: [MediaUrl] @@ -17,6 +17,25 @@ struct FullScreenCarouselView: View { let settings: UserSettingsStore @Binding var selectedIndex: Int + let content: (() -> Content)? + + init(video_controller: VideoController, urls: [MediaUrl], showMenu: Bool = true, settings: UserSettingsStore, selectedIndex: Binding, @ViewBuilder content: @escaping () -> Content) { + self.video_controller = video_controller + self.urls = urls + self.showMenu = showMenu + self.settings = settings + _selectedIndex = selectedIndex + self.content = content + } + + init(video_controller: VideoController, urls: [MediaUrl], showMenu: Bool = true, settings: UserSettingsStore, selectedIndex: Binding) { + self.video_controller = video_controller + self.urls = urls + self.showMenu = showMenu + self.settings = settings + _selectedIndex = selectedIndex + self.content = nil + } var tabViewIndicator: some View { HStack(spacing: 10) { @@ -99,6 +118,8 @@ struct FullScreenCarouselView: View { if (urls.count > 1) { tabViewIndicator } + + self.content?() } } .animation(.easeInOut, value: showMenu) @@ -115,7 +136,7 @@ fileprivate struct ImageViewPreview: View { let test_video_url: MediaUrl = .video(URL(string: "http://cdn.jb55.com/s/zaps-build.mp4")!) var body: some View { - FullScreenCarouselView(video_controller: test_damus_state.video, urls: [test_video_url, url], settings: test_damus_state.settings, selectedIndex: $selectedIndex) + FullScreenCarouselView(video_controller: test_damus_state.video, urls: [test_video_url, url], settings: test_damus_state.settings, selectedIndex: $selectedIndex) .environmentObject(OrientationTracker()) } } diff --git a/damus/Views/NoteContentView.swift b/damus/Views/NoteContentView.swift index 1b664baf..491fe4ac 100644 --- a/damus/Views/NoteContentView.swift +++ b/damus/Views/NoteContentView.swift @@ -57,6 +57,10 @@ struct NoteContentView: View { return options.contains(.truncate_content) } + var truncate_very_short: Bool { + return options.contains(.truncate_content_very_short) + } + var with_padding: Bool { return options.contains(.wide) } @@ -73,7 +77,11 @@ struct NoteContentView: View { func truncatedText(content: CompatibleText) -> some View { Group { - if truncate { + if truncate_very_short { + TruncatedText(text: content, maxChars: 140) + .font(eventviewsize_to_font(size, font_size: damus_state.settings.font_size)) + } + else if truncate { TruncatedText(text: content) .font(eventviewsize_to_font(size, font_size: damus_state.settings.font_size)) } else { @@ -107,6 +115,19 @@ struct NoteContentView: View { } } + func fullscreen_preview(dismiss: @escaping () -> Void) -> some View { + VStack { + EventView(damus: damus_state, event: self.event, options: .embedded_text_only) + .padding(.top) + } + .background(.thinMaterial) + .preferredColorScheme(.dark) + .onTapGesture(perform: { + damus_state.nav.push(route: Route.Thread(thread: .init(event: self.event, damus_state: damus_state))) + dismiss() + }) + } + func MainContent(artifacts: NoteArtifactsSeparated) -> some View { VStack(alignment: .leading) { if size == .selected { @@ -135,13 +156,19 @@ struct NoteContentView: View { } if artifacts.media.count > 0 { - if !damus_state.settings.media_previews && !load_media { + if (self.options.contains(.no_media)) { + EmptyView() + } else if !damus_state.settings.media_previews && !load_media { loadMediaButton(artifacts: artifacts) } else if !blur_images || (!blur_images && !damus_state.settings.media_previews && load_media) { - ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.media) + ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.media) { dismiss in + fullscreen_preview(dismiss: dismiss) + } } else if blur_images || (blur_images && !damus_state.settings.media_previews && load_media) { ZStack { - ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.media) + ImageCarousel(state: damus_state, evid: event.id, urls: artifacts.media) { dismiss in + fullscreen_preview(dismiss: dismiss) + } Blur() .onTapGesture { blur_images = false