mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 16:05:19 +00:00
Add macOS photo picker support
- Added MacImagePickerView with NSOpenPanel for macOS - macOS shows photo.circle.fill icon (no camera hardware) - Opens native file picker for images (.png, .jpeg, .heic) - Images processed through ImageUtils with EXIF stripping - Simple sheet with Select/Cancel buttons Cross-platform photo sharing now works: - iOS: Tap for library, long-press for camera - macOS: Tap for file picker
This commit is contained in:
+23563
-23409
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,8 @@ struct ContentView: View {
|
|||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
@State private var showImagePicker = false
|
@State private var showImagePicker = false
|
||||||
@State private var imagePickerSourceType: UIImagePickerController.SourceType = .camera
|
@State private var imagePickerSourceType: UIImagePickerController.SourceType = .camera
|
||||||
|
#else
|
||||||
|
@State private var showMacImagePicker = false
|
||||||
#endif
|
#endif
|
||||||
@ScaledMetric(relativeTo: .body) private var headerHeight: CGFloat = 44
|
@ScaledMetric(relativeTo: .body) private var headerHeight: CGFloat = 44
|
||||||
@ScaledMetric(relativeTo: .subheadline) private var headerPeerIconSize: CGFloat = 11
|
@ScaledMetric(relativeTo: .subheadline) private var headerPeerIconSize: CGFloat = 11
|
||||||
@@ -225,6 +227,25 @@ struct ContentView: View {
|
|||||||
.presentationDragIndicator(.hidden)
|
.presentationDragIndicator(.hidden)
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
.sheet(isPresented: $showMacImagePicker) {
|
||||||
|
MacImagePickerView { url in
|
||||||
|
showMacImagePicker = false
|
||||||
|
if let url = url {
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
let processedURL = try ImageUtils.processImage(at: url)
|
||||||
|
await MainActor.run {
|
||||||
|
viewModel.sendImage(from: processedURL)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
SecureLogger.error("Image processing failed: \(error)", category: .session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
.sheet(isPresented: Binding(
|
.sheet(isPresented: Binding(
|
||||||
get: { imagePreviewURL != nil },
|
get: { imagePreviewURL != nil },
|
||||||
@@ -1825,10 +1846,14 @@ private extension ContentView {
|
|||||||
}
|
}
|
||||||
.accessibilityLabel("Tap for library, long press for camera")
|
.accessibilityLabel("Tap for library, long press for camera")
|
||||||
#else
|
#else
|
||||||
Image(systemName: "camera.circle.fill")
|
Button(action: { showMacImagePicker = true }) {
|
||||||
.font(.bitchatSystem(size: 24))
|
Image(systemName: "photo.circle.fill")
|
||||||
.foregroundColor(composerAccentColor)
|
.font(.bitchatSystem(size: 24))
|
||||||
.frame(width: 36, height: 36)
|
.foregroundColor(composerAccentColor)
|
||||||
|
.frame(width: 36, height: 36)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.accessibilityLabel("Choose photo")
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2187,3 +2212,41 @@ struct ImagePickerView: UIViewControllerRepresentable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
// MARK: - macOS Image Picker
|
||||||
|
struct MacImagePickerView: View {
|
||||||
|
let completion: (URL?) -> Void
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 16) {
|
||||||
|
Text("Choose an image")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
Button("Select Image") {
|
||||||
|
let panel = NSOpenPanel()
|
||||||
|
panel.allowsMultipleSelection = false
|
||||||
|
panel.canChooseDirectories = false
|
||||||
|
panel.canChooseFiles = true
|
||||||
|
panel.allowedContentTypes = [.image, .png, .jpeg, .heic]
|
||||||
|
panel.message = "Choose an image to send"
|
||||||
|
|
||||||
|
if panel.runModal() == .OK {
|
||||||
|
completion(panel.url)
|
||||||
|
} else {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderedProminent)
|
||||||
|
|
||||||
|
Button("Cancel") {
|
||||||
|
completion(nil)
|
||||||
|
}
|
||||||
|
.buttonStyle(.bordered)
|
||||||
|
}
|
||||||
|
.padding(40)
|
||||||
|
.frame(minWidth: 300, minHeight: 150)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user