Fix image preview presentation when order source sheet is open.

Present previews from the top of the presentation chain so tapping lead images inside the sheet no longer conflicts with the already-presented picker.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 11:14:57 +08:00
co-authored by Cursor
parent 77fec21563
commit 5a2b7b6097
4 changed files with 31 additions and 20 deletions
+24
View File
@@ -119,6 +119,30 @@ class BaseViewController: UIViewController {
navigationController?.popViewController(animated: true) navigationController?.popViewController(animated: true)
} }
/// 沿 presentation 链找到当前最顶层控制器,避免 Sheet 已展示时 present 冲突。
func topMostPresentedViewController() -> UIViewController {
var top: UIViewController = self
while let presented = top.presentedViewController {
top = presented
}
return top
}
/// 在当前可见 presentation 链顶端弹出页面。
func presentOnTop(
_ viewController: UIViewController,
animated: Bool = true,
completion: (() -> Void)? = nil
) {
topMostPresentedViewController().present(viewController, animated: animated, completion: completion)
}
/// 全屏预览网络图片。
func presentImagePreview(imageURLs: [String], startIndex: Int) {
guard !imageURLs.isEmpty else { return }
presentOnTop(ImagePreviewViewController(imageURLs: imageURLs, startIndex: startIndex))
}
// MARK: - Notifications // MARK: - Notifications
private func registerBaseNotifications() { private func registerBaseNotifications() {
@@ -16,7 +16,6 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa
private let loadLeads: (OrderSourcePerson) async -> Void private let loadLeads: (OrderSourcePerson) async -> Void
private let onLeadBound: (OrderSourceSelection) -> Void private let onLeadBound: (OrderSourceSelection) -> Void
private let onCallPhone: (String) -> Void private let onCallPhone: (String) -> Void
private let onPreviewImages: ([String], Int) -> Void
private let phoneRow = UIStackView() private let phoneRow = UIStackView()
private let phoneLabel = UILabel() private let phoneLabel = UILabel()
@@ -32,8 +31,7 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa
referralOrder: BoundReferralOrderEntity?, referralOrder: BoundReferralOrderEntity?,
loadLeads: @escaping (OrderSourcePerson) async -> Void, loadLeads: @escaping (OrderSourcePerson) async -> Void,
onLeadBound: @escaping (OrderSourceSelection) -> Void, onLeadBound: @escaping (OrderSourceSelection) -> Void,
onCallPhone: @escaping (String) -> Void, onCallPhone: @escaping (String) -> Void
onPreviewImages: @escaping ([String], Int) -> Void
) { ) {
self.person = person self.person = person
self.orderNumber = orderNumber self.orderNumber = orderNumber
@@ -42,7 +40,6 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa
self.loadLeads = loadLeads self.loadLeads = loadLeads
self.onLeadBound = onLeadBound self.onLeadBound = onLeadBound
self.onCallPhone = onCallPhone self.onCallPhone = onCallPhone
self.onPreviewImages = onPreviewImages
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
} }
@@ -178,7 +175,9 @@ final class OrderSourceLeadListViewController: BaseViewController, UITableViewDa
&& currentSelection?.lead.key == lead.key && currentSelection?.lead.key == lead.key
cell.configure(lead: lead, selected: selected) cell.configure(lead: lead, selected: selected)
cell.onCallPhone = onCallPhone cell.onCallPhone = onCallPhone
cell.onImageTap = onPreviewImages cell.onImageTap = { [weak self] urls, index in
self?.presentImagePreview(imageURLs: urls, startIndex: index)
}
cell.onSelect = { [weak self] in cell.onSelect = { [weak self] in
guard let self else { return } guard let self else { return }
let selection = OrderSourceSelection(person: self.person, lead: lead) let selection = OrderSourceSelection(person: self.person, lead: lead)
@@ -15,7 +15,6 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo
private let loadLeads: (OrderSourcePerson) async -> Void private let loadLeads: (OrderSourcePerson) async -> Void
private let onLeadBound: (OrderSourceSelection) -> Void private let onLeadBound: (OrderSourceSelection) -> Void
private let onCallPhone: (String) -> Void private let onCallPhone: (String) -> Void
private let onPreviewImages: ([String], Int) -> Void
private let titleLabel = UILabel() private let titleLabel = UILabel()
private let subtitleLabel = UILabel() private let subtitleLabel = UILabel()
@@ -29,8 +28,7 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo
referralOrder: BoundReferralOrderEntity?, referralOrder: BoundReferralOrderEntity?,
loadLeads: @escaping (OrderSourcePerson) async -> Void, loadLeads: @escaping (OrderSourcePerson) async -> Void,
onLeadBound: @escaping (OrderSourceSelection) -> Void, onLeadBound: @escaping (OrderSourceSelection) -> Void,
onCallPhone: @escaping (String) -> Void, onCallPhone: @escaping (String) -> Void
onPreviewImages: @escaping ([String], Int) -> Void
) { ) {
self.orderNumber = orderNumber self.orderNumber = orderNumber
self.viewModel = viewModel self.viewModel = viewModel
@@ -38,7 +36,6 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo
self.loadLeads = loadLeads self.loadLeads = loadLeads
self.onLeadBound = onLeadBound self.onLeadBound = onLeadBound
self.onCallPhone = onCallPhone self.onCallPhone = onCallPhone
self.onPreviewImages = onPreviewImages
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
} }
@@ -157,8 +154,7 @@ final class OrderSourcePickerViewController: UIViewController, UITableViewDataSo
referralOrder: referralOrder, referralOrder: referralOrder,
loadLeads: loadLeads, loadLeads: loadLeads,
onLeadBound: onLeadBound, onLeadBound: onLeadBound,
onCallPhone: onCallPhone, onCallPhone: onCallPhone
onPreviewImages: onPreviewImages
) )
navigationController?.setNavigationBarHidden(false, animated: true) navigationController?.setNavigationBarHidden(false, animated: true)
navigationController?.pushViewController(leadController, animated: true) navigationController?.pushViewController(leadController, animated: true)
@@ -377,7 +377,7 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT
self?.presentOrderSourcePicker(for: order) self?.presentOrderSourcePicker(for: order)
} }
actions.onOrderSourceImageTap = { [weak self] images, index in actions.onOrderSourceImageTap = { [weak self] images, index in
self?.presentImagePreview(images: images, startIndex: index) self?.presentImagePreview(imageURLs: images, startIndex: index)
} }
if let travel = order.photoTravel, travel.canGiftRetouch { if let travel = order.photoTravel, travel.canGiftRetouch {
actions.onSendGift = { [weak self] in actions.onSendGift = { [weak self] in
@@ -492,9 +492,6 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT
}, },
onCallPhone: { [weak self] phone in onCallPhone: { [weak self] phone in
self?.callPhone(phone) self?.callPhone(phone)
},
onPreviewImages: { [weak self] urls, index in
self?.presentImagePreview(images: urls, startIndex: index)
} }
) )
self.orderSourcePicker = controller self.orderSourcePicker = controller
@@ -524,9 +521,4 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT
guard !trimmed.isEmpty, let url = URL(string: "tel://\(trimmed)") else { return } guard !trimmed.isEmpty, let url = URL(string: "tel://\(trimmed)") else { return }
UIApplication.shared.open(url) UIApplication.shared.open(url)
} }
private func presentImagePreview(images: [String], startIndex: Int) {
guard !images.isEmpty else { return }
present(ImagePreviewViewController(imageURLs: images, startIndex: startIndex), animated: true)
}
} }