Skip to content

Commit

Permalink
⚗️ (Navigation): Add programmatic navigation from HomeView
Browse files Browse the repository at this point in the history
  • Loading branch information
ladislas committed Dec 2, 2023
1 parent 4fead37 commit 4ddab24
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 3 deletions.
18 changes: 18 additions & 0 deletions Examples/iOSApp/Sources/Array+SafeIndex.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Leka - iOS Monorepo
// Copyright 2023 APF France handicap
// SPDX-License-Identifier: Apache-2.0

import Foundation

// TODO(@ladislas): move to UtilsKit
extension Array {

subscript(safe index: Int) -> Element? {
guard indices.contains(index) else {
return nil
}

return self[index]
}

}
2 changes: 1 addition & 1 deletion Examples/iOSApp/Sources/CurriculumListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct CurriculumInfoView: View {
}

Section("List of activities") {
ForEach(Activity.all.filter { curriculum.activities.contains($0.id) }) { activity in
ForEach(curriculum.activities) { activity in
NavigationLink(value: activity) {
Text(activity.name)
}
Expand Down
11 changes: 10 additions & 1 deletion Examples/iOSApp/Sources/DataModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,18 @@ struct Activity: Identifiable, Hashable {
struct Curriculum: Identifiable, Hashable {
let id: String
let name: String
let activities: [String]
let activities: [Activity]
let similarCurriculums: [String]?

init(id: String, name: String, activities: [String], similarCurriculums: [String]?) {
self.id = id
self.name = name
self.activities = activities.compactMap { activityId in
Activity.all.first { $0.id == activityId }
}
self.similarCurriculums = similarCurriculums
}

static let all: [Curriculum] = [
Curriculum(
id: "curriculum_1", name: "Curriculum 1", activities: ["activity_1", "activity_2", "activity_3"],
Expand Down
51 changes: 50 additions & 1 deletion Examples/iOSApp/Sources/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,53 @@ struct HomeView: View {
Text( /*@START_MENU_TOKEN@*/"Hello, World!" /*@END_MENU_TOKEN@*/)
.font(.largeTitle)

Button("Go to Activities / Activity 1") {
navigation.set(path: Activity.all[0], for: .activities)
}
.buttonStyle(.borderedProminent)
.tint(.pink)

Button("Go to Activities / Activity 1 / Activity 2 / Activity 3") {
navigation.set(path: Activity.all[0], Activity.all[1], Activity.all[2], for: .activities)
}
.buttonStyle(.borderedProminent)
.tint(.orange)

Button("Go to Curriculums / Curriculum 1") {
navigation.set(path: Curriculum.all[0], for: .curriculums)
}
.buttonStyle(.borderedProminent)
.tint(.yellow)

Button("Go to Curriculums / Curriculum 1 / Activity 2 (w/ objects)") {
navigation.set(path: Curriculum.all[0], Curriculum.all[0].activities[1], for: .curriculums)
}
.buttonStyle(.borderedProminent)
.tint(.purple)

Button("Go to Curriculums / Curriculum 1 / Activity 2 (w/ id + index)") {
navigation.set(curriculum: "curriculum_1", activity: 1)
}
.buttonStyle(.borderedProminent)
.tint(.indigo)

Button("Go to Curriculums / Curriculum 1 / Activity -1 (w/ id + index) NOT WORKING") {
navigation.set(curriculum: "curriculum_1", activity: -1)
}
.buttonStyle(.borderedProminent)
.tint(.red)

Button("Go to Curriculums / Curriculum 1 / Activity 1 (w/ id + id)") {
navigation.set(curriculum: "curriculum_1", activity: "activity_1")
}
.buttonStyle(.borderedProminent)
.tint(.mint)

Button("Go to Curriculums / Curriculum 1 / Activity 1 (w/ id + id) NOT WORKING") {
navigation.set(curriculum: "curriculum_1", activity: "bad_id")
}
.buttonStyle(.borderedProminent)
.tint(.red)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.cyan)
Expand All @@ -21,5 +68,7 @@ struct HomeView: View {
}

#Preview {
HomeView()
NavigationStack {
HomeView()
}
}
77 changes: 77 additions & 0 deletions Examples/iOSApp/Sources/Navigation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class Navigation: ObservableObject {
var selectedCategory: Category? = .home {
willSet {
disableUICompletly = true
guard !isProgrammaticNavigation else {
print("isProgrammaticNavigation is true, early return to avoid reseting path")
return // ? Note: early return to avoid reseting path
}
backupPath(for: selectedCategory)
}
didSet {
Expand All @@ -46,6 +50,8 @@ class Navigation: ObservableObject {
}
}

private var isProgrammaticNavigation: Bool = false

private var homeNavPathBackup: NavigationPath = NavigationPath()
private var activitiesNavPathBackup: NavigationPath = NavigationPath()
private var curriculumsNavPathBackup: NavigationPath = NavigationPath()
Expand Down Expand Up @@ -110,4 +116,75 @@ class Navigation: ObservableObject {
}
}

func set(path newPath: AnyHashable..., for newCategory: Category) {
switch newCategory {
case .home:
break
case .activities:
activitiesNavPathBackup = newPath.compactMap { $0 as? Activity }
.reduce(into: NavigationPath()) { $0.append($1) }
case .curriculums:
var localPath = NavigationPath()
newPath.forEach {
if let activity = $0 as? Activity {
print("append activity: \(activity)")
localPath.append(activity)
} else if let curriculum = $0 as? Curriculum {
print("append curriculum: \(curriculum)")
localPath.append(curriculum)
} else {
print("append unknown: \($0)")
}
}
print("localPath: \(localPath)")
curriculumsNavPathBackup = localPath
print("bckupPath: \(curriculumsNavPathBackup)")
}

underProgrammaticNavigation {
select(category: newCategory)
}
}

func set(curriculum: String, activity index: Int) {
guard let curriculum = Curriculum.all.first(where: { $0.id == curriculum }) else { return }
guard let activity = curriculum.activities[safe: index] else { return }

var localPath = NavigationPath()

localPath.append(curriculum)
localPath.append(activity)

curriculumsNavPathBackup = localPath

underProgrammaticNavigation {
select(category: .curriculums)
}
}

func set(curriculum: String, activity id: String) {
guard let curriculum = Curriculum.all.first(where: { $0.id == curriculum }) else { return }
guard let activity = curriculum.activities.first(where: { $0.id == id }) else { return }

print("curri: \(curriculum)")
print("activ: \(activity)")

var localPath = NavigationPath()

localPath.append(curriculum)
localPath.append(activity)

curriculumsNavPathBackup = localPath

underProgrammaticNavigation {
select(category: .curriculums)
}
}

private func underProgrammaticNavigation(_ callback: () -> Void) {
isProgrammaticNavigation = true
callback()
isProgrammaticNavigation = false
}

}

0 comments on commit 4ddab24

Please sign in to comment.