Skip to content

Commit db4c8d8

Browse files
committed
Early Profile WIP
1 parent 26c576e commit db4c8d8

11 files changed

+180
-16
lines changed

App/AppRouter.swift

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public struct AppRouter: ViewModifier {
1818
PostsTimelineView()
1919
case .profile(let profile):
2020
ProfileView(profile: profile)
21+
case .profilePosts(let profile, let filter):
22+
PostsProfileView(profile: profile, filter: filter)
23+
case .profileLikes(let profile):
24+
PostsLikesView(profile: profile)
2125
}
2226
}
2327
}

App/IcySkyApp.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct IcySkyApp: App {
2121
@State var currentUser: CurrentUser?
2222
@State var router: Router = .init()
2323
@State var isLoadingInitialSession: Bool = true
24-
@State var postDataControllerProvider: PostDataControllerProvider = .init()
24+
@State var postDataControllerProvider: PostContextProvider = .init()
2525

2626
init() {
2727
ImagePipeline.shared = ImagePipeline(configuration: .withDataCache)

Packages/Features/Sources/NotificationsUI/Rows/SingleNotificationRow.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import SwiftUI
88
struct SingleNotificationRow: View {
99
@Environment(Router.self) var router
1010
@Environment(BSkyClient.self) var client
11-
@Environment(PostDataControllerProvider.self) var postDataControllerProvider
11+
@Environment(PostContextProvider.self) var postDataControllerProvider
1212

1313
let notification: AppBskyLexicon.Notification.Notification
1414
let postItem: PostItem?
@@ -57,7 +57,7 @@ struct SingleNotificationRow: View {
5757
.onTapGesture {
5858
router.navigateTo(RouterDestination.post(postItem))
5959
}
60-
.environment(postDataControllerProvider.getController(for: postItem, client: client))
60+
.environment(postDataControllerProvider.get(for: postItem, client: client))
6161
}
6262
}
6363

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
@preconcurrency import ATProtoKit
2+
import DesignSystem
3+
import Models
4+
import Network
5+
import SwiftUI
6+
import User
7+
8+
public struct PostsLikesView: View {
9+
@Environment(BSkyClient.self) var client
10+
11+
let profile: Profile
12+
13+
public init(profile: Profile) {
14+
self.profile = profile
15+
}
16+
17+
public var body: some View {
18+
PostListView(datasource: self)
19+
}
20+
}
21+
22+
// MARK: - Datasource
23+
extension PostsLikesView: PostsListViewDatasource {
24+
var title: String {
25+
"Likes"
26+
}
27+
28+
func loadPosts(with state: PostsListViewState) async -> PostsListViewState {
29+
do {
30+
switch state {
31+
case .uninitialized, .loading, .error:
32+
let feed = try await client.protoClient.getActorLikes(by: profile.did)
33+
return .loaded(posts: PostListView.processFeed(feed.feed), cursor: feed.cursor)
34+
case let .loaded(posts, cursor):
35+
let feed = try await client.protoClient.getActorLikes(
36+
by: profile.did, limit: nil, cursor: cursor)
37+
return .loaded(posts: posts + PostListView.processFeed(feed.feed), cursor: feed.cursor)
38+
}
39+
} catch {
40+
return .error(error)
41+
}
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@preconcurrency import ATProtoKit
2+
import DesignSystem
3+
import Models
4+
import Network
5+
import SwiftUI
6+
import User
7+
8+
public struct PostsProfileView: View {
9+
@Environment(BSkyClient.self) var client
10+
11+
let profile: Profile
12+
let filter: PostsProfileViewFilter
13+
14+
public init(profile: Profile, filter: PostsProfileViewFilter) {
15+
self.profile = profile
16+
self.filter = filter
17+
}
18+
19+
public var body: some View {
20+
PostListView(datasource: self)
21+
}
22+
}
23+
24+
// MARK: - Datasource
25+
extension PostsProfileView: PostsListViewDatasource {
26+
var title: String {
27+
"Posts"
28+
}
29+
30+
func loadPosts(with state: PostsListViewState) async -> PostsListViewState {
31+
do {
32+
switch state {
33+
case .uninitialized, .loading, .error:
34+
let feed = try await client.protoClient.getAuthorFeed(
35+
by: profile.did, postFilter: filter.atProtocolFilter)
36+
return .loaded(posts: PostListView.processFeed(feed.feed), cursor: feed.cursor)
37+
case let .loaded(posts, cursor):
38+
let feed = try await client.protoClient.getAuthorFeed(
39+
by: profile.did, limit: nil, cursor: cursor, postFilter: filter.atProtocolFilter)
40+
return .loaded(posts: posts + PostListView.processFeed(feed.feed), cursor: feed.cursor)
41+
}
42+
} catch {
43+
return .error(error)
44+
}
45+
}
46+
}

Packages/Features/Sources/PostUI/Row/PostRowActionsView.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extension EnvironmentValues {
88

99
public struct PostRowActionsView: View {
1010
@Environment(\.hideMoreActions) var hideMoreActions
11-
@Environment(PostDataController.self) var dataController
11+
@Environment(PostContext.self) var dataController
1212

1313
let post: PostItem
1414

Packages/Features/Sources/PostUI/Row/PostRowView.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public struct PostRowView: View {
1515
@Environment(\.isFocused) var isFocused
1616
@Environment(\.sizeCategory) var sizeCategory
1717

18-
@Environment(PostDataControllerProvider.self) var postDataControllerProvider
18+
@Environment(PostContextProvider.self) var postDataControllerProvider
1919
@Environment(Router.self) var router
2020
@Environment(BSkyClient.self) var client
2121

@@ -36,7 +36,7 @@ public struct PostRowView: View {
3636
mainView
3737
.padding(.bottom, 18)
3838
}
39-
.environment(postDataControllerProvider.getController(for: post, client: client))
39+
.environment(postDataControllerProvider.get(for: post, client: client))
4040
.listRowSeparator(.hidden)
4141
.listRowInsets(.init(top: 0, leading: 18, bottom: 0, trailing: 18))
4242
}
@@ -187,7 +187,7 @@ public struct PostRowView: View {
187187
}
188188
.listStyle(.plain)
189189
.environment(Router())
190-
.environment(PostDataControllerProvider())
190+
.environment(PostContextProvider())
191191
.environment(
192192
BSkyClient(
193193
session: .init(

Packages/Features/Sources/ProfileUI/ProfileView.swift

+52
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import DesignSystem
22
import Models
3+
import PostUI
4+
import Router
35
import SwiftUI
46

57
public struct ProfileView: View {
8+
@Environment(Router.self) var router
69
public let profile: Profile
710
public let showBack: Bool
811

@@ -19,9 +22,58 @@ public struct ProfileView: View {
1922
showBack: showBack
2023
)
2124
.padding(.bottom)
25+
26+
NavigationLink(
27+
value: RouterDestination.profilePosts(profile: profile, filter: .postsWithNoReplies)
28+
) {
29+
makeLabelButton(title: "Posts", icon: "bubble.fill", color: .blueskyBackground)
30+
}
31+
32+
NavigationLink(
33+
value: RouterDestination.profilePosts(profile: profile, filter: .postsWithReplies)
34+
) {
35+
makeLabelButton(title: "Replies", icon: "arrowshape.turn.up.left.fill", color: .teal)
36+
}
37+
38+
NavigationLink(
39+
value: RouterDestination.profilePosts(profile: profile, filter: .postsWithMedia)
40+
) {
41+
makeLabelButton(title: "Medias", icon: "photo.fill", color: .gray)
42+
}
43+
44+
NavigationLink(
45+
value: RouterDestination.profilePosts(profile: profile, filter: .postAndAuthorThreads)
46+
) {
47+
makeLabelButton(title: "Threads", icon: "bubble.left.and.bubble.right.fill", color: .green)
48+
}
49+
50+
NavigationLink(value: RouterDestination.profileLikes(profile)) {
51+
makeLabelButton(title: "Likes", icon: "heart.fill", color: .red)
52+
}
2253
}
2354
.listStyle(.plain)
2455
.navigationBarBackButtonHidden()
2556
.toolbar(.hidden, for: .navigationBar)
2657
}
58+
59+
private func makeLabelButton(title: String, icon: String, color: Color) -> some View {
60+
HStack {
61+
Image(systemName: icon)
62+
.foregroundColor(.white)
63+
.shadow(color: .white, radius: 3)
64+
.padding(12)
65+
.background(
66+
LinearGradient(
67+
colors: [color, .indigo],
68+
startPoint: .topLeading,
69+
endPoint: .bottomTrailing)
70+
)
71+
.frame(width: 40, height: 40)
72+
.glowingRoundedRectangle()
73+
Text(title)
74+
.font(.title3)
75+
.fontWeight(.semibold)
76+
Spacer()
77+
}
78+
}
2779
}

Packages/Model/Sources/Models/PostDataController.swift Packages/Model/Sources/Models/PostContext.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,25 @@ import SwiftUI
55

66
@MainActor
77
@Observable
8-
public class PostDataControllerProvider {
9-
private var dataControllers: [String: PostDataController] = [:]
8+
public class PostContextProvider {
9+
private var contexts: [String: PostContext] = [:]
1010

1111
public init() {}
1212

13-
public func getController(for post: PostItem, client: BSkyClient) -> PostDataController {
14-
if let controller = dataControllers[post.uri] {
15-
return controller
13+
public func get(for post: PostItem, client: BSkyClient) -> PostContext {
14+
if let context = contexts[post.uri] {
15+
return context
1616
} else {
17-
let controller = PostDataController(post: post, client: client)
18-
dataControllers[post.uri] = controller
19-
return controller
17+
let context = PostContext(post: post, client: client)
18+
contexts[post.uri] = context
19+
return context
2020
}
2121
}
2222
}
2323

2424
@MainActor
2525
@Observable
26-
public class PostDataController {
26+
public class PostContext {
2727
private var post: PostItem
2828
private let client: BSkyClient
2929

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import ATProtoKit
2+
3+
public enum PostsProfileViewFilter: String, Sendable, CaseIterable, Equatable, Hashable {
4+
case postsWithReplies
5+
case postsWithNoReplies
6+
case postsWithMedia
7+
case postAndAuthorThreads
8+
9+
public var atProtocolFilter: AppBskyLexicon.Feed.GetAuthorFeed.Filter {
10+
switch self {
11+
case .postsWithReplies: return .postsWithReplies
12+
case .postsWithNoReplies: return .postsWithNoReplies
13+
case .postsWithMedia: return .postsWithMedia
14+
case .postAndAuthorThreads: return .postAndAuthorThreads
15+
}
16+
}
17+
}

Packages/Model/Sources/Router/RouterDestination.swift

+2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ public enum RouterDestination: Hashable {
55
case feed(uri: String, name: String, avatarImageURL: URL?)
66
case post(PostItem)
77
case profile(Profile)
8+
case profilePosts(profile: Profile, filter: PostsProfileViewFilter)
9+
case profileLikes(Profile)
810
case timeline
911
}

0 commit comments

Comments
 (0)