Add native iOS notifications (#64)

This commit is contained in:
Georg Bauer
2026-08-15 12:50:05 +02:00
parent 69d1709523
commit 8ba7f5ad39
23 changed files with 1561 additions and 22 deletions

View File

@@ -649,6 +649,12 @@ public protocol GotchaCoreProtocol: AnyObject, Sendable {
func setMilestoneClosed(owner: String, repository: String, id: Int64, closed: Bool) async throws
func markNotificationRead(serverId: String, id: Int64) async throws
func notifications(status: NotificationStatus, page: UInt32) async throws -> NotificationListPage
func pollNotifications() async throws -> [NotificationRow]
func clearPullFilters() throws
func pull(owner: String, repository: String, number: Int64, page: UInt32) async throws -> PullPage
@@ -685,6 +691,8 @@ public protocol GotchaCoreProtocol: AnyObject, Sendable {
func setIssueStatus(status: String) throws
func setNotificationsEnabled(enabled: Bool) throws
func setPullStatus(status: String) throws
func settings() -> Settings
@@ -1114,6 +1122,54 @@ open func setMilestoneClosed(owner: String, repository: String, id: Int64, close
)
}
open func markNotificationRead(serverId: String, id: Int64)async throws {
return
try await uniffiRustCallAsync(
rustFutureFunc: {
uniffi_gotcha_core_fn_method_gotchacore_mark_notification_read(
self.uniffiCloneHandle(),FfiConverterString.lower(serverId),FfiConverterInt64.lower(id)
)
},
pollFunc: ffi_gotcha_core_rust_future_poll_void,
completeFunc: ffi_gotcha_core_rust_future_complete_void,
freeFunc: ffi_gotcha_core_rust_future_free_void,
liftFunc: { $0 },
errorHandler: FfiConverterTypeGotchaError_lift
)
}
open func notifications(status: NotificationStatus, page: UInt32)async throws -> NotificationListPage {
return
try await uniffiRustCallAsync(
rustFutureFunc: {
uniffi_gotcha_core_fn_method_gotchacore_notifications(
self.uniffiCloneHandle(),FfiConverterTypeNotificationStatus_lower(status),FfiConverterUInt32.lower(page)
)
},
pollFunc: ffi_gotcha_core_rust_future_poll_rust_buffer,
completeFunc: ffi_gotcha_core_rust_future_complete_rust_buffer,
freeFunc: ffi_gotcha_core_rust_future_free_rust_buffer,
liftFunc: FfiConverterTypeNotificationListPage_lift,
errorHandler: FfiConverterTypeGotchaError_lift
)
}
open func pollNotifications()async throws -> [NotificationRow] {
return
try await uniffiRustCallAsync(
rustFutureFunc: {
uniffi_gotcha_core_fn_method_gotchacore_poll_notifications(
self.uniffiCloneHandle()
)
},
pollFunc: ffi_gotcha_core_rust_future_poll_rust_buffer,
completeFunc: ffi_gotcha_core_rust_future_complete_rust_buffer,
freeFunc: ffi_gotcha_core_rust_future_free_rust_buffer,
liftFunc: FfiConverterSequenceTypeNotificationRow.lift,
errorHandler: FfiConverterTypeGotchaError_lift
)
}
open func clearPullFilters()throws {try rustCallWithError(FfiConverterTypeGotchaError_lift) {
uniffiCallStatus in
uniffi_gotcha_core_fn_method_gotchacore_clear_pull_filters(
@@ -1329,6 +1385,15 @@ open func setIssueStatus(status: String)throws {try rustCallWithError(FfiConve
}
}
open func setNotificationsEnabled(enabled: Bool)throws {try rustCallWithError(FfiConverterTypeGotchaError_lift) {
uniffiCallStatus in
uniffi_gotcha_core_fn_method_gotchacore_set_notifications_enabled(
self.uniffiCloneHandle(),
FfiConverterBool.lower(enabled),uniffiCallStatus
)
}
}
open func setPullStatus(status: String)throws {try rustCallWithError(FfiConverterTypeGotchaError_lift) {
uniffiCallStatus in
uniffi_gotcha_core_fn_method_gotchacore_set_pull_status(
@@ -2988,6 +3053,150 @@ public func FfiConverterTypeMilestoneRow_lower(_ value: MilestoneRow) -> RustBuf
}
public struct NotificationListPage: Equatable, Hashable {
public var rows: [NotificationRow]
public var hasMore: Bool
// Default memberwise initializers are never public by default, so we
// declare one manually.
public init(rows: [NotificationRow], hasMore: Bool) {
self.rows = rows
self.hasMore = hasMore
}
}
#if compiler(>=6)
extension NotificationListPage: Sendable {}
#endif
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeNotificationListPage: FfiConverterRustBuffer {
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NotificationListPage {
return
try NotificationListPage(
rows: FfiConverterSequenceTypeNotificationRow.read(from: &buf),
hasMore: FfiConverterBool.read(from: &buf)
)
}
public static func write(_ value: NotificationListPage, into buf: inout [UInt8]) {
FfiConverterSequenceTypeNotificationRow.write(value.rows, into: &buf)
FfiConverterBool.write(value.hasMore, into: &buf)
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeNotificationListPage_lift(_ buf: RustBuffer) throws -> NotificationListPage {
return try FfiConverterTypeNotificationListPage.lift(buf)
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeNotificationListPage_lower(_ value: NotificationListPage) -> RustBuffer {
return FfiConverterTypeNotificationListPage.lower(value)
}
public struct NotificationRow: Equatable, Hashable {
public var id: Int64
public var serverId: String
public var title: String
public var detail: String
public var meta: String
public var unread: Bool
public var target: ActivityTargetKind
public var owner: String
public var repository: String
public var number: Int64
public var sha: String
// Default memberwise initializers are never public by default, so we
// declare one manually.
public init(id: Int64, serverId: String, title: String, detail: String, meta: String, unread: Bool, target: ActivityTargetKind, owner: String, repository: String, number: Int64, sha: String) {
self.id = id
self.serverId = serverId
self.title = title
self.detail = detail
self.meta = meta
self.unread = unread
self.target = target
self.owner = owner
self.repository = repository
self.number = number
self.sha = sha
}
}
#if compiler(>=6)
extension NotificationRow: Sendable {}
#endif
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeNotificationRow: FfiConverterRustBuffer {
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NotificationRow {
return
try NotificationRow(
id: FfiConverterInt64.read(from: &buf),
serverId: FfiConverterString.read(from: &buf),
title: FfiConverterString.read(from: &buf),
detail: FfiConverterString.read(from: &buf),
meta: FfiConverterString.read(from: &buf),
unread: FfiConverterBool.read(from: &buf),
target: FfiConverterTypeActivityTargetKind.read(from: &buf),
owner: FfiConverterString.read(from: &buf),
repository: FfiConverterString.read(from: &buf),
number: FfiConverterInt64.read(from: &buf),
sha: FfiConverterString.read(from: &buf)
)
}
public static func write(_ value: NotificationRow, into buf: inout [UInt8]) {
FfiConverterInt64.write(value.id, into: &buf)
FfiConverterString.write(value.serverId, into: &buf)
FfiConverterString.write(value.title, into: &buf)
FfiConverterString.write(value.detail, into: &buf)
FfiConverterString.write(value.meta, into: &buf)
FfiConverterBool.write(value.unread, into: &buf)
FfiConverterTypeActivityTargetKind.write(value.target, into: &buf)
FfiConverterString.write(value.owner, into: &buf)
FfiConverterString.write(value.repository, into: &buf)
FfiConverterInt64.write(value.number, into: &buf)
FfiConverterString.write(value.sha, into: &buf)
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeNotificationRow_lift(_ buf: RustBuffer) throws -> NotificationRow {
return try FfiConverterTypeNotificationRow.lift(buf)
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeNotificationRow_lower(_ value: NotificationRow) -> RustBuffer {
return FfiConverterTypeNotificationRow.lower(value)
}
public struct PullFilterOptions: Equatable, Hashable {
public var milestones: [String]
public var selectedMilestone: String
@@ -3620,13 +3829,15 @@ public struct Settings: Equatable, Hashable {
public var issueStatus: String
public var pullStatus: String
public var appearance: UInt32
public var notificationsEnabled: Bool
// Default memberwise initializers are never public by default, so we
// declare one manually.
public init(issueStatus: String, pullStatus: String, appearance: UInt32) {
public init(issueStatus: String, pullStatus: String, appearance: UInt32, notificationsEnabled: Bool) {
self.issueStatus = issueStatus
self.pullStatus = pullStatus
self.appearance = appearance
self.notificationsEnabled = notificationsEnabled
}
@@ -3647,7 +3858,8 @@ public struct FfiConverterTypeSettings: FfiConverterRustBuffer {
try Settings(
issueStatus: FfiConverterString.read(from: &buf),
pullStatus: FfiConverterString.read(from: &buf),
appearance: FfiConverterUInt32.read(from: &buf)
appearance: FfiConverterUInt32.read(from: &buf),
notificationsEnabled: FfiConverterBool.read(from: &buf)
)
}
@@ -3655,6 +3867,7 @@ public struct FfiConverterTypeSettings: FfiConverterRustBuffer {
FfiConverterString.write(value.issueStatus, into: &buf)
FfiConverterString.write(value.pullStatus, into: &buf)
FfiConverterUInt32.write(value.appearance, into: &buf)
FfiConverterBool.write(value.notificationsEnabled, into: &buf)
}
}
@@ -4206,6 +4419,72 @@ public func FfiConverterTypeHomeActivityFilter_lower(_ value: HomeActivityFilter
public enum NotificationStatus: Equatable, Hashable {
case `open`
case closed
}
#if compiler(>=6)
extension NotificationStatus: Sendable {}
#endif
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public struct FfiConverterTypeNotificationStatus: FfiConverterRustBuffer {
typealias SwiftType = NotificationStatus
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> NotificationStatus {
let variant: Int32 = try readInt(&buf)
switch variant {
case 1: return .`open`
case 2: return .closed
default: throw UniffiInternalError.unexpectedEnumCase
}
}
public static func write(_ value: NotificationStatus, into buf: inout [UInt8]) {
switch value {
case .`open`:
writeInt(&buf, Int32(1))
case .closed:
writeInt(&buf, Int32(2))
}
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeNotificationStatus_lift(_ buf: RustBuffer) throws -> NotificationStatus {
return try FfiConverterTypeNotificationStatus.lift(buf)
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
public func FfiConverterTypeNotificationStatus_lower(_ value: NotificationStatus) -> RustBuffer {
return FfiConverterTypeNotificationStatus.lower(value)
}
public enum RepositoryContentKind: Equatable, Hashable {
case directory
@@ -5002,6 +5281,31 @@ fileprivate struct FfiConverterSequenceTypeMilestoneRow: FfiConverterRustBuffer
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
fileprivate struct FfiConverterSequenceTypeNotificationRow: FfiConverterRustBuffer {
typealias SwiftType = [NotificationRow]
public static func write(_ value: [NotificationRow], into buf: inout [UInt8]) {
let len = Int32(value.count)
writeInt(&buf, len)
for item in value {
FfiConverterTypeNotificationRow.write(item, into: &buf)
}
}
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [NotificationRow] {
let len: Int32 = try readInt(&buf)
var seq = [NotificationRow]()
seq.reserveCapacity(Int(len))
for _ in 0 ..< len {
seq.append(try FfiConverterTypeNotificationRow.read(from: &buf))
}
return seq
}
}
#if swift(>=5.8)
@_documentation(visibility: private)
#endif
@@ -5234,6 +5538,15 @@ private let initializationResult: InitializationResult = {
if (uniffi_gotcha_core_checksum_method_gotchacore_set_milestone_closed() != 33) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_mark_notification_read() != 39536) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_notifications() != 58813) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_poll_notifications() != 21038) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_clear_pull_filters() != 61566) {
return InitializationResult.apiChecksumMismatch
}
@@ -5288,6 +5601,9 @@ private let initializationResult: InitializationResult = {
if (uniffi_gotcha_core_checksum_method_gotchacore_set_issue_status() != 5573) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_set_notifications_enabled() != 13019) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_set_pull_status() != 40421) {
return InitializationResult.apiChecksumMismatch
}