GiteaPR: native iOS app to manage Gitea pull requests
Build iOS App / Build .ipa and publish source (push) Failing after 35s
Build iOS App / Build .ipa and publish source (push) Failing after 35s
Multi-repo PR inbox, review (approve/request changes/comment), merge with gating toggle, read-only diff viewer, and Gitea Actions check status with one-tap re-run. Ships unsigned via the iMac runner to the SideStore source.
This commit is contained in:
commit
1025634978
27 files changed
+2322
No files matched your search
@@ -0,0 +1,129 @@
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var instanceURL: String
|
||||
@State private var token: String
|
||||
@State private var mergeGateMode: MergeGateMode
|
||||
@State private var testResult: TestResult?
|
||||
@State private var testing = false
|
||||
@State private var showLogoutConfirm = false
|
||||
|
||||
enum TestResult: Equatable {
|
||||
case success(String)
|
||||
case failure(String)
|
||||
}
|
||||
|
||||
init() {
|
||||
_instanceURL = State(initialValue: SettingsStore.shared.instanceURL)
|
||||
_token = State(initialValue: SettingsStore.shared.token)
|
||||
_mergeGateMode = State(initialValue: SettingsStore.shared.mergeGateMode)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Form {
|
||||
Section("Server") {
|
||||
TextField("Instance URL", text: $instanceURL)
|
||||
.keyboardType(.URL)
|
||||
.autocapitalization(.none)
|
||||
.autocorrectionDisabled()
|
||||
.textInputAutocapitalization(.never)
|
||||
SecureField("Personal access token", text: $token)
|
||||
Button(testing ? "Testing…" : "Test connection") {
|
||||
test()
|
||||
}
|
||||
.disabled(testing || token.isEmpty)
|
||||
if let testResult {
|
||||
testResultView(testResult)
|
||||
}
|
||||
}
|
||||
|
||||
Section("Merge gating") {
|
||||
Picker("Merge behavior", selection: $mergeGateMode) {
|
||||
ForEach(MergeGateMode.allCases) { m in
|
||||
Text(m.rawValue).tag(m)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.inline)
|
||||
Text("Warn mode shows CI status and allows merging a red PR after confirmation. Block mode disables merge while any check is failing.")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
Section {
|
||||
Button("Log out", role: .destructive) {
|
||||
showLogoutConfirm = true
|
||||
}
|
||||
.disabled(token.isEmpty)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Settings")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Cancel") { dismiss() }
|
||||
}
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button("Save") { save() }
|
||||
.disabled(instanceURL.trimmingCharacters(in: .whitespaces)
|
||||
.isEmpty)
|
||||
}
|
||||
}
|
||||
.confirmationDialog("Log out?",
|
||||
isPresented: $showLogoutConfirm,
|
||||
titleVisibility: .visible) {
|
||||
Button("Log out", role: .destructive) {
|
||||
SettingsStore.shared.logout()
|
||||
testResult = nil
|
||||
dismiss()
|
||||
}
|
||||
Button("Cancel", role: .cancel) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func testResultView(_ result: TestResult) -> some View {
|
||||
switch result {
|
||||
case .success(let login):
|
||||
Label("Connected as \(login)", systemImage: "checkmark.circle.fill")
|
||||
.font(.callout)
|
||||
.foregroundColor(.green)
|
||||
case .failure(let message):
|
||||
Label(message, systemImage: "xmark.circle.fill")
|
||||
.font(.callout)
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
|
||||
private func test() {
|
||||
testing = true
|
||||
testResult = nil
|
||||
let trimmed = instanceURL.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard let url = URL(string: trimmed) else {
|
||||
testResult = .failure("Invalid URL")
|
||||
testing = false
|
||||
return
|
||||
}
|
||||
let client = GiteaClient(instanceURL: url, token: token)
|
||||
Task {
|
||||
do {
|
||||
let user = try await client.currentUser()
|
||||
AppSession.currentLogin = user.login
|
||||
testResult = .success(user.login)
|
||||
} catch {
|
||||
testResult = .failure(error.localizedDescription)
|
||||
}
|
||||
testing = false
|
||||
}
|
||||
}
|
||||
|
||||
private func save() {
|
||||
SettingsStore.shared.instanceURL =
|
||||
instanceURL.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
SettingsStore.shared.token = token
|
||||
SettingsStore.shared.mergeGateMode = mergeGateMode
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user