GetStream / stream-chat-swiftui

SwiftUI Chat SDK ➜ Stream Chat 💬
https://getstream.io/chat/sdk/swiftui/
Other
342 stars 84 forks source link

Unable to load images to composer using PHPickerViewController #203

Closed Dzondzula closed 2 years ago

Dzondzula commented 2 years ago

What did you do?

I've added custom button overriding viewFactory makePhotoAttachmentPickerView that is opening sheet with PHPicker. Code is as short as posible but also works.

func makePhotoAttachmentPickerView(
        assets: PHFetchResultCollection,
        onAssetTap: @escaping (AddedAsset) -> Void,
        isAssetSelected: @escaping (String) -> Bool
    ) -> some View {
        ZStack(alignment: .bottomTrailing){
            PhotoAttachmentPickerView(
                assets: assets,
                onImageTap: onAssetTap,
                imageSelected: isAssetSelected
            )

            OpenPhotoLibrary{ image in
                onAssetTap(image)
            }
        }
        }

Button that opens picker:

struct OpenPhotoLibrary: View {

    @State var photoLibraryShown: Bool = false
    var onImageTap: (AddedAsset) -> Void
    var body: some View {

        VStack{
            Spacer()
                .sheet(isPresented: $photoLibraryShown, onDismiss: {

                }) {

                    PHImagePicker{asset in
                        onImageTap(asset)
                    }
                    .ignoresSafeArea()

                }
            Button {

                photoLibraryShown = true
            } label: {
                VStack{
                    Image(systemName: "circle.grid.3x3.circle.fill")
                        .resizable()
                        .frame(width: 49, height: 49)

                }
            }
            .frame(width: 49, height: 49)
            .padding(.horizontal,7)
            .padding(.bottom,35)
            .padding(.trailing,10)

        }
    }
}

And picker:

struct PHImagePicker: UIViewControllerRepresentable{

    var onAssetPicked: (AddedAsset) -> Void

    init(_ onAssetPicked:@escaping (AddedAsset) -> Void) {
        self.onAssetPicked = onAssetPicked
    }

    class Coordinator: NSObject,PHPickerViewControllerDelegate,UIAdaptivePresentationControllerDelegate{

        var parent : PHImagePicker

        init(_ parent: PHImagePicker){
            self.parent = parent

        }

        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            let itemProvider = results[0].itemProvider
                self.getPhoto(from: itemProvider)
            picker.dismiss(animated: true)

        }

        private func getPhoto(from itemProvider: NSItemProvider) {
            if itemProvider.canLoadObject(ofClass: UIImage.self) {
                itemProvider.loadObject(ofClass: UIImage.self) { object, error in
                    if let error = error {
                        print(error.localizedDescription)
                    }

                    if let image = object as? UIImage {
                        DispatchQueue.main.async {
                            let url = URL(string: "https://www.abc.com/")
                            self.parent.onAssetPicked(AddedAsset(image: image, id: UUID().uuidString, url: url!, type: .image))
                        }
                    }
                }
            }
        }
    }
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIViewController(context: Context) -> PHPickerViewController {
           var config = PHPickerConfiguration()
        config.selectionLimit = 20
        config.preferredAssetRepresentationMode = .current
        config.filter = .images

        let picker = PHPickerViewController(configuration: config)
        picker.delegate = context.coordinator
        return picker
       }

       func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {

       }
}

What did you expect to happen?

After clicking Add button on picker I want to trigger view for an added image displayed in the composer input AddedImageAttachmentsView

What happened instead?

Picker is being dissmissed and no input is shown inside composer

GetStream Environment

GetStream Chat version: GetStream Chat frameworks: StreamChat, StreamChatSwiftUI iOS version: 15 Swift version: Xcode version: 13.4 Device:

Additional context

martinmitrevski commented 2 years ago

Hey @Dzondzula,

This happens because you're adding a hardcoded url let url = URL(string: "https://www.abc.com/").

Here you need to provide the local asset url. The SDK uses the local URL in order to compute the attachment size, and if it can't (in this case because it's a remote url not connected to the resource), it throws an error.

Best, Martin

Dzondzula commented 2 years ago

Thanks a lot for your commitment and responsiveness @martinmitrevski

Wishing you best, Nikola