damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit d09154344833a0ccd20c23e38947664dad255b01
parent 2e596a47a152f6b4f35a95cca39f9b0b710559c9
Author: Ben Weeks <ben.weeks@outlook.com>
Date:   Mon, 24 Apr 2023 01:51:16 +0100

Add new image carousel

Changelog-Added: Added dots under image carousel
Changelof-Fixed: Fixed carousel issues with multiple images of different aspect ratios
Closes: #1004

Diffstat:
Mdamus/Components/ImageCarousel.swift | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mdamus/Views/Settings/AppearanceSettingsView.swift | 3+++
2 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/damus/Components/ImageCarousel.swift b/damus/Components/ImageCarousel.swift @@ -52,6 +52,7 @@ enum ImageShape { } } +// MARK: - Image Carousel struct ImageCarousel: View { var urls: [URL] @@ -62,9 +63,12 @@ struct ImageCarousel: View { @State private var open_sheet: Bool = false @State private var current_url: URL? = nil @State private var image_fill: ImageFill? = nil - - let fillHeight: CGFloat = 350 - let maxHeight: CGFloat = UIScreen.main.bounds.height * 1.2 + + @State private var fillHeight: CGFloat = 350 + @State private var maxHeight: CGFloat = UIScreen.main.bounds.height * 0.85 // 1.2 + @State private var firstImageHeight: CGFloat = UIScreen.main.bounds.height * 0.85 + @State private var currentImageHeight: CGFloat? + @State private var selectedIndex = 0 init(state: DamusState, evid: String, urls: [URL]) { _open_sheet = State(initialValue: false) @@ -91,7 +95,7 @@ struct ImageCarousel: View { .resizable() .frame(width: geo_size.width * UIScreen.main.scale, height: self.height * UIScreen.main.scale) } else { - EmptyView() + Color.clear } } .onAppear { @@ -105,9 +109,10 @@ struct ImageCarousel: View { } } - var body: some View { - TabView { - ForEach(urls, id: \.absoluteString) { url in + var Images: some View { + TabView(selection: $selectedIndex) { + ForEach(urls.indices, id: \.self) { index in + let url = urls[index] GeometryReader { geo in KFAnimatedImage(url) .callbackQueue(.dispatch(.global(qos:.background))) @@ -128,27 +133,72 @@ struct ImageCarousel: View { 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) } .aspectRatio(contentMode: filling ? .fill : .fit) + //.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .position(x: geo.size.width / 2, y: geo.size.height / 2) .tabItem { Text(url.absoluteString) } .id(url.absoluteString) + .padding(0) } } } + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) .fullScreenCover(isPresented: $open_sheet) { ImageView(urls: urls, disable_animation: state.settings.disable_animation) } - .frame(height: self.height) + .frame(height: firstImageHeight) .onTapGesture { open_sheet = true } + .onChange(of: selectedIndex) { value in + selectedIndex = value + } .tabViewStyle(PageTabViewStyle()) } + + var body: some View { + VStack { + Images + + // This is our custom carousel image indicator + CarouselDotsView(urls: urls, selectedIndex: $selectedIndex) + } + } +} + +// MARK: - Custom Carousel +struct CarouselDotsView: View { + let urls: [URL] + @Binding var selectedIndex: Int + + var body: some View { + if urls.count > 1 { + HStack { + ForEach(urls.indices, id: \.self) { index in + Circle() + .fill(index == selectedIndex ? Color("DamusPurple") : Color("DamusLightGrey")) + .frame(width: 10, height: 10) + .onTapGesture { + selectedIndex = index + } + } + } + .padding(.top, CGFloat(8)) + .id(UUID()) + } + } } // MARK: - Image Modifier @@ -199,6 +249,7 @@ public struct ImageFill { } } +// MARK: - Preview Provider struct ImageCarousel_Previews: PreviewProvider { 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")!]) diff --git a/damus/Views/Settings/AppearanceSettingsView.swift b/damus/Views/Settings/AppearanceSettingsView.swift @@ -14,6 +14,7 @@ struct AppearanceSettingsView: View { var body: some View { Form { + // MARK: - Text Truncation Section(header: Text(NSLocalizedString("Text Truncation", comment: "Section header for damus text truncation user configuration"))) { Toggle(NSLocalizedString("Truncate timeline text", comment: "Setting to truncate text in timeline"), isOn: $settings.truncate_timeline_text) .toggleStyle(.switch) @@ -21,11 +22,13 @@ struct AppearanceSettingsView: View { .toggleStyle(.switch) } + // MARK: - Accessibility Section(header: Text(NSLocalizedString("Accessibility", comment: "Section header for accessibility settings"))) { Toggle(NSLocalizedString("Left Handed", comment: "Moves the post button to the left side of the screen"), isOn: $settings.left_handed) .toggleStyle(.switch) } + // MARK: - Images Section(NSLocalizedString("Images", comment: "Section title for images configuration.")) { Toggle(NSLocalizedString("Animations", comment: "Toggle to enable or disable image animation"), isOn: $settings.enable_animation) .toggleStyle(.switch)