完善 OTG 相机有线传图:支持 Sony/Canon 自动识别,页面 detach 保持会话以便再次进入复连。
引入进程级 CameraTetheringSession 与共享 USB Browser;离开传图页仅取消 UI 回调,App 终止时再完整 shutdown 释放 PTP 与 Browser 资源。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -16,6 +16,7 @@ struct WiredCameraTransferView: View {
|
||||
@Environment(\.ossUploadService) private var ossUploadService
|
||||
@EnvironmentObject private var toastCenter: ToastCenter
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
|
||||
@StateObject private var viewModel: WiredCameraTransferViewModel
|
||||
@State private var previewSources: [String]?
|
||||
@ -26,7 +27,7 @@ struct WiredCameraTransferView: View {
|
||||
_viewModel = StateObject(
|
||||
wrappedValue: WiredCameraTransferViewModel(
|
||||
context: context,
|
||||
cameraService: CameraServiceFactory.make(brand: .sony)
|
||||
cameraService: CameraServiceFactory.makeAutoDetect()
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -50,6 +51,7 @@ struct WiredCameraTransferView: View {
|
||||
deviceStorageInfo: viewModel.deviceStorageInfo,
|
||||
isCameraConnected: viewModel.isCameraConnected,
|
||||
isRefreshingCameraFiles: viewModel.isRefreshingCameraFiles,
|
||||
isSearchingCamera: viewModel.isSearchingCamera,
|
||||
cameraDeviceName: viewModel.cameraDeviceName,
|
||||
transferModeOption: viewModel.transferModeOption,
|
||||
tabTitles: tabTitles,
|
||||
@ -103,7 +105,11 @@ struct WiredCameraTransferView: View {
|
||||
)
|
||||
}
|
||||
.onDisappear {
|
||||
Task { await viewModel.stop() }
|
||||
viewModel.detachFromUI()
|
||||
}
|
||||
.onChange(of: scenePhase) { phase in
|
||||
guard phase == .active, !viewModel.isCameraConnected else { return }
|
||||
Task { await viewModel.restartCameraSearch() }
|
||||
}
|
||||
.onChange(of: viewModel.errorMessage) { message in
|
||||
guard let message, !message.isEmpty else { return }
|
||||
|
||||
@ -11,6 +11,7 @@ struct WiredTransferControlCard: View {
|
||||
let deviceStorageInfo: DeviceStorageSnapshot
|
||||
let isCameraConnected: Bool
|
||||
let isRefreshingCameraFiles: Bool
|
||||
let isSearchingCamera: Bool
|
||||
let cameraDeviceName: String
|
||||
let transferModeOption: String
|
||||
let tabTitles: [String]
|
||||
@ -130,19 +131,20 @@ struct WiredTransferControlCard: View {
|
||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(!isCameraConnected || isRefreshingCameraFiles)
|
||||
.opacity(isCameraConnected && !isRefreshingCameraFiles ? 1 : 0.85)
|
||||
.disabled(isRefreshingCameraFiles || isSearchingCamera)
|
||||
.opacity(isRefreshingCameraFiles || isSearchingCamera ? 0.85 : 1)
|
||||
}
|
||||
|
||||
private var refreshButtonTitle: String {
|
||||
if isSearchingCamera { return "搜索中" }
|
||||
if isRefreshingCameraFiles { return "读取中" }
|
||||
if isCameraConnected { return "刷新" }
|
||||
return "等待连接"
|
||||
return "重新搜索"
|
||||
}
|
||||
|
||||
private var refreshButtonColor: Color {
|
||||
if !isCameraConnected { return WiredTransferDesign.danger }
|
||||
if isRefreshingCameraFiles { return WiredTransferDesign.text999 }
|
||||
if isSearchingCamera || isRefreshingCameraFiles { return WiredTransferDesign.text999 }
|
||||
if !isCameraConnected { return AppDesign.primary }
|
||||
return AppDesign.primary
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user