Skip to content

Commit

Permalink
Merge pull request #1664 from planetary-social/onboarding-display-name
Browse files Browse the repository at this point in the history
#1597: Display Name screen in onboarding
  • Loading branch information
joshuatbrown authored Oct 18, 2024
2 parents 244247d + 6b32a0a commit 496bf7e
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed new moderation feature flag. [#1646](https://github.com/planetary-social/nos/issues/1646)
- Added the Private Key onboarding screen. Currently behind the “New Onboarding Flow” feature flag. [#1595](https://github.com/planetary-social/nos/issues/1595)
- Added the Public Key onboarding screen. Currently behind the “New Onboarding Flow” feature flag. [#1596](https://github.com/planetary-social/nos/issues/1596)
- Added the Display Name onboarding screen. Currently behind the “New Onboarding Flow” feature flag. [#1597](https://github.com/planetary-social/nos/issues/1597)

## [0.2.2] - 2024-10-11Z

Expand Down
8 changes: 8 additions & 0 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
030E56CA2CC1BC6200A4A51E /* PublicKeyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030E56C92CC1BC6200A4A51E /* PublicKeyView.swift */; };
030E56E42CC1BF2900A4A51E /* CopyButtonState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030E56E32CC1BF2900A4A51E /* CopyButtonState.swift */; };
030E56F32CC2836D00A4A51E /* CopyKeyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030E56F22CC2836D00A4A51E /* CopyKeyView.swift */; };
030E570D2CC2A05B00A4A51E /* DisplayNameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030E570C2CC2A05B00A4A51E /* DisplayNameView.swift */; };
030E571B2CC2ADDB00A4A51E /* SaveProfileError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030E571A2CC2ADDB00A4A51E /* SaveProfileError.swift */; };
030FECAB2CB5E0B900820014 /* BuildYourNetworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030FECAA2CB5E0B900820014 /* BuildYourNetworkView.swift */; };
0314CF742C9C7DD00001A53B /* youTube_fortnight_short.html in Resources */ = {isa = PBXBuildFile; fileRef = 0314CF732C9C7DD00001A53B /* youTube_fortnight_short.html */; };
0314D5AC2C7D31060002E7F4 /* MediaService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0314D5AB2C7D31060002E7F4 /* MediaService.swift */; };
Expand Down Expand Up @@ -595,6 +597,8 @@
030E56C92CC1BC6200A4A51E /* PublicKeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicKeyView.swift; sourceTree = "<group>"; };
030E56E32CC1BF2900A4A51E /* CopyButtonState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyButtonState.swift; sourceTree = "<group>"; };
030E56F22CC2836D00A4A51E /* CopyKeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyKeyView.swift; sourceTree = "<group>"; };
030E570C2CC2A05B00A4A51E /* DisplayNameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayNameView.swift; sourceTree = "<group>"; };
030E571A2CC2ADDB00A4A51E /* SaveProfileError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveProfileError.swift; sourceTree = "<group>"; };
030FECAA2CB5E0B900820014 /* BuildYourNetworkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildYourNetworkView.swift; sourceTree = "<group>"; };
0314CF732C9C7DD00001A53B /* youTube_fortnight_short.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = youTube_fortnight_short.html; sourceTree = "<group>"; };
0314D5AB2C7D31060002E7F4 /* MediaService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaService.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1478,6 +1482,7 @@
children = (
030FECAA2CB5E0B900820014 /* BuildYourNetworkView.swift */,
039F09582CC051EE00FEEC81 /* CreateAccountView.swift */,
030E570C2CC2A05B00A4A51E /* DisplayNameView.swift */,
3F30020629C237AB003D4F8B /* OnboardingAgeVerificationView.swift */,
3F30020C29C382EB003D4F8B /* OnboardingLoginView.swift */,
3F30020829C23895003D4F8B /* OnboardingNotOldEnoughView.swift */,
Expand Down Expand Up @@ -1658,6 +1663,7 @@
502B6C3C2C9462A400446316 /* PushNotificationRegistrar.swift */,
C936B4612A4CB01C00DF1EB9 /* PushNotificationService.swift */,
C9A8015D2BD0177D006E29B2 /* ReportPublisher.swift */,
030E571A2CC2ADDB00A4A51E /* SaveProfileError.swift */,
5B8805192A21027C00E21F06 /* SHA256Key.swift */,
C9B678E029EEC41000303F33 /* SocialGraphCache.swift */,
C9F64D8B29ED840700563F2B /* Zipper.swift */,
Expand Down Expand Up @@ -2351,6 +2357,7 @@
C92E7F6D2C4EFF9B00B80638 /* WebSocketState.swift in Sources */,
C95D68AB299E710F00429F86 /* Color+Hex.swift in Sources */,
037975EA2C0E695A00ADDF37 /* MockFeatureFlags.swift in Sources */,
030E571B2CC2ADDB00A4A51E /* SaveProfileError.swift in Sources */,
C94A5E182A72C84200B6EC5D /* ReportCategory.swift in Sources */,
C9A8015E2BD0177D006E29B2 /* ReportPublisher.swift in Sources */,
C9F0BB6B29A503D6000547FC /* PublicKey.swift in Sources */,
Expand Down Expand Up @@ -2549,6 +2556,7 @@
C905B0772A619E99009B8A78 /* LPLinkViewRepresentable.swift in Sources */,
C95D68A7299E6FF000429F86 /* KeyFixture.swift in Sources */,
0304D0B22C9B731F001D16C7 /* MockOpenGraphService.swift in Sources */,
030E570D2CC2A05B00A4A51E /* DisplayNameView.swift in Sources */,
C94437E629B0DB83004D8C86 /* NotificationsView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.500",
"blue" : "0xD8",
"green" : "0x88",
"red" : "0xA5"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
48 changes: 48 additions & 0 deletions Nos/Assets/Localization/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -5224,6 +5224,30 @@
}
}
},
"displayNameDescription" : {
"comment" : "a description for the display name screen in onboarding",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "This is how others will see you when they view your notes. You can always change it."
}
}
}
},
"displayNameError" : {
"comment" : "error message for when we can't set the display name in onboarding",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "There is a problem connecting to the servers. You can skip for now and visit your Profile to update later."
}
}
}
},
"displayNameHeadline" : {
"comment" : "headline for the display name screen in onboarding",
"extractionState" : "manual",
Expand All @@ -5236,6 +5260,18 @@
}
}
},
"displayNamePlaceholder" : {
"comment" : "placeholder text for the display name field in onboarding",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Your display name"
}
}
}
},
"done" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -17463,6 +17499,18 @@
}
}
},
"skipForNow" : {
"comment" : "button title that allows the user to skip this for now",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Skip for now"
}
}
}
},
"software" : {
"extractionState" : "manual",
"localizations" : {
Expand Down
16 changes: 16 additions & 0 deletions Nos/Service/SaveProfileError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Foundation

/// An error that may occur while saving a profile.
enum SaveProfileError: LocalizedError {
case unexpectedError
case unableToPublishChanges

var errorDescription: String? {
switch self {
case .unexpectedError:
return "Something unexpected happened"
case .unableToPublishChanges:
return "We were unable to publish your changes to the network."
}
}
}
94 changes: 94 additions & 0 deletions Nos/Views/Onboarding/DisplayNameView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import Dependencies
import SwiftUI

/// The Display Name view in the onboarding.
struct DisplayNameView: View {
@Environment(OnboardingState.self) private var state
@Environment(CurrentUser.self) private var currentUser
@Environment(\.managedObjectContext) private var viewContext

@Dependency(\.crashReporting) private var crashReporting

@State private var displayName = ""
@State private var showError: Bool = false

var body: some View {
ZStack {
Color.appBg
.ignoresSafeArea()
ViewThatFits(in: .vertical) {
displayNameStack

ScrollView {
displayNameStack
}
}
}
.navigationBarHidden(true)
.alert("displayNameError", isPresented: $showError) {
Button {
nextStep()
} label: {
Text("skipForNow")
}
}
}

var displayNameStack: some View {
VStack(alignment: .leading, spacing: 20) {
LargeNumberView(3)
Text("displayNameHeadline")
.font(.clarityBold(.title))
.foregroundStyle(Color.primaryTxt)
Text("displayNameDescription")
.font(.body)
.foregroundStyle(Color.secondaryTxt)
TextField(
"",
text: $displayName,
prompt: Text("displayNamePlaceholder")
.foregroundStyle(Color.textFieldPlaceholder)
)
.textInputAutocapitalization(.none)
.foregroundStyle(Color.primaryTxt)
.fontWeight(.bold)
.autocorrectionDisabled()
.padding()
.withStyledBorder()
Spacer()
BigActionButton("next") {
await save()
}
}
.padding(40)
.readabilityPadding()
}

func nextStep() {
state.step = .buildYourNetwork
}

/// Saves the display name locally and publishes the event to relays. Sets `showError` if it fails.
func save() async {
guard let author = await currentUser.author else {
showError = true
return
}

author.displayName = displayName
do {
try viewContext.save()
try await currentUser.publishMetadata()
nextStep()
} catch {
crashReporting.report(error)
showError = true
}
}
}

#Preview {
DisplayNameView()
.environment(OnboardingState())
.inject(previewData: PreviewData())
}
4 changes: 4 additions & 0 deletions Nos/Views/Onboarding/OnboardingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum OnboardingStep {
case createAccount
case privateKey
case publicKey
case displayName
case buildYourNetwork
case login
}
Expand Down Expand Up @@ -57,6 +58,9 @@ struct OnboardingView: View {
case .publicKey:
PublicKeyView()
.environment(state)
case .displayName:
DisplayNameView()
.environment(state)
case .login:
OnboardingLoginView(completion: completion)
case .buildYourNetwork:
Expand Down
2 changes: 1 addition & 1 deletion Nos/Views/Onboarding/PublicKeyView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct PublicKeyView: View {
CopyKeyView("copyPublicKey", keyString: $publicKeyString, copyButtonState: $copyButtonState)
Spacer()
BigActionButton("next") {
state.step = .buildYourNetwork
state.step = .displayName
}
}
.padding(40)
Expand Down
20 changes: 3 additions & 17 deletions Nos/Views/Profile/Edit/ProfileEditView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct ProfileEditView: View {
@State private var website: String = ""
@State private var showNIP05Wizard = false
@State private var showConfirmationDialog = false
@State private var saveError: SaveError?
@State private var saveError: SaveProfileError?

@State private var isUploadingPhoto = false

Expand Down Expand Up @@ -144,24 +144,10 @@ struct ProfileEditView: View {
// Go back to profile page
router.pop()
} catch CurrentUserError.errorWhilePublishingToRelays {
saveError = SaveError.unableToPublishChanges
saveError = SaveProfileError.unableToPublishChanges
} catch {
crashReporting.report(error)
saveError = SaveError.unexpectedError
}
}

enum SaveError: LocalizedError {
case unexpectedError
case unableToPublishChanges

var errorDescription: String? {
switch self {
case .unexpectedError:
return "Something unexpected happened"
case .unableToPublishChanges:
return "We were unable to publish your changes in the network"
}
saveError = SaveProfileError.unexpectedError
}
}
}
Expand Down

0 comments on commit 496bf7e

Please sign in to comment.