From 98efeaad6bed76542104398b7f50401200650c8c Mon Sep 17 00:00:00 2001 From: Joseph Cha Date: Thu, 22 Aug 2024 10:07:13 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8#297:=20Share=20Extension=EC=9D=98=20'?= =?UTF-8?q?=EC=95=B1=EC=97=90=EC=84=9C=20=EB=B3=B4=EA=B8=B0'=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C,=20=EC=95=B1?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=B4=20Share=20Exte?= =?UTF-8?q?nsion=EC=97=90=EC=84=9C=20=EB=93=9C=EB=9E=8D=ED=95=9C=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=ED=85=9C=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EC=BB=A4=EB=AE=A4=EB=8B=88=ED=8B=B0=20Scene=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EB=A0=8C=EB=8D=94=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Share Extension에서 드랍한 아이템 ID, UserDefaults에 저장 및 메인 Scene ViewDidAppear 또는 Bakcground -> Foreground 전환 시 커뮤니티 Scene 렌더링 --- .../View/DropDone/DropDoneView.swift | 8 +++ .../View/ShareViewController.swift | 58 +++++++++++++++++-- .../ViewModel/ShareViewModel.swift | 6 +- .../Application/SceneDelegate.swift | 36 ++++++------ .../MainScene/View/MainViewController.swift | 34 +++++++++++ 5 files changed, 118 insertions(+), 24 deletions(-) diff --git a/StreetDrop/ShareExtension/View/DropDone/DropDoneView.swift b/StreetDrop/ShareExtension/View/DropDone/DropDoneView.swift index 6259eda0..f7317d3b 100644 --- a/StreetDrop/ShareExtension/View/DropDone/DropDoneView.swift +++ b/StreetDrop/ShareExtension/View/DropDone/DropDoneView.swift @@ -18,6 +18,10 @@ final class DropDoneView: UIView { var exitButtonEvent: Observable { exitButtonEventRelay.asObservable() } + private let viewOnAppButtonEventRelay: PublishRelay = .init() + var viewOnAppButtonEvent: Observable { + viewOnAppButtonEventRelay.asObservable() + } private let droppedMusic: Music private let droppedAddress: String @@ -150,6 +154,10 @@ private extension DropDoneView { exitButton.rx.tap .bind(to: exitButtonEventRelay) .disposed(by: disposeBag) + + viewOnAppButton.rx.tap + .bind(to: viewOnAppButtonEventRelay) + .disposed(by: disposeBag) } func configureUI() { diff --git a/StreetDrop/ShareExtension/View/ShareViewController.swift b/StreetDrop/ShareExtension/View/ShareViewController.swift index fa88b711..bc751a90 100644 --- a/StreetDrop/ShareExtension/View/ShareViewController.swift +++ b/StreetDrop/ShareExtension/View/ShareViewController.swift @@ -216,8 +216,6 @@ final class ShareViewController: UIViewController, Alertable { return reSearchingMusicForSharingView }() - private var dropDoneView: DropDoneView? - private let failedLoadingMusicView: FailedLoadingMusicView = { let failedLoadingMusicView: FailedLoadingMusicView = .init() failedLoadingMusicView.isHidden = true @@ -424,13 +422,13 @@ private extension ShareViewController { containerView.isHidden = true reSearchingMusicForSharingView.isHidden = true - dropDoneView = .init( + let dropDoneView: DropDoneView = .init( droppedMusic: droppedMusic, droppedAddress: droppedAddress, droppedComment: droppedComment ) - guard let dropDoneView = dropDoneView else { return } view.addSubview(dropDoneView) + dropDoneView.snp.makeConstraints { $0.horizontalEdges.bottom.equalToSuperview() } @@ -444,6 +442,58 @@ private extension ShareViewController { } .disposed(by: disposeBag) + dropDoneView.viewOnAppButtonEvent + .bind(with: self) { owner, _ in + guard let droppedItemID = owner.viewModel.itemID else { + owner.showAlert( + type: .alert( + onConfirm: { [weak self] in + self?.extensionContext?.completeRequest( + returningItems: nil, + completionHandler: nil + ) + } + ), + state: .primary, + title: "에러 발생", + subText: "드랍된 ID를 찾을 수 없습니다.", + buttonTitle: "확인" + ) + return + } + + guard let url = URL(string: "streetdrop://") else { return } + var responder = self as UIResponder? + while responder != nil { + if let application = responder as? UIApplication { + guard let sharedDefaults = UserDefaults(suiteName: "group.com.depromeet.StreetDrop") else { + owner.showAlert( + type: .alert( + onConfirm: { [weak self] in + self?.extensionContext?.completeRequest( + returningItems: nil, + completionHandler: nil + ) + } + ), + state: .primary, + title: "에러 발생", + subText: "드랍 아이템 ID 내부 데이터 저장 실패", + buttonTitle: "확인" + ) + return + } + sharedDefaults.set(droppedItemID, forKey: "ShareExtensionDroppedItemID") + sharedDefaults.synchronize() + + application.open(url, options: [:], completionHandler: nil) + break + } + responder = responder?.next + } + } + .disposed(by: disposeBag) + view.layoutIfNeeded() }) }) diff --git a/StreetDrop/ShareExtension/ViewModel/ShareViewModel.swift b/StreetDrop/ShareExtension/ViewModel/ShareViewModel.swift index a052472c..617ef5ce 100644 --- a/StreetDrop/ShareExtension/ViewModel/ShareViewModel.swift +++ b/StreetDrop/ShareExtension/ViewModel/ShareViewModel.swift @@ -28,6 +28,7 @@ final class ShareViewModel: NSObject, ShareViewModelType { var sharedSongName: String = "" var selectedMusic: Music? var comment: String? + var itemID: Int? init( searchMusicUsecase: SearchMusicUsecase = DefaultSearchingMusicUsecase(), @@ -131,14 +132,15 @@ final class ShareViewModel: NSObject, ShareViewModelType { return } - owner.dropMusicUseCase.drop( + owner.dropMusicUseCase.dropMusicResponsingOnlyItemID( droppingInfo: .init( location: currentLocation, music: selectedMusic ), content: comment ) - .subscribe(with: self) { owner, statusCode in + .subscribe(with: self) { owner, itemID in + owner.itemID = itemID owner.output.goDropDoneViewRelay.accept( (selectedMusic, currentLocation.address, comment) ) diff --git a/StreetDrop/StreetDrop/Application/SceneDelegate.swift b/StreetDrop/StreetDrop/Application/SceneDelegate.swift index a29923af..1e88a846 100644 --- a/StreetDrop/StreetDrop/Application/SceneDelegate.swift +++ b/StreetDrop/StreetDrop/Application/SceneDelegate.swift @@ -33,6 +33,24 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { guard let url = URLContexts.first?.url else { return } handleDeepLink(isLaunched: false, url: url) } + + func navigateToCommunity(with itemID: Int) { + let sceneDelegate = UIApplication.shared.connectedScenes + .first!.delegate as? SceneDelegate + + if let navigationView = topViewController(base: sceneDelegate?.window!.rootViewController)? + .navigationController as? UINavigationController{ + + let communityViewModel = CommunityViewModel( + communityInfos: [], + index: 0 + ) + communityViewModel.itemID = itemID + + let communityView = CommunityViewController(viewModel: communityViewModel) + navigationView.pushViewController(communityView, animated: true) + } + } } // MARK: - Private Methods @@ -89,24 +107,6 @@ private extension SceneDelegate { } } - func navigateToCommunity(with itemID: Int) { - let sceneDelegate = UIApplication.shared.connectedScenes - .first!.delegate as? SceneDelegate - - if let navigationView = topViewController(base: sceneDelegate?.window!.rootViewController)? - .navigationController as? UINavigationController{ - - let communityViewModel = CommunityViewModel( - communityInfos: [], - index: 0 - ) - communityViewModel.itemID = itemID - - let communityView = CommunityViewController(viewModel: communityViewModel) - navigationView.pushViewController(communityView, animated: true) - } - } - func topViewController(base: UIViewController?) -> UIViewController? { if let nav = base as? UINavigationController { return topViewController(base: nav.visibleViewController) diff --git a/StreetDrop/StreetDrop/Presentation/MainScene/View/MainViewController.swift b/StreetDrop/StreetDrop/Presentation/MainScene/View/MainViewController.swift index 516677f7..30323bea 100644 --- a/StreetDrop/StreetDrop/Presentation/MainScene/View/MainViewController.swift +++ b/StreetDrop/StreetDrop/Presentation/MainScene/View/MainViewController.swift @@ -41,6 +41,14 @@ final class MainViewController: UIViewController, Toastable, Alertable { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + deinit { + NotificationCenter.default.removeObserver( + self, + name: UIApplication.willEnterForegroundNotification, + object: nil + ) + } override func viewDidLoad() { super.viewDidLoad() @@ -64,6 +72,13 @@ final class MainViewController: UIViewController, Toastable, Alertable { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) viewDidAppearEvent.accept(Void()) + NotificationCenter.default.addObserver( + self, + selector: #selector(configureShareExtensionViewOnAppButton), + name: UIApplication.willEnterForegroundNotification, + object: nil + ) + configureShareExtensionViewOnAppButton() } // MARK: - UI @@ -977,3 +992,22 @@ extension MainViewController: NMFMapViewCameraDelegate { self.locationOverlay.circleRadius = viewModel.userCircleRadius / naverMapView.projection.metersPerPixel() } } + +// MARK: - Share Extension + +private extension MainViewController { + @objc func configureShareExtensionViewOnAppButton() { + guard let sharedDefaults = UserDefaults(suiteName: "group.com.depromeet.StreetDrop") else { + print("Failed to access shared UserDefaults.") + return + } + + guard let shareExtensionDroppedItemID = sharedDefaults.object(forKey: "ShareExtensionDroppedItemID") as? Int, + let scene = view.window?.windowScene, + let sceneDelegate = scene.delegate as? SceneDelegate else { return } + + sceneDelegate.navigateToCommunity(with: shareExtensionDroppedItemID) + sharedDefaults.removeObject(forKey: "ShareExtensionDroppedItemID") + sharedDefaults.synchronize() + } +}