feat: Ipad app production readiness, Colony orchestration, Social posting (#44)
#38 Ipad app production readiness, Colony orchestration, Social posting Co-authored-by: Sayan Datta <sayan@Sayans-MacBook-Air.local> Reviewed-on: #44
This commit was merged in pull request #44.
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
struct VelocityVaultShareAsset {
|
||||
let leadId: String?
|
||||
let assetName: String
|
||||
let assetType: String
|
||||
let storagePath: String?
|
||||
|
||||
var isShareable: Bool {
|
||||
leadId?.trimmedNonEmpty != nil && storagePath?.trimmedNonEmpty != nil
|
||||
}
|
||||
}
|
||||
|
||||
extension URL {
|
||||
var velocityStoragePath: String {
|
||||
let cleaned = path.trimmingCharacters(in: CharacterSet(charactersIn: "/"))
|
||||
if cleaned.hasPrefix("assets/") {
|
||||
return String(cleaned.dropFirst("assets/".count))
|
||||
}
|
||||
return cleaned
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func vaultSwipeToShare(asset: VelocityVaultShareAsset?) -> some View {
|
||||
modifier(VaultSwipeToShareModifier(asset: asset))
|
||||
}
|
||||
}
|
||||
|
||||
private struct VaultSwipeToShareModifier: ViewModifier {
|
||||
@State private var appStore = AppStore.shared
|
||||
let asset: VelocityVaultShareAsset?
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.overlay {
|
||||
ThreeFingerSwipeUpRecognizer {
|
||||
Task { await shareAsset() }
|
||||
}
|
||||
.allowsHitTesting(asset != nil)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func shareAsset() async {
|
||||
guard let asset else { return }
|
||||
guard let leadId = asset.leadId?.trimmedNonEmpty,
|
||||
let storagePath = asset.storagePath?.trimmedNonEmpty else {
|
||||
withAnimation(.interactiveSpring(response: 0.35, dampingFraction: 0.86)) {
|
||||
appStore.vaultShareError = "Vault share requires a backend lead and stored asset path."
|
||||
appStore.vaultShareMessage = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
guard let threadId = appStore.activeCommunicationsThreadID?.trimmedNonEmpty else {
|
||||
withAnimation(.interactiveSpring(response: 0.35, dampingFraction: 0.86)) {
|
||||
appStore.vaultShareError = "Open a Communications thread before using Vault Swipe-to-Share."
|
||||
appStore.vaultShareMessage = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
||||
do {
|
||||
let link = try await VelocityAPIClient.shared.generateVaultLink(
|
||||
leadId: leadId,
|
||||
assetName: asset.assetName,
|
||||
assetType: asset.assetType,
|
||||
storagePath: storagePath
|
||||
)
|
||||
_ = try await VelocityAPIClient.shared.sendCommsMessage(
|
||||
threadId: threadId,
|
||||
body: "Secure Velocity Vault link: \(link.vaultUrl)"
|
||||
)
|
||||
withAnimation(.interactiveSpring(response: 0.42, dampingFraction: 0.82)) {
|
||||
appStore.vaultShareMessage = "Vault link shared to the active thread."
|
||||
appStore.vaultShareError = nil
|
||||
}
|
||||
} catch {
|
||||
withAnimation(.interactiveSpring(response: 0.35, dampingFraction: 0.86)) {
|
||||
appStore.vaultShareError = error.localizedDescription
|
||||
appStore.vaultShareMessage = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct ThreeFingerSwipeUpRecognizer: UIViewRepresentable {
|
||||
let onSwipe: () -> Void
|
||||
|
||||
func makeUIView(context: Context) -> UIView {
|
||||
let view = UIView(frame: .zero)
|
||||
view.backgroundColor = .clear
|
||||
let recognizer = UISwipeGestureRecognizer(
|
||||
target: context.coordinator,
|
||||
action: #selector(Coordinator.didSwipe(_:))
|
||||
)
|
||||
recognizer.direction = .up
|
||||
recognizer.numberOfTouchesRequired = 3
|
||||
view.addGestureRecognizer(recognizer)
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIView, context: Context) {}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(onSwipe: onSwipe)
|
||||
}
|
||||
|
||||
final class Coordinator: NSObject {
|
||||
let onSwipe: () -> Void
|
||||
|
||||
init(onSwipe: @escaping () -> Void) {
|
||||
self.onSwipe = onSwipe
|
||||
}
|
||||
|
||||
@objc func didSwipe(_ recognizer: UISwipeGestureRecognizer) {
|
||||
guard recognizer.state == .ended else { return }
|
||||
onSwipe()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension String {
|
||||
var trimmedNonEmpty: String? {
|
||||
let value = trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return value.isEmpty ? nil : value
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user