完善首页权限申请流程与队列播报体验。

对齐 Android 无权限强制弹窗、角色下拉与申请页交互,补充 UIButton configuration 适配,并增强景区排队 TTS 与相关单元测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-14 13:46:45 +08:00
parent c083f1d4b3
commit efb3925257
50 changed files with 2585 additions and 455 deletions

View File

@ -35,10 +35,10 @@ final class HomeViewController: BaseViewController {
collectionViewLayout: HomeCollectionLayoutBuilder.makeLayout(sections: [.commonApps])
)
collectionView.backgroundColor = .clear
collectionView.alwaysBounceVertical = true
collectionView.alwaysBounceHorizontal = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.isDirectionalLockEnabled = true
// collectionView.alwaysBounceVertical = true
// collectionView.alwaysBounceHorizontal = false
// collectionView.showsHorizontalScrollIndicator = false
// collectionView.contentInsetAdjustmentBehavior = .never
// section.contentInsets contentInset
collectionView.contentInset = UIEdgeInsets(
top: AppSpacing.sm,
@ -56,13 +56,13 @@ final class HomeViewController: BaseViewController {
override func setupConstraints() {
scenicHeaderView.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide)
make.leading.trailing.equalToSuperview()
make.height.equalTo(AppSpacing.homeHeaderHeight)
make.top.leading.trailing.equalToSuperview()
make.bottom.equalTo(view.safeAreaLayoutGuide.snp.top).offset(AppSpacing.homeHeaderHeight)
}
collectionView.snp.makeConstraints { make in
make.top.equalTo(scenicHeaderView.snp.bottom)
make.leading.trailing.bottom.equalToSuperview()
make.leading.trailing.equalToSuperview()
make.bottom.equalTo(view.safeAreaLayoutGuide)
}
}
@ -73,7 +73,6 @@ final class HomeViewController: BaseViewController {
viewModel.onShowMessage = { [weak self] message in
Task { @MainActor in self?.showToast(message) }
}
scenicHeaderView.onTap = { [weak self] in self?.presentScenicSelection() }
collectionView.delegate = self
@ -102,7 +101,14 @@ final class HomeViewController: BaseViewController {
hasInitialized = true
Task { await initializeHome() }
} else {
Task { await viewModel.reloadIfNeeded(api: homeAPI) }
Task {
let shouldReevaluateDialogs = viewModel.needsPermissionReload
await viewModel.reloadIfNeeded(api: homeAPI)
if shouldReevaluateDialogs {
await viewModel.evaluateDialogs(api: homeAPI)
applyViewModel()
}
}
}
startCountdownTimer()
}
@ -389,20 +395,34 @@ final class HomeViewController: BaseViewController {
}
private func presentPermissionDialog() {
let alert = UIAlertController(
title: "权限提示",
message: "您还没有权限,请先申请权限",
preferredStyle: .alert
let dialog = PermissionRequiredDialogViewController(
onExitApp: {
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
},
onGoToApply: { [weak self] in
guard let self else { return }
self.activeDialog = nil
Task { await self.openPermissionApplyFlow() }
}
)
alert.addAction(UIAlertAction(title: "取消", style: .cancel) { [weak self] _ in
self?.viewModel.hidePermissionDialog()
self?.activeDialog = nil
})
alert.addAction(UIAlertAction(title: "去申请", style: .default) { [weak self] _ in
self?.showToast("功能开发中")
self?.activeDialog = nil
})
present(alert, animated: true)
present(dialog, animated: true)
}
private func openPermissionApplyFlow() async {
showLoading()
let destination = await viewModel.resolvePermissionApplyDestination(api: homeAPI)
hideLoading()
viewModel.markNeedsPermissionReload()
navigationController?.setNavigationBarHidden(false, animated: true)
switch destination {
case .apply:
navigationController?.pushViewController(PermissionApplyViewController(), animated: true)
case .status(let applyCode):
navigationController?.pushViewController(
PermissionApplyStatusViewController(applyCode: applyCode),
animated: true
)
}
}
private func presentScenicDialog() {