Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions ios/Kith.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
A3E58ADFB234FD1407023392 /* KithOnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 416A75C69650AAD584FEE064 /* KithOnboardingView.swift */; };
A4336E3A96ACF2FE47DA6C35 /* HubSyncIssueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A41324D637F7A736FAD6B80A /* HubSyncIssueTests.swift */; };
B11A9EBD171FF12E6F7B0045 /* KithUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69B0BA41F320166AEA1728A2 /* KithUITests.swift */; };
DAC253113D3DD2E0BB7067CC /* KithOnboardingReplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E19BA6F30BC6EADC0EA7CD /* KithOnboardingReplayTests.swift */; };
B71A3A7A7503BACD158CAAF1 /* KithOnboardingPresentationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2497D4CF5603E39B52F3EEE /* KithOnboardingPresentationTests.swift */; };
F3C48A6CA9EC720182B123BC /* Design.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4DDB782CAF5D8FD571DC3B /* Design.swift */; };
F680576C1F45EE52AFBA44DE /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 2C466A859325D15A49C22248 /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -107,7 +107,6 @@
79D378032A9722C9555ED8AE /* DemoData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoData.swift; sourceTree = "<group>"; };
7A8B5ADE80477C15D5324428 /* CloudStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudStore.swift; sourceTree = "<group>"; };
7AA76B6FCE2A1BD2FDDE7D45 /* BubbleField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BubbleField.swift; sourceTree = "<group>"; };
80E19BA6F30BC6EADC0EA7CD /* KithOnboardingReplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KithOnboardingReplayTests.swift; sourceTree = "<group>"; };
8E3415A5E88E90361208B65E /* CloudKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CloudKit.framework; path = System/Library/Frameworks/CloudKit.framework; sourceTree = SDKROOT; };
8FDEF1D744F055053CB588A9 /* KithCoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KithCoreTests.swift; sourceTree = "<group>"; };
A41324D637F7A736FAD6B80A /* HubSyncIssueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HubSyncIssueTests.swift; sourceTree = "<group>"; };
Expand All @@ -120,6 +119,7 @@
DC4EA45455B6FF74E4BCFC21 /* Domain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Domain.swift; sourceTree = "<group>"; };
DE4DDB782CAF5D8FD571DC3B /* Design.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Design.swift; sourceTree = "<group>"; };
E01B4D3A257D3291B92EA865 /* KithAppTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = KithAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
E2497D4CF5603E39B52F3EEE /* KithOnboardingPresentationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KithOnboardingPresentationTests.swift; sourceTree = "<group>"; };
F2AF9D313021EF3F3623DE6D /* KithConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KithConnectionView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -164,7 +164,7 @@
isa = PBXGroup;
children = (
A41324D637F7A736FAD6B80A /* HubSyncIssueTests.swift */,
80E19BA6F30BC6EADC0EA7CD /* KithOnboardingReplayTests.swift */,
E2497D4CF5603E39B52F3EEE /* KithOnboardingPresentationTests.swift */,
);
name = KithAppTests;
path = Tests/KithAppTests;
Expand Down Expand Up @@ -440,7 +440,7 @@
buildActionMask = 2147483647;
files = (
A4336E3A96ACF2FE47DA6C35 /* HubSyncIssueTests.swift in Sources */,
DAC253113D3DD2E0BB7067CC /* KithOnboardingReplayTests.swift in Sources */,
B71A3A7A7503BACD158CAAF1 /* KithOnboardingPresentationTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
37 changes: 22 additions & 15 deletions ios/Sources/Kith/AppModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class AppModel {
private(set) var document: KithDocument = .empty
var isLoading = true
var isOnboardingPresented = false
private(set) var isReplayingOnboarding = false
private(set) var isExistingOwnerOrientation = false
private(set) var onboardingPersonID: UUID?
var selectedPersonID: UUID?
var isAddingPerson = false
Expand Down Expand Up @@ -107,7 +107,7 @@ final class AppModel {
}
}

static let onboardingCompletionKey = "kith.onboarding.completed.v1"
static let onboardingCompletionKey = "kith.illustrated-onboarding.seen.v1"
static let onboardingPersonKey = "kith.onboarding.person.v1"
static let lastPlatformSyncKey = "kith.hub.last-sync.v1"
static let demoOnboardingPersonID = UUID(uuidString: "BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB")!
Expand All @@ -121,32 +121,45 @@ final class AppModel {
completed: Bool,
resumablePersonID: UUID?
) -> Bool {
guard !completed else { return false }
if document.people.isEmpty { return true }
!completed
}

static func isExistingOwnerOrientation(
document: KithDocument,
resumablePersonID: UUID?
) -> Bool {
guard !document.people.isEmpty else { return false }
guard let resumablePersonID,
document.person(id: resumablePersonID) != nil,
document.entries(for: resumablePersonID).isEmpty else { return false }
return true
document.entries(for: resumablePersonID).isEmpty else { return true }
return false
}

private func configureOnboarding(arguments: [String]) {
if arguments.contains("--fresh-demo") {
isOnboardingPresented = false
isExistingOwnerOrientation = false
return
}
if arguments.contains("--onboarding-demo") {
isOnboardingPresented = true
isExistingOwnerOrientation = false
return
}
if arguments.contains("--onboarding-resume-demo") {
isOnboardingPresented = true
isExistingOwnerOrientation = false
return
}
let defaults = UserDefaults.standard
if onboardingPersonID == nil,
let rawID = defaults.string(forKey: Self.onboardingPersonKey) {
onboardingPersonID = UUID(uuidString: rawID)
}
isExistingOwnerOrientation = Self.isExistingOwnerOrientation(
document: document,
resumablePersonID: onboardingPersonID
)
isOnboardingPresented = Self.shouldPresentOnboarding(
document: document,
completed: defaults.bool(forKey: Self.onboardingCompletionKey),
Expand Down Expand Up @@ -208,20 +221,14 @@ final class AppModel {
}

func finishOnboarding(addAnother: Bool = false) {
UserDefaults.standard.set(true, forKey: Self.onboardingCompletionKey)
UserDefaults.standard.removeObject(forKey: Self.onboardingPersonKey)
isOnboardingPresented = false
isReplayingOnboarding = false
isExistingOwnerOrientation = false
onboardingPersonID = nil
if addAnother { isAddingPerson = true }
}

/// Reopens the product tour without creating or editing a person.
func replayOnboarding() {
onboardingPersonID = nil
isReplayingOnboarding = true
isShowingConnection = false
isOnboardingPresented = true
}

func deletePerson(id: UUID) {
let deletedIDs = [id] + document.entries.filter { $0.personID == id }.map(\.id)
document.removePerson(id: id)
Expand Down
8 changes: 0 additions & 8 deletions ios/Sources/Kith/KithConnectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,6 @@ struct KithConnectionView: View {
.foregroundStyle(KithPalette.rust)
}

Button {
model.replayOnboarding()
} label: {
Label("Replay onboarding", systemImage: "sparkles")
.frame(maxWidth: .infinity, alignment: .leading)
}
.font(.headline)
.frame(minHeight: 44)
}
.padding(28)
}
Expand Down
6 changes: 3 additions & 3 deletions ios/Sources/Kith/KithOnboardingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ struct KithOnboardingView: View {
.frame(maxHeight: 220)
.frame(maxWidth: .infinity)
.accessibilityLabel("A hand-drawn figure ties one remembered moment to the lantern of someone close.")
if model.isReplayingOnboarding {
replayActions
if model.isExistingOwnerOrientation {
existingOwnerActions
} else {
lanternPreview
VStack(alignment: .leading, spacing: 16) {
Expand Down Expand Up @@ -99,7 +99,7 @@ struct KithOnboardingView: View {
.navigationBarTitleDisplayMode(.inline)
}

private var replayActions: some View {
private var existingOwnerActions: some View {
VStack(alignment: .leading, spacing: 14) {
Text("Your existing constellation stays exactly as it is.")
.font(.body)
Expand Down
34 changes: 34 additions & 0 deletions ios/Tests/KithAppTests/KithOnboardingPresentationTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import KithCore
import XCTest

@testable import Kith

@MainActor
final class KithOnboardingPresentationTests: XCTestCase {
func testExistingOwnerGetsSafeIllustratedOrientationUntilSeen() throws {
let person = Person(
id: UUID(),
name: "Rahul",
circle: .friends,
closeness: 4,
hue: .clay
)
var document = KithDocument.empty
try document.upsert(person)

XCTAssertTrue(AppModel.shouldPresentOnboarding(
document: document,
completed: false,
resumablePersonID: nil
))
XCTAssertTrue(AppModel.isExistingOwnerOrientation(
document: document,
resumablePersonID: nil
))
XCTAssertFalse(AppModel.shouldPresentOnboarding(
document: document,
completed: true,
resumablePersonID: nil
))
}
}
16 changes: 0 additions & 16 deletions ios/Tests/KithAppTests/KithOnboardingReplayTests.swift

This file was deleted.

4 changes: 2 additions & 2 deletions ios/Tests/KithUITests/KithUITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class KithUITests: XCTestCase {
}

func testDemoConstellationOpensAPersonAndTheirLog() {
let app = launch(["--ui-demo"])
let app = launch(["--ui-demo", "-kith.illustrated-onboarding.seen.v1", "YES"])
let maya = app.buttons.matching(NSPredicate(format: "label CONTAINS[c] %@", "Maya Rao")).firstMatch
XCTAssertTrue(maya.waitForExistence(timeout: 4))
maya.tap()
Expand Down Expand Up @@ -82,7 +82,7 @@ final class KithUITests: XCTestCase {
}

func testExistingPeopleBypassOnboarding() {
let app = launch(["--ui-demo"])
let app = launch(["--ui-demo", "-kith.illustrated-onboarding.seen.v1", "YES"])

XCTAssertTrue(app.staticTexts["Kith"].waitForExistence(timeout: 4))
XCTAssertFalse(app.staticTexts["The people you keep close."].exists)
Expand Down
Loading