Skip to content

Commit

Permalink
feat: router (#10)
Browse files Browse the repository at this point in the history
* refactor: remove obsolete ShelfModels and introduce Status model

- Deleted the ShelfModels.swift file, which contained unused shelf-related enums and structs.
- Added a new Status model in Status.swift, encapsulating various properties for status updates, including visibility, media attachments, and account details.
- Enhanced data handling capabilities with the introduction of new structures for Account, MediaAttachment, Mention, Tag, and Card, improving the overall architecture for timeline management.

* feat: implement router for navigation and remove Status model

- Introduced a Router object to manage navigation paths and sheet presentations across the app.
- Updated ContentView to utilize NavigationStack with dynamic navigation destinations for various views (e.g., ItemDetail, UserProfile).
- Enhanced NeoDBApp to provide the Router object to ContentView.
- Removed the obsolete Status model, streamlining the codebase and improving maintainability.
- Added TODO comments for future implementation of detailed views, ensuring clarity on upcoming features.

* feat: enhance router functionality and improve view integration

- Expanded the router implementation to support deep linking and centralized navigation management, including handling for new destinations such as status details and hashtags.
- Updated HomeView and LibraryView to utilize the router for navigation, improving user experience and code organization.
- Added logging for navigation actions to facilitate debugging and tracking of user interactions.
- Revised documentation to reflect new features and next steps for further development, including the implementation of destination views and enhanced error handling.

* feat: add neodb logo assets

- Introduced new logo assets for NeoDB, including a square SVG logo and its corresponding asset catalog configuration.
- The logo is available in multiple scales (1x, 2x, 3x) for improved display across different device resolutions.
- Updated asset catalog to include metadata for the new logo, enhancing the app's branding and visual identity.

* feat: enhance navigation and shelf management features

- Integrated router functionality for improved navigation across user profiles, item details, and shelf management.
- Added new navigation examples and deep linking support in the router documentation.
- Migrated shelf display functionality from ProfileView to a dedicated LibraryView, enhancing organization and user experience.
- Implemented pagination, filtering, and deep linking for the LibraryView, allowing users to manage their collections more effectively.
- Updated StatusView to utilize the router for user profile navigation, improving interaction and accessibility.

* chore: update project.pbxproj to include new documentation files

- Added new documentation files for router functionality and shelf features to the project configuration.
- Included references for router.md and IceCubes/Router.md to enhance navigation documentation.
- Improved organization of project resources by updating membership exceptions in the project file.
  • Loading branch information
lcandy2 authored Jan 8, 2025
1 parent 97ae355 commit 57d4497
Show file tree
Hide file tree
Showing 15 changed files with 1,073 additions and 117 deletions.
2 changes: 2 additions & 0 deletions NeoDB/NeoDB.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@
membershipExceptions = (
Info.plist,
References/Cursor/auth_and_profile.md,
References/Cursor/router.md,
References/Cursor/shelf_feature.md,
References/Cursor/timeline_local.md,
References/IceCubes/Router.md,
References/Mastodon/timelines.md,
References/NeoDB/api.md,
References/NeoDB/openapi/openapi.yaml,
Expand Down
21 changes: 21 additions & 0 deletions NeoDB/NeoDB/Assets.xcassets/neodb-logo.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "logo_square.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
193 changes: 193 additions & 0 deletions NeoDB/NeoDB/Assets.xcassets/neodb-logo.imageset/logo_square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 97 additions & 7 deletions NeoDB/NeoDB/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,38 @@ import SwiftUI

struct ContentView: View {
@EnvironmentObject var authService: AuthService
@StateObject private var router = Router()

var body: some View {
TabView {
NavigationStack {
NavigationStack(path: $router.path) {
HomeView(authService: authService)
.navigationDestination(for: RouterDestination.self) { destination in
switch destination {
case .itemDetail(let id):
Text("Item Detail: \(id)") // TODO: Implement ItemDetailView
case .itemDetailWithItem(let item):
Text("Item Detail: \(item.displayTitle)") // TODO: Implement ItemDetailView
case .shelfDetail(let type):
Text("Shelf: \(type.displayName)") // TODO: Implement ShelfDetailView
case .userShelf(let userId, let type):
Text("User Shelf: \(userId) - \(type.displayName)") // TODO: Implement UserShelfView
case .userProfile(let id):
Text("User Profile: \(id)") // TODO: Implement UserProfileView
case .userProfileWithUser(let user):
Text("User Profile: \(user.displayName)") // TODO: Implement UserProfileView
case .statusDetail(let id):
Text("Status: \(id)") // TODO: Implement StatusDetailView
case .statusDetailWithStatus(let status):
Text("Status: \(status.id)") // TODO: Implement StatusDetailView
case .hashTag(let tag):
Text("Tag: #\(tag)") // TODO: Implement HashTagView
case .followers(let id):
Text("Followers: \(id)") // TODO: Implement FollowersView
case .following(let id):
Text("Following: \(id)") // TODO: Implement FollowingView
}
}
}
.tabItem {
Label("Home", systemImage: "house.fill")
Expand All @@ -27,26 +54,89 @@ struct ContentView: View {
Label("Search", systemImage: "magnifyingglass")
}

NavigationStack {
NavigationStack(path: $router.path) {
LibraryView(authService: authService)
.navigationDestination(for: RouterDestination.self) { destination in
switch destination {
case .itemDetail(let id):
Text("Item Detail: \(id)") // TODO: Implement ItemDetailView
case .itemDetailWithItem(let item):
Text("Item Detail: \(item.displayTitle)") // TODO: Implement ItemDetailView
case .shelfDetail(let type):
Text("Shelf: \(type.displayName)") // TODO: Implement ShelfDetailView
case .userShelf(let userId, let type):
Text("User Shelf: \(userId) - \(type.displayName)") // TODO: Implement UserShelfView
case .userProfile(let id):
Text("User Profile: \(id)") // TODO: Implement UserProfileView
case .userProfileWithUser(let user):
Text("User Profile: \(user.displayName)") // TODO: Implement UserProfileView
case .statusDetail(let id):
Text("Status: \(id)") // TODO: Implement StatusDetailView
case .statusDetailWithStatus(let status):
Text("Status: \(status.id)") // TODO: Implement StatusDetailView
case .hashTag(let tag):
Text("Tag: #\(tag)") // TODO: Implement HashTagView
case .followers(let id):
Text("Followers: \(id)") // TODO: Implement FollowersView
case .following(let id):
Text("Following: \(id)") // TODO: Implement FollowingView
}
}
}
.tabItem {
Label("Library", systemImage: "books.vertical.fill")
}

NavigationStack {
NavigationStack(path: $router.path) {
ProfileView(authService: authService)
.navigationDestination(for: RouterDestination.self) { destination in
switch destination {
case .itemDetail(let id):
Text("Item Detail: \(id)") // TODO: Implement ItemDetailView
case .itemDetailWithItem(let item):
Text("Item Detail: \(item.displayTitle)") // TODO: Implement ItemDetailView
case .shelfDetail(let type):
Text("Shelf: \(type.displayName)") // TODO: Implement ShelfDetailView
case .userShelf(let userId, let type):
Text("User Shelf: \(userId) - \(type.displayName)") // TODO: Implement UserShelfView
case .userProfile(let id):
Text("User Profile: \(id)") // TODO: Implement UserProfileView
case .userProfileWithUser(let user):
Text("User Profile: \(user.displayName)") // TODO: Implement UserProfileView
case .statusDetail(let id):
Text("Status: \(id)") // TODO: Implement StatusDetailView
case .statusDetailWithStatus(let status):
Text("Status: \(status.id)") // TODO: Implement StatusDetailView
case .hashTag(let tag):
Text("Tag: #\(tag)") // TODO: Implement HashTagView
case .followers(let id):
Text("Followers: \(id)") // TODO: Implement FollowersView
case .following(let id):
Text("Following: \(id)") // TODO: Implement FollowingView
}
}
}
.tabItem {
Label("Profile", systemImage: "person.fill")
}
}
.tint(.accentColor)
.environmentObject(router)
.sheet(item: $router.presentedSheet) { sheet in
switch sheet {
case .newStatus:
Text("New Status") // TODO: Implement StatusEditorView
case .editStatus(let status):
Text("Edit Status: \(status.id)") // TODO: Implement StatusEditorView
case .replyToStatus(let status):
Text("Reply to: \(status.id)") // TODO: Implement StatusEditorView
case .addToShelf(let item):
Text("Add to Shelf: \(item.displayTitle)") // TODO: Implement ShelfEditorView
case .editShelfItem(let mark):
Text("Edit Shelf Item: \(mark.item.displayTitle)") // TODO: Implement ShelfEditorView
}
}
}

#if DEBUG
@ObserveInjection var forceRedraw
#endif
}

#Preview {
Expand Down
22 changes: 17 additions & 5 deletions NeoDB/NeoDB/NeoDBApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,37 @@ import SwiftUI
@main
struct NeoDBApp: App {
@StateObject private var authService = AuthService()
@StateObject private var router = Router()

var body: some Scene {
WindowGroup {
Group {
if authService.isAuthenticated {
ContentView()
.environmentObject(authService)
.environmentObject(router)
} else {
LoginView()
.environmentObject(authService)
}
}
.onOpenURL { url in
Task {
do {
try await authService.handleCallback(url: url)
} catch {
print("Authentication error: \(error)")
// First try to handle OAuth callback
if url.scheme == "neodb" && url.host == "oauth" {
Task {
do {
try await authService.handleCallback(url: url)
} catch {
print("Authentication error: \(error)")
}
}
return
}

// Then try to handle deep links
if !router.handleURL(url) {
// If the router didn't handle the URL, open it in the default browser
UIApplication.shared.open(url)
}
}
}
Expand Down
67 changes: 67 additions & 0 deletions NeoDB/NeoDB/References/Cursor/auth_and_profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ graph TD
B --> C[ProfileViewModel]
C --> D[ProfileView]
A --> D
E[Router] --> D
```

### State Management
Expand All @@ -20,6 +21,10 @@ graph TD
// Profile-level state
@Published var user: User?
@Published var isLoading: Bool

// Navigation state
@Published var path: [RouterDestination]
@Published var presentedSheet: SheetDestination?
```

## Key Components
Expand Down Expand Up @@ -55,6 +60,51 @@ class UserService {
}
```

### Router Integration
```swift
// Profile-related destinations
case userProfile(id: String)
case userProfileWithUser(user: User)
case followers(id: String)
case following(id: String)

// Navigation in views
Button {
router.navigate(to: .userProfile(id: account.id))
} label: {
KFImage(URL(string: account.avatar))
.placeholder { ... }
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 44, height: 44)
.clipShape(Circle())
}

// For User type
Button {
router.navigate(to: .userProfileWithUser(user: user))
} label: {
UserAvatarView(user: user)
}
```

### Navigation Examples
```swift
// In StatusView
Button {
router.navigate(to: .userProfile(id: status.account.id))
} label: {
// Avatar or username view
}

// In ProfileView
Button {
router.navigate(to: .followers(id: user.id))
} label: {
Text("Followers")
}
```

### Cache Strategy
```swift
// Cache key format
Expand Down Expand Up @@ -100,6 +150,13 @@ KFImage(URL(string: user.avatar))
.clipShape(Circle())
```

### Navigation Features
- Profile view navigation
- Followers/Following lists
- Deep linking support
- Back navigation
- Sheet presentations

### Image Loading Features
- Automatic caching
- Placeholder support
Expand Down Expand Up @@ -149,11 +206,14 @@ enum AuthError {
- [ ] Background sync
- [ ] Rate limiting
- [ ] Error retry mechanism
- [ ] Analytics tracking
- [ ] Deep linking enhancements

### Performance Optimizations
- Preload avatar images
- Cache size limits
- Background data prefetch
- Navigation state persistence

## API Endpoints

Expand All @@ -173,4 +233,11 @@ Response: {
avatar: string
username: string
}
```

### Navigation
```
/users/{id}
/users/{id}/followers
/users/{id}/following
```
Loading

0 comments on commit 57d4497

Please sign in to comment.