Support Forgejo servers

This commit is contained in:
Georg Bauer
2026-08-03 18:14:21 +02:00
parent 46cca8fdd2
commit d47b21d6a6
15 changed files with 405 additions and 78 deletions

View File

@@ -669,7 +669,7 @@ public protocol GotchaCoreProtocol: AnyObject, Sendable {
func activeServerName() -> String?
func addServer(name: String, url: String, token: String) async throws -> UInt32
func addServer(name: String, url: String, token: String, provider: ServerProvider) async throws -> UInt32
func home(page: UInt32, filter: HomeActivityFilter) async throws -> HomePage
@@ -1224,12 +1224,12 @@ open func activeServerName() -> String? {
})
}
open func addServer(name: String, url: String, token: String)async throws -> UInt32 {
open func addServer(name: String, url: String, token: String, provider: ServerProvider)async throws -> UInt32 {
return
try await uniffiRustCallAsync(
rustFutureFunc: {
uniffi_gotcha_core_fn_method_gotchacore_add_server(
self.uniffiCloneHandle(),FfiConverterString.lower(name),FfiConverterString.lower(url),FfiConverterString.lower(token)
self.uniffiCloneHandle(),FfiConverterString.lower(name),FfiConverterString.lower(url),FfiConverterString.lower(token),FfiConverterTypeServerProvider_lower(provider)
)
},
pollFunc: ffi_gotcha_core_rust_future_poll_u32,
@@ -4163,6 +4163,72 @@ public func FfiConverterTypeRepositoryPane_lower(_ value: RepositoryPane) -> Rus
public enum ServerProvider: Equatable, Hashable {
case gitea
case forgejo
}
#if compiler(>=6)
extension ServerProvider: Sendable {}
#endif
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeServerProvider: FfiConverterRustBuffer {
typealias SwiftType = ServerProvider
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> ServerProvider {
let variant: Int32 = try readInt(&buf)
switch variant {
case 1: return .gitea
case 2: return .forgejo
default: throw UniffiInternalError.unexpectedEnumCase
}
}
public static func write(_ value: ServerProvider, into buf: inout [UInt8]) {
switch value {
case .gitea:
writeInt(&buf, Int32(1))
case .forgejo:
writeInt(&buf, Int32(2))
}
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeServerProvider_lift(_ buf: RustBuffer) throws -> ServerProvider {
return try FfiConverterTypeServerProvider.lift(buf)
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeServerProvider_lower(_ value: ServerProvider) -> RustBuffer {
return FfiConverterTypeServerProvider.lower(value)
}
public enum WorkItemState: Equatable, Hashable {
case `open`
@@ -4943,7 +5009,7 @@ private let initializationResult: InitializationResult = {
if (uniffi_gotcha_core_checksum_method_gotchacore_active_server_name() != 45045) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_add_server() != 8514) {
if (uniffi_gotcha_core_checksum_method_gotchacore_add_server() != 51168) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_home() != 37602) {

View File

@@ -426,7 +426,7 @@ RustBuffer uniffi_gotcha_core_fn_method_gotchacore_active_server_name(uint64_t p
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_ADD_SERVER
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_ADD_SERVER
uint64_t uniffi_gotcha_core_fn_method_gotchacore_add_server(uint64_t ptr, RustBuffer name, RustBuffer url, RustBuffer token
uint64_t uniffi_gotcha_core_fn_method_gotchacore_add_server(uint64_t ptr, RustBuffer name, RustBuffer url, RustBuffer token, RustBuffer provider
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_HOME

View File

@@ -21,7 +21,7 @@ final class ServersViewController: UITableViewController {
servers = context.core.servers()
tableView.reloadData()
tableView.backgroundView = servers.isEmpty
? EmptyBackgroundView(title: "No servers", detail: "Add a Gitea server to get started.")
? EmptyBackgroundView(title: "No servers", detail: "Add a code hosting server to get started.")
: nil
navigationItem.rightBarButtonItem = UIBarButtonItem(
systemItem: .add,
@@ -70,6 +70,8 @@ final class AddServerViewController: UITableViewController, UITextFieldDelegate
private let nameField = UITextField()
private let urlField = UITextField()
private let tokenField = UITextField()
private let providerButton = UIButton(type: .system)
private var provider = ServerProvider.gitea
private var saveButton: UIBarButtonItem!
init(context: AppContext, completion: @escaping () -> Void) {
@@ -103,13 +105,14 @@ final class AddServerViewController: UITableViewController, UITextFieldDelegate
tokenField.isSecureTextEntry = true
tokenField.autocapitalizationType = .none
tokenField.returnKeyType = .done
configureProviderButton()
}
override func numberOfSections(in tableView: UITableView) -> Int { 3 }
override func numberOfSections(in tableView: UITableView) -> Int { 4 }
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 1 }
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
["Name", "Server URL", "Access token"][section]
["API provider", "Name", "Server URL", "Access token"][section]
}
override func tableView(
@@ -117,14 +120,16 @@ final class AddServerViewController: UITableViewController, UITextFieldDelegate
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
let field = [nameField, urlField, tokenField][indexPath.section]
field.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(field)
let control: UIView = indexPath.section == 0
? providerButton
: [nameField, urlField, tokenField][indexPath.section - 1]
control.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.addSubview(control)
NSLayoutConstraint.activate([
field.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: 16),
field.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: -16),
field.topAnchor.constraint(equalTo: cell.contentView.topAnchor),
field.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor),
control.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: 16),
control.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: -16),
control.topAnchor.constraint(equalTo: cell.contentView.topAnchor),
control.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor),
cell.contentView.heightAnchor.constraint(greaterThanOrEqualToConstant: 48),
])
return cell
@@ -148,7 +153,8 @@ final class AddServerViewController: UITableViewController, UITextFieldDelegate
let index = try await context.core.addServer(
name: nameField.text ?? "",
url: urlField.text ?? "",
token: tokenField.text ?? ""
token: tokenField.text ?? "",
provider: provider
)
try context.didAddServer(index: index)
completion()
@@ -174,4 +180,24 @@ final class AddServerViewController: UITableViewController, UITextFieldDelegate
field.adjustsFontForContentSizeCategory = true
field.font = .preferredFont(forTextStyle: .body)
}
private func configureProviderButton() {
providerButton.contentHorizontalAlignment = .leading
providerButton.showsMenuAsPrimaryAction = true
providerButton.changesSelectionAsPrimaryAction = true
providerButton.accessibilityLabel = "API provider"
providerButton.accessibilityValue = "Gitea"
providerButton.menu = UIMenu(options: .singleSelection, children: [
UIAction(title: "Gitea", state: .on) { [weak self] _ in
self?.provider = .gitea
self?.urlField.placeholder = "https://gitea.example.com"
self?.providerButton.accessibilityValue = "Gitea"
},
UIAction(title: "Forgejo") { [weak self] _ in
self?.provider = .forgejo
self?.urlField.placeholder = "https://forgejo.example.com"
self?.providerButton.accessibilityValue = "Forgejo"
},
])
}
}