PadXcode-iPad/Git/GitCallbackHandler.swift
2026-04-12 00:46:30 -07:00

74 lines
3.5 KiB
Swift

import Foundation
import UIKit
@MainActor
final class GitCallbackHandler {
private let store: GitStore
init(store: GitStore) { self.store = store }
func handle(url: URL) {
guard url.scheme == "padxcode", url.host == "git-callback" else { return }
let params = parseQuery(url)
store.pendingOperation = nil
switch params["action"] ?? "" {
case "repos": handleRepos(params)
case "status": handleStatus(params)
case "log": handleLog(params)
case "branches": handleBranches(params)
case "checkout": NotificationCenter.default.post(name: .gitCheckoutCompleted, object: nil)
case "commit": store.fileStatuses = []; NotificationCenter.default.post(name: .gitCommitCompleted, object: nil)
case "push": NotificationCenter.default.post(name: .gitPushCompleted, object: nil)
case "pull","fetch": NotificationCenter.default.post(name: .gitSyncCompleted, object: nil)
case "merge": NotificationCenter.default.post(name: .gitMergeCompleted, object: nil)
case "write": NotificationCenter.default.post(name: .gitWriteCompleted, object: nil)
case "read": handleRead(params)
case "error":
let msg = params["errorMessage"] ?? "Working Copy error."
store.lastError = msg
NotificationCenter.default.post(name: .gitOperationFailed, object: nil,
userInfo: ["message": msg])
default: break
}
}
private func handleRepos(_ p: [String: String]) {
guard let json = extractJSON(p),
let repos = try? JSONDecoder().decode([GitRepository].self, from: json) else { return }
store.repositories = repos
}
private func handleStatus(_ p: [String: String]) {
guard let json = extractJSON(p),
let statuses = try? JSONDecoder().decode([GitFileStatus].self, from: json) else { return }
store.fileStatuses = statuses.filter { $0.status != "unchanged" }
}
private func handleLog(_ p: [String: String]) {
guard let json = extractJSON(p),
let commits = try? JSONDecoder().decode([GitCommit].self, from: json) else { return }
store.commitLog = commits
}
private func handleBranches(_ p: [String: String]) {
guard let json = extractJSON(p),
let branches = try? JSONDecoder().decode([GitBranch].self, from: json) else { return }
store.branches = branches
if let current = branches.first(where: { !$0.isRemote }) { store.currentBranch = current.name }
}
private func handleRead(_ p: [String: String]) {
guard let repo = p["repo"], let path = p["path"], let text = p["text"] else { return }
let decoded = text.removingPercentEncoding ?? text
NotificationCenter.default.post(name: .gitReadCompleted, object: nil,
userInfo: ["repo": repo, "path": path, "content": decoded])
}
private func extractJSON(_ params: [String: String]) -> Data? {
let raw = params[""] ?? params["text"] ?? ""
return (raw.removingPercentEncoding ?? raw).data(using: .utf8)
}
private func parseQuery(_ url: URL) -> [String: String] {
guard let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems
else { return [:] }
var result: [String: String] = [:]
for item in items { result[item.name] = item.value ?? "" }
return result
}
}