From d130d6c690377c8375b4ac34af2769af72daae83 Mon Sep 17 00:00:00 2001 From: Suhail Saqan Date: Fri, 22 Dec 2023 15:36:32 -0600 Subject: [PATCH] Add ability to preview media taken with camera --- damus.xcodeproj/project.pbxproj | 14 ++-- damus/Views/Camera/CameraMediaView.swift | 89 ++++++++++++++++++++++++ damus/Views/Camera/CameraView.swift | 11 ++- 3 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 damus/Views/Camera/CameraMediaView.swift diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj index a1ebcf7a9c..567b344404 100644 --- a/damus.xcodeproj/project.pbxproj +++ b/damus.xcodeproj/project.pbxproj @@ -420,13 +420,14 @@ 9C83F89329A937B900136C08 /* TextViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C83F89229A937B900136C08 /* TextViewWrapper.swift */; }; 9CA876E229A00CEA0003B9A3 /* AttachMediaUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CA876E129A00CE90003B9A3 /* AttachMediaUtility.swift */; }; ADFE73552AD4793100EC7326 /* QRScanNSECView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADFE73542AD4793100EC7326 /* QRScanNSECView.swift */; }; + BA0F0A6F2B36207E001641B2 /* CameraMediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA0F0A6E2B36207E001641B2 /* CameraMediaView.swift */; }; + BA10192F2B449556009C57DA /* CameraPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA10192E2B449556009C57DA /* CameraPreview.swift */; }; BA37598A2ABCCDE40018D73B /* ImageResizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA3759892ABCCDE30018D73B /* ImageResizer.swift */; }; BA37598D2ABCCE500018D73B /* PhotoCaptureProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA37598B2ABCCE500018D73B /* PhotoCaptureProcessor.swift */; }; BA37598E2ABCCE500018D73B /* VideoCaptureProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA37598C2ABCCE500018D73B /* VideoCaptureProcessor.swift */; }; BA3759922ABCCEBA0018D73B /* CameraService+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA37598F2ABCCEBA0018D73B /* CameraService+Extensions.swift */; }; BA3759932ABCCEBA0018D73B /* CameraModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA3759902ABCCEBA0018D73B /* CameraModel.swift */; }; BA3759942ABCCEBA0018D73B /* CameraService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA3759912ABCCEBA0018D73B /* CameraService.swift */; }; - BA3759972ABCCF360018D73B /* CameraPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA3759962ABCCF360018D73B /* CameraPreview.swift */; }; BA4AB0AE2A63B9270070A32A /* AddEmojiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4AB0AD2A63B9270070A32A /* AddEmojiView.swift */; }; BA4AB0B02A63B94D0070A32A /* EmojiListItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4AB0AF2A63B94D0070A32A /* EmojiListItemView.swift */; }; BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; }; @@ -1238,13 +1239,14 @@ 9C83F89229A937B900136C08 /* TextViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewWrapper.swift; sourceTree = ""; }; 9CA876E129A00CE90003B9A3 /* AttachMediaUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachMediaUtility.swift; sourceTree = ""; }; ADFE73542AD4793100EC7326 /* QRScanNSECView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRScanNSECView.swift; sourceTree = ""; }; + BA0F0A6E2B36207E001641B2 /* CameraMediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraMediaView.swift; sourceTree = ""; }; + BA10192E2B449556009C57DA /* CameraPreview.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraPreview.swift; sourceTree = ""; }; BA3759892ABCCDE30018D73B /* ImageResizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageResizer.swift; sourceTree = ""; }; BA37598B2ABCCE500018D73B /* PhotoCaptureProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoCaptureProcessor.swift; sourceTree = ""; }; BA37598C2ABCCE500018D73B /* VideoCaptureProcessor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoCaptureProcessor.swift; sourceTree = ""; }; BA37598F2ABCCEBA0018D73B /* CameraService+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CameraService+Extensions.swift"; sourceTree = ""; }; BA3759902ABCCEBA0018D73B /* CameraModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraModel.swift; sourceTree = ""; }; BA3759912ABCCEBA0018D73B /* CameraService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraService.swift; sourceTree = ""; }; - BA3759962ABCCF360018D73B /* CameraPreview.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraPreview.swift; sourceTree = ""; }; BA4AB0AD2A63B9270070A32A /* AddEmojiView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddEmojiView.swift; sourceTree = ""; }; BA4AB0AF2A63B94D0070A32A /* EmojiListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiListItemView.swift; sourceTree = ""; }; BA693073295D649800ADDB87 /* UserSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsStore.swift; sourceTree = ""; }; @@ -2487,8 +2489,9 @@ BA3759952ABCCF360018D73B /* Camera */ = { isa = PBXGroup; children = ( - BA3759962ABCCF360018D73B /* CameraPreview.swift */, BAA578D42AED7F4000EA8BE3 /* CameraView.swift */, + BA10192E2B449556009C57DA /* CameraPreview.swift */, + BA0F0A6E2B36207E001641B2 /* CameraMediaView.swift */, ); path = Camera; sourceTree = ""; @@ -2498,8 +2501,6 @@ children = ( D72A2D042AD9C1B5002AFF62 /* MockDamusState.swift */, D72A2D062AD9C1FB002AFF62 /* MockProfiles.swift */, - BAA8C3262AEC570800696158 /* CameraView.swift */, - BA3759962ABCCF360018D73B /* CameraPreview.swift */, ); path = Mocking; sourceTree = ""; @@ -2890,7 +2891,6 @@ 4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */, 3A5E47C52A4A6CF400C0D090 /* Trie.swift in Sources */, 4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */, - BA3759972ABCCF360018D73B /* CameraPreview.swift in Sources */, 4C75EFA627FF87A20006080F /* Nostr.swift in Sources */, 4CA927672A290F8B0098A105 /* RelativeTime.swift in Sources */, 4CB883A62975F83C00DC99E7 /* LNUrlPayRequest.swift in Sources */, @@ -3107,6 +3107,7 @@ 4C1253562A76C8C60004F4B8 /* BroadcastNotify.swift in Sources */, 4C3BEFD42819DE8F00B3DE84 /* NostrKind.swift in Sources */, 4C32B9532A9AD44700DC3548 /* Verifier.swift in Sources */, + BA10192F2B449556009C57DA /* CameraPreview.swift in Sources */, 4C3EA66028FF5E7700C48A62 /* node_id.c in Sources */, 4C687C212A5F7ED00092C550 /* DamusBackground.swift in Sources */, 4CA352A02A76AE80003BB08B /* Notify.swift in Sources */, @@ -3175,6 +3176,7 @@ 4C1A9A2529DDDF2600516EAC /* ZapSettingsView.swift in Sources */, 4C2CDDF7299D4A5E00879FD5 /* Debouncer.swift in Sources */, 3AAA95CC298E07E900F3D526 /* DeepLPlan.swift in Sources */, + BA0F0A6F2B36207E001641B2 /* CameraMediaView.swift in Sources */, 4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */, 3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */, 3AE45AF6297BB2E700C1D842 /* LibreTranslateServer.swift in Sources */, diff --git a/damus/Views/Camera/CameraMediaView.swift b/damus/Views/Camera/CameraMediaView.swift new file mode 100644 index 0000000000..bce63083a5 --- /dev/null +++ b/damus/Views/Camera/CameraMediaView.swift @@ -0,0 +1,89 @@ +// +// MediaViewer.swift +// damus +// +// Created by Suhail Saqan on 12/22/23. +// + +import SwiftUI +import Kingfisher + +// MARK: - Camera Media Viewer +struct CameraMediaView: View { + let video_controller: VideoController + let urls: [MediaUrl] + + @Environment(\.presentationMode) var presentationMode + + @State private var selectedIndex = 0 + @State var showMenu = true + + let settings: UserSettingsStore + + var tabViewIndicator: some View { + HStack(spacing: 10) { + ForEach(urls.indices, id: \.self) { index in + Capsule() + .fill(index == selectedIndex ? Color(UIColor.label) : Color.secondary) + .frame(width: 7, height: 7) + .onTapGesture { + selectedIndex = index + } + } + } + .padding() + .background(.regularMaterial) + .clipShape(Capsule()) + } + + var body: some View { + ZStack { + Color(.systemBackground) + .ignoresSafeArea() + + TabView(selection: $selectedIndex) { + ForEach(urls.indices, id: \.self) { index in + ZoomableScrollView { + ImageContainerView(video_controller: video_controller, url: urls[index], settings: settings) + .aspectRatio(contentMode: .fit) + .padding(.top, Theme.safeAreaInsets?.top) + .padding(.bottom, Theme.safeAreaInsets?.bottom) + } + .ignoresSafeArea() + .tag(index) + } + } + .ignoresSafeArea() + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .never)) + .gesture(TapGesture(count: 2).onEnded { + // Prevents menu from hiding on double tap + }) + .gesture(TapGesture(count: 1).onEnded { + showMenu.toggle() + }) + .overlay( + GeometryReader { geo in + VStack { + if showMenu { + NavDismissBarView() + Spacer() + + if (urls.count > 1) { + tabViewIndicator + } + } + } + .animation(.easeInOut, value: showMenu) + .padding(.bottom, geo.safeAreaInsets.bottom == 0 ? 12 : 0) + } + ) + } + } +} + +struct CameraMediaView_Previews: PreviewProvider { + static var previews: some View { + let url: MediaUrl = .image(URL(string: "https://jb55.com/red-me.jpg")!) + CameraMediaView(video_controller: test_damus_state.video, urls: [url], settings: test_damus_state.settings) + } +} diff --git a/damus/Views/Camera/CameraView.swift b/damus/Views/Camera/CameraView.swift index c021bb710c..4c4d07d448 100644 --- a/damus/Views/Camera/CameraView.swift +++ b/damus/Views/Camera/CameraView.swift @@ -174,7 +174,16 @@ struct CameraView: View { HStack(alignment: .center) { if !model.mediaItems.isEmpty { - NavigationLink(destination: Text(model.mediaItems.map { $0.url.absoluteString }.joined(separator: ", "))) { + NavigationLink(destination: CameraMediaView(video_controller: damus_state.video, urls: model.mediaItems.map { mediaItem in + switch mediaItem.type { + case .image: + return .image(mediaItem.url) + case .video: + return .video(mediaItem.url) + } + }, settings: damus_state.settings) + .navigationBarBackButtonHidden(true) + ) { capturedPhotoThumbnail } .frame(width: 100, alignment: .leading)