Skip to content

Commit 6e6b04f

Browse files
authored
Merge pull request #1562 from DimensionDev/feature/ios_performance
optimize ios performance
2 parents 0067888 + 66ff8bb commit 6e6b04f

File tree

23 files changed

+308
-408
lines changed

23 files changed

+308
-408
lines changed

compose-ui/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ skie {
104104
group {
105105
DefaultArgumentInterop.Enabled(true)
106106
}
107+
enableFlowCombineConvertorPreview = true
107108
}
108109
}
109110

iosApp/flare/UI/Component/AdaptiveGrid.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import SwiftUI
22

33
struct AdaptiveGrid: Layout {
44

5-
public var singleFollowsImageAspect: Bool
6-
public var spacing: CGFloat
7-
public var maxColumns: Int
5+
public let singleFollowsImageAspect: Bool
6+
public let singleViewAspectRatio: CGFloat?
7+
public let spacing: CGFloat
8+
public let maxColumns: Int
89

910
public init(
1011
singleFollowsImageAspect: Bool = true,
12+
singleViewAspectRatio: CGFloat? = nil,
1113
spacing: CGFloat = 4,
1214
maxColumns: Int = 3
1315
) {
1416
self.singleFollowsImageAspect = singleFollowsImageAspect
1517
self.spacing = spacing
1618
self.maxColumns = max(1, maxColumns)
19+
self.singleViewAspectRatio = singleViewAspectRatio
1720
}
1821

1922
public struct Cache {}
@@ -140,9 +143,13 @@ struct AdaptiveGrid: Layout {
140143

141144
private func aspectForSingle(subviews: Subviews) -> CGFloat {
142145
if singleFollowsImageAspect {
143-
let ideal = subviews[0].sizeThatFits(.unspecified)
144-
if ideal.width > 0, ideal.height > 0 { return max(0.01, ideal.width / ideal.height) }
145-
return 1
146+
if let ratio = singleViewAspectRatio {
147+
return max(9.0/21.0, ratio)
148+
} else {
149+
let ideal = subviews[0].sizeThatFits(.unspecified)
150+
if ideal.width > 0, ideal.height > 0 { return max(0.01, ideal.width / ideal.height) }
151+
return 1
152+
}
146153
} else {
147154
return 16.0 / 9.0
148155
}
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
1-
import KotlinSharedUI
1+
@preconcurrency import KotlinSharedUI
22
import Foundation
3-
import Combine
3+
@preconcurrency import Combine
44

55
// using @Observable might init presenter multiple times
66
// which is a heavy work since Kotlin Presenter is not designed to do so
77
// so we keep using the old ObservableObject and @StateObject
88
// see: https://github.com/Dimillian/IceCubesApp/issues/2033
99
final class KotlinPresenter<T: AnyObject>: ObservableObject {
10+
private var subscribers = Set<AnyCancellable>()
1011
var presenter: PresenterBase<T>
1112
let key = UUID().uuidString
1213

1314
init(presenter: PresenterBase<T>) {
1415
self.presenter = presenter
1516
self.state = presenter.models.value
16-
self.presenter.subscribe { [weak self] newState in
17+
self.presenter.models.toPublisher().receive(on: DispatchQueue.main).sink { [weak self] newState in
1718
self?.state = newState
18-
}
19+
}.store(in: &subscribers)
1920
}
2021

2122
@Published
2223
var state: T
2324

24-
@MainActor
25+
// @MainActor
2526
deinit {
26-
self.presenter.close()
27+
subscribers.forEach { cancellable in
28+
cancellable.cancel()
29+
}
30+
presenter.close()
2731
}
2832
}

iosApp/flare/UI/Component/MediaView.swift

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ struct MediaView: View {
1717
switch onEnum(of: data) {
1818
case .image(let image):
1919
AdaptiveSizeMediaContainerView(
20-
aspectRatio: CGFloat(image.aspectRatio),
2120
expandToFullSize: expandToFullSize
2221
) {
2322
NetworkImage(data: image.previewUrl)
@@ -26,7 +25,6 @@ struct MediaView: View {
2625
MediaVideoView(data: video, expandToFullSize: expandToFullSize)
2726
case .gif(let gif):
2827
AdaptiveSizeMediaContainerView(
29-
aspectRatio: CGFloat(gif.aspectRatio),
3028
expandToFullSize: expandToFullSize
3129
) {
3230
NetworkImage(data: gif.url)
@@ -38,24 +36,17 @@ struct MediaView: View {
3836
}
3937

4038
struct AdaptiveSizeMediaContainerView<Content: View>: View {
41-
let aspectRatio: CGFloat?
4239
let expandToFullSize: Bool
4340
@ViewBuilder let content: () -> Content
4441

45-
init(aspectRatio: CGFloat? = nil, expandToFullSize: Bool, @ViewBuilder content: @escaping () -> Content) {
46-
self.aspectRatio = aspectRatio
42+
init(expandToFullSize: Bool, @ViewBuilder content: @escaping () -> Content) {
4743
self.expandToFullSize = expandToFullSize
4844
self.content = content
4945
}
5046

5147
var body: some View {
5248
if expandToFullSize {
53-
if let aspectRatio {
54-
content()
55-
.aspectRatio(aspectRatio, contentMode: .fit)
56-
} else {
57-
content()
58-
}
49+
content()
5950
} else {
6051
Color.gray
6152
.opacity(0.2)
@@ -92,7 +83,6 @@ struct MediaVideoView: View {
9283

9384
var body: some View {
9485
AdaptiveSizeMediaContainerView(
95-
aspectRatio: CGFloat(data.aspectRatio),
9686
expandToFullSize: expandToFullSize
9787
) {
9888
NetworkImage(data: data.thumbnailUrl)

iosApp/flare/UI/Component/NetworkImage.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ struct NetworkImage: View {
66
let placeholder: URL?
77
let customHeader: [String: String]?
88
var body: some View {
9-
KFAnimatedImage
10-
.url(data)
9+
KFAnimatedImage(data)
1110
.requestModifier({ request in
1211
if let customHeader {
1312
for (key, value) in customHeader {
@@ -24,11 +23,12 @@ struct NetworkImage: View {
2423
.redacted(reason: .placeholder)
2524
}
2625
}
27-
.if(placeholder == nil, if: { image in
28-
image.loadTransition(.blurReplace)
29-
}, else: { image in
30-
image
31-
})
26+
.cancelOnDisappear(true)
27+
// .if(placeholder == nil, if: { image in
28+
// image.loadTransition(.opacity)
29+
// }, else: { image in
30+
// image
31+
// })
3232
// .resizable()
3333
.scaledToFill()
3434
}

iosApp/flare/UI/Component/PagingView.swift

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ struct PagingView<T: AnyObject, EmptyContent: View, ErrorContent: View, LoadingC
88
@ViewBuilder
99
let errorContent: (KotlinThrowable, @escaping () -> Void) -> ErrorContent
1010
@ViewBuilder
11-
let loadingContent: () -> LoadingContent
11+
let loadingContent: (Int, Int) -> LoadingContent
1212
let loadingCount = 5
1313
@ViewBuilder
14-
let successContent: (T) -> SuccessContent
14+
let successContent: (T, Int, Int) -> SuccessContent
1515
var body: some View {
1616
switch onEnum(of: data) {
1717
case .empty: emptyContent()
@@ -20,20 +20,19 @@ struct PagingView<T: AnyObject, EmptyContent: View, ErrorContent: View, LoadingC
2020
}
2121
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
2222
case .loading: ForEach(0..<loadingCount, id: \.self) { index in
23-
loadingContent()
23+
loadingContent(index, loadingCount)
2424
}
2525
case .success(let success):
2626
ForEach(0..<success.itemCount, id: \.self) { index in
27-
if let item = success.peek(index: index) {
28-
successContent(item)
29-
.onAppear {
30-
_ = success.get(index: index)
31-
}
32-
} else {
33-
loadingContent()
34-
.onAppear {
35-
_ = success.get(index: index)
36-
}
27+
ZStack {
28+
if let item = success.peek(index: index) {
29+
successContent(item, Int(index), Int(success.itemCount))
30+
} else {
31+
loadingContent(Int(index), Int(success.itemCount))
32+
}
33+
}
34+
.onAppear {
35+
_ = success.get(index: index)
3736
}
3837
}
3938

@@ -70,7 +69,13 @@ extension PagingView {
7069
retry()
7170
}
7271
},
73-
loadingContent: loadingContent, successContent: successContent)
72+
loadingContent: { index, loadingCount in
73+
loadingContent()
74+
},
75+
successContent: { item, index, itemCount in
76+
successContent(item)
77+
}
78+
)
7479
}
7580
}
7681

0 commit comments

Comments
 (0)