From b865abfd3a63532f787085e580f17755b4cdf3dd Mon Sep 17 00:00:00 2001 From: marchidalgo Date: Fri, 20 Feb 2026 13:09:33 +0100 Subject: [PATCH 1/3] refactor: update InfiniteScrollingDataSource and preview Remove Combine and replace @Published with SwiftUI's @Observable annotations for better performance with SwiftUI 18. Utilize the @ObservationIgnored attribute for non-observable properties. Simplify preview code by removing unnecessary @StateObject and @ObservedObject wrappers, as the @Observable protocol already manages state changes efficiently. --- .../DataSource/InfiniteScrollingDataSource.swift | 15 +++++++-------- .../InfiniteScrollingDataSource+Preview.swift | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift b/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift index 9cabf1b0..6824595b 100644 --- a/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift +++ b/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift @@ -1,16 +1,17 @@ -#if canImport(Darwin) import SwiftUI -import Combine +import Observation /// As of iOS 18 and aligned releases, this is no longer recommended as /// there are cleaner alternatives like `InfiniteVerticalScrollView` @MainActor -open class InfiniteScrollingDataSource: ObservableObject { +@Observable +open class InfiniteScrollingDataSource { - @Published public private(set) var items = [ListItem]() - @Published public private(set) var state: State - @Published public var paginationError: Error? + public private(set) var items = [ListItem]() + public private(set) var state: State + public var paginationError: Error? + @ObservationIgnored private var itemFetcher: ItemFetcher public enum State: Equatable { @@ -106,5 +107,3 @@ open class InfiniteScrollingDataSource: Obser } } } - -#endif diff --git a/Sources/BSWInterfaceKit/SwiftUI/Previews/InfiniteScrollingDataSource+Preview.swift b/Sources/BSWInterfaceKit/SwiftUI/Previews/InfiniteScrollingDataSource+Preview.swift index 2912096a..3d60c4e8 100644 --- a/Sources/BSWInterfaceKit/SwiftUI/Previews/InfiniteScrollingDataSource+Preview.swift +++ b/Sources/BSWInterfaceKit/SwiftUI/Previews/InfiniteScrollingDataSource+Preview.swift @@ -48,7 +48,7 @@ struct InfiniteDataSource_Previews: PreviewProvider { struct ItemListView: View { - @StateObject var dataSource: ItemInfiniteDataSource + var dataSource: ItemInfiniteDataSource var body: some View { List { @@ -67,7 +67,7 @@ struct InfiniteDataSource_Previews: PreviewProvider { struct FooterView: View { - @ObservedObject var dataSource: ItemInfiniteDataSource + var dataSource: ItemInfiniteDataSource var body: some View { HStack(spacing: 8) { From bb5f8eec77c68ab746b7ccbffffdf6fecff8c1d5 Mon Sep 17 00:00:00 2001 From: marchidalgo Date: Fri, 20 Feb 2026 13:59:41 +0100 Subject: [PATCH 2/3] feat: add Android compatibility to InfiniteScrollingDataSource Introduce an Android-compatible static creation method in InfiniteScrollingDataSource for improved support across platforms. This change ensures that the class can be instantiated on Android OS, broadening the potential use cases and facilitating platform- specific adaptations. Adjust the initializer to cater to these specifications while preserving existing functionality. --- .../InfiniteScrollingDataSource.swift | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift b/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift index 6824595b..19f0e00f 100644 --- a/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift +++ b/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift @@ -22,12 +22,28 @@ open class InfiniteScrollingDataSource { public typealias ItemFetcher = (Int) async throws -> ([ListItem], Bool) - public init(currentPage: Int = 0, itemFetcher: @escaping ItemFetcher) async throws { + // SKIP @nobridge + public init( + currentPage: Int = 0, + itemFetcher: @escaping ItemFetcher + ) async throws { self.itemFetcher = itemFetcher self.state = State.canLoadMorePages(currentPage: currentPage) try await loadMoreContent() } + #if os(Android) + public static func create( + currentPage: Int = 0, + itemFetcher: @escaping ItemFetcher + ) async throws -> InfiniteScrollingDataSource { + return try await InfiniteScrollingDataSource( + currentPage: currentPage, + itemFetcher: itemFetcher + ) + } + #endif + public init(mockItems: [ListItem]) { self.items = mockItems self.state = .noMorePages From 0ae37f5e0c2cb0128f985fe4c97d2bcc9031532d Mon Sep 17 00:00:00 2001 From: marchidalgo Date: Fri, 20 Feb 2026 17:26:53 +0100 Subject: [PATCH 3/3] Revert "feat: add Android compatibility to InfiniteScrollingDataSource" This reverts commit bb5f8eec77c68ab746b7ccbffffdf6fecff8c1d5. --- .../InfiniteScrollingDataSource.swift | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift b/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift index 19f0e00f..6824595b 100644 --- a/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift +++ b/Sources/BSWInterfaceKit/SwiftUI/DataSource/InfiniteScrollingDataSource.swift @@ -22,28 +22,12 @@ open class InfiniteScrollingDataSource { public typealias ItemFetcher = (Int) async throws -> ([ListItem], Bool) - // SKIP @nobridge - public init( - currentPage: Int = 0, - itemFetcher: @escaping ItemFetcher - ) async throws { + public init(currentPage: Int = 0, itemFetcher: @escaping ItemFetcher) async throws { self.itemFetcher = itemFetcher self.state = State.canLoadMorePages(currentPage: currentPage) try await loadMoreContent() } - #if os(Android) - public static func create( - currentPage: Int = 0, - itemFetcher: @escaping ItemFetcher - ) async throws -> InfiniteScrollingDataSource { - return try await InfiniteScrollingDataSource( - currentPage: currentPage, - itemFetcher: itemFetcher - ) - } - #endif - public init(mockItems: [ListItem]) { self.items = mockItems self.state = .noMorePages