Files
Kecalek_python/ios_client 0.8.5/Kecalek/Views/Chat/ImageViewerView.swift
2026-03-14 12:43:56 +01:00

114 lines
4.4 KiB
Swift

import SwiftUI
import UIKit
import Photos
struct ImageViewerView: View {
let imageData: Data
@State private var scale: CGFloat = 1.0
@State private var saved = false
@State private var saveError: String?
@Environment(\.dismiss) private var dismiss
var body: some View {
NavigationStack {
GeometryReader { geo in
if let uiImage = UIImage(data: imageData) {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fit)
.scaleEffect(scale)
.gesture(
MagnifyGesture()
.onChanged { value in
scale = value.magnification
}
.onEnded { _ in
withAnimation {
scale = max(1.0, min(scale, 5.0))
}
}
)
.onTapGesture(count: 2) {
withAnimation {
scale = scale > 1 ? 1 : 2
}
}
.frame(width: geo.size.width, height: geo.size.height)
}
}
.overlay(alignment: .bottom) {
if let error = saveError {
Text(error)
.font(.caption)
.foregroundStyle(.white)
.padding(8)
.background(Capsule().fill(.red.opacity(0.8)))
.padding(.bottom, 40)
.transition(.move(edge: .bottom).combined(with: .opacity))
}
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button {
dismiss()
} label: {
Image(systemName: "xmark")
.foregroundStyle(.white)
}
}
ToolbarItem(placement: .topBarTrailing) {
HStack(spacing: 16) {
// Share
if let uiImage = UIImage(data: imageData) {
ShareLink(item: Image(uiImage: uiImage), preview: SharePreview("Image", image: Image(uiImage: uiImage))) {
Image(systemName: "square.and.arrow.up")
.foregroundStyle(.white)
}
}
// Save to Photos
Button {
saveToPhotos()
} label: {
Image(systemName: saved ? "checkmark.circle.fill" : "arrow.down.to.line")
.foregroundStyle(saved ? .green : .white)
}
}
}
}
.toolbarBackground(.hidden, for: .navigationBar)
.background(.black)
}
}
private func saveToPhotos() {
guard let uiImage = UIImage(data: imageData) else {
withAnimation { saveError = "Invalid image data" }
return
}
PHPhotoLibrary.requestAuthorization(for: .addOnly) { status in
DispatchQueue.main.async {
switch status {
case .authorized, .limited:
PHPhotoLibrary.shared().performChanges {
PHAssetChangeRequest.creationRequestForAsset(from: uiImage)
} completionHandler: { success, error in
DispatchQueue.main.async {
if success {
withAnimation { saved = true; saveError = nil }
} else {
withAnimation { saveError = error?.localizedDescription ?? "Save failed" }
}
}
}
case .denied, .restricted:
withAnimation { saveError = "Photo library access denied. Check Settings." }
default:
withAnimation { saveError = "Photo library access required" }
}
}
}
}
}