diff --git a/RiotSwiftUI/Modules/Room/Composer/LinkAction/Coordinator/ComposerLinkActionBridgePresenter.swift b/RiotSwiftUI/Modules/Room/Composer/LinkAction/Coordinator/ComposerLinkActionBridgePresenter.swift new file mode 100644 index 000000000..b0c69c221 --- /dev/null +++ b/RiotSwiftUI/Modules/Room/Composer/LinkAction/Coordinator/ComposerLinkActionBridgePresenter.swift @@ -0,0 +1,65 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import WysiwygComposer + +protocol ComposerLinkActionBridgePresenterDelegate: AnyObject { + func didCancel() + func didDismissInteractively() + func didRequestLinkOperation(_ linkOperation: WysiwygLinkOperation) +} + +final class ComposerLinkActionBridgePresenter: NSObject { + private var coordinator: ComposerLinkActionCoordinator? + private var linkAction: LinkAction + + weak var delegate: ComposerLinkActionBridgePresenterDelegate? + + init(linkAction: LinkActionWrapper) { + self.linkAction = linkAction.linkAction + super.init() + } + + func present(from viewController: UIViewController, animated: Bool) { + let composerLinkActionCoordinator = ComposerLinkActionCoordinator(linkAction: linkAction) + composerLinkActionCoordinator.callback = { [weak self] action in + switch action { + case .didTapCancel: + self?.delegate?.didCancel() + case .didDismissInteractively: + self?.delegate?.didDismissInteractively() + case let .didRequestLinkOperation(linkOperation): + self?.delegate?.didRequestLinkOperation(linkOperation) + } + } + let presentable = composerLinkActionCoordinator.toPresentable() + viewController.present(presentable, animated: animated, completion: nil) + composerLinkActionCoordinator.start() + coordinator = composerLinkActionCoordinator + } + + func dismiss(animated: Bool, completion: (() -> Void)?) { + guard let coordinator = coordinator else { + return + } + // Dismiss modal + coordinator.toPresentable().dismiss(animated: animated) { + self.coordinator = nil + completion?() + } + } +} diff --git a/RiotSwiftUI/Modules/Room/Composer/LinkAction/Coordinator/ComposerLinkActionCoordinator.swift b/RiotSwiftUI/Modules/Room/Composer/LinkAction/Coordinator/ComposerLinkActionCoordinator.swift new file mode 100644 index 000000000..c3bd7406e --- /dev/null +++ b/RiotSwiftUI/Modules/Room/Composer/LinkAction/Coordinator/ComposerLinkActionCoordinator.swift @@ -0,0 +1,61 @@ +// +// Copyright 2022 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import WysiwygComposer + +enum ComposerLinkActionCoordinatorAction { + case didTapCancel + case didDismissInteractively + case didRequestLinkOperation(_ linkOperation: WysiwygLinkOperation) +} + +final class ComposerLinkActionCoordinator: NSObject, Coordinator, Presentable { + var childCoordinators: [Coordinator] = [] + + private let hostingController: UIViewController + private let viewModel: ComposerLinkActionViewModel + + var callback: ((ComposerLinkActionCoordinatorAction) -> Void)? + + init(linkAction: LinkAction) { + viewModel = ComposerLinkActionViewModel(from: linkAction) + hostingController = VectorHostingController(rootView: ComposerLinkAction(viewModel: viewModel.context)) + super.init() + hostingController.presentationController?.delegate = self + } + + func start() { + viewModel.callback = { [weak self] result in + switch result { + case .cancel: + self?.callback?(.didTapCancel) + case let .performOperation(linkOperation): + self?.callback?(.didRequestLinkOperation(linkOperation)) + } + } + } + + func toPresentable() -> UIViewController { + hostingController + } +} + +extension ComposerLinkActionCoordinator: UIAdaptivePresentationControllerDelegate { + func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { + self.callback?(.didDismissInteractively) + } +}