Skip to content

Commit

Permalink
Merge pull request #1645 from planetary-social/fix-onboarding-spinner
Browse files Browse the repository at this point in the history
#1593: Fix spinner and flashing tab view
  • Loading branch information
joshuatbrown authored Oct 16, 2024
2 parents 72744a0 + 2bde08e commit aebbcb7
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 122 deletions.
4 changes: 4 additions & 0 deletions Nos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
030024192CC00DFC0073ED56 /* SplashScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030024182CC00DF70073ED56 /* SplashScreenView.swift */; };
030036852C5D39DD002C71F5 /* RefreshController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030036842C5D39DD002C71F5 /* RefreshController.swift */; };
030036942C5D3AD3002C71F5 /* RefreshController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030036842C5D39DD002C71F5 /* RefreshController.swift */; };
030036AB2C5D872B002C71F5 /* NewNotesButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 030036AA2C5D872B002C71F5 /* NewNotesButton.swift */; };
Expand Down Expand Up @@ -575,6 +576,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
030024182CC00DF70073ED56 /* SplashScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreenView.swift; sourceTree = "<group>"; };
030036842C5D39DD002C71F5 /* RefreshController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshController.swift; sourceTree = "<group>"; };
030036AA2C5D872B002C71F5 /* NewNotesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewNotesButton.swift; sourceTree = "<group>"; };
0304D0A62C9B4BF2001D16C7 /* OpenGraphMetatdata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGraphMetatdata.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1916,6 +1918,7 @@
isa = PBXGroup;
children = (
C9F84C20298DC36800C6714D /* AppView.swift */,
030024182CC00DF70073ED56 /* SplashScreenView.swift */,
5B79F6402BA11618002DA9BE /* Components */,
65BD8DC12BDAF2C300802039 /* Discover */,
03618B112C825D8700BCBC55 /* Fixtures */,
Expand Down Expand Up @@ -2365,6 +2368,7 @@
C9B597652BBC8300002EC76A /* ImagePickerUIViewController.swift in Sources */,
C98CA9042B14FA3D00929141 /* PagedRelaySubscription.swift in Sources */,
5B0D99032A94090A0039F0C5 /* DoubleTapToPopModifier.swift in Sources */,
030024192CC00DFC0073ED56 /* SplashScreenView.swift in Sources */,
0357299B2BE415E5005FEE85 /* ContentWarningController.swift in Sources */,
5BFF66B42A58853D00AA79DD /* PublishedEventsView.swift in Sources */,
03D1B42C2C3C1B0D001778CD /* TLVElement.swift in Sources */,
Expand Down
4 changes: 3 additions & 1 deletion Nos/AppController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ import Logger

enum CurrentState {
case onboarding
case loading
case loggedIn
}

private(set) var currentState: CurrentState?
private(set) var currentState: CurrentState

@ObservationIgnored @Dependency(\.analytics) private var analytics
@ObservationIgnored @Dependency(\.router) private var router
@ObservationIgnored @Dependency(\.currentUser) private var currentUser

init() {
currentState = .loading
Log.info("App Version: \(Bundle.current.versionAndBuild)")
}

Expand Down
253 changes: 132 additions & 121 deletions Nos/Views/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Dependencies
struct AppView: View {

@State var showNewPost = false
@State var newPostContents: String?
@State var newPostContents: String?

@Environment(AppController.self) var appController
@EnvironmentObject private var router: Router
Expand All @@ -13,132 +13,21 @@ struct AppView: View {
@Dependency(\.crashReporting) private var crashReporting
@Dependency(\.userDefaults) private var userDefaults
@Environment(CurrentUser.self) var currentUser

@State private var lastSelectedTab = AppDestination.home
@State private var showNIP05Wizard = false

var body: some View {
ZStack {
if appController.currentState == .onboarding {
switch appController.currentState {
case .loading:
SplashScreenView()
.ignoresSafeArea()
case .onboarding:
OnboardingView(completion: appController.completeOnboarding)
} else {
TabView(selection: $router.selectedTab) {
if let author = currentUser.author {
HomeTab(user: author)
.tabItem {
VStack {
let text = Text(.localizable.homeFeed)
if $router.selectedTab.wrappedValue == .home {
Image.tabIconHomeSelected
text
} else {
Image.tabIconHome
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.home)
.onAppear {
// TODO: Move this somewhere better like CurrentUser when it becomes the source of truth
// for who is logged in
if let keyPair = currentUser.keyPair {
analytics.identify(
with: keyPair,
nip05: currentUser.author?.nip05
)
crashReporting.identify(with: keyPair)
}
}
}

DiscoverTab()
.tabItem {
VStack {
let text = Text(.localizable.discover)
if $router.selectedTab.wrappedValue == .discover {
Image.tabIconEveryoneSelected
text.foregroundColor(.primaryTxt)
} else {
Image.tabIconEveryone
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.discover)

VStack {}
.tabItem {
VStack {
Image.newPostButton
Text(.localizable.post)
}
}
.tag(AppDestination.noteComposer(nil))

NotificationsView(user: currentUser.author)
.tabItem {
VStack {
let text = Text(.localizable.notifications)
if $router.selectedTab.wrappedValue == .notifications {
Image.tabIconNotificationsSelected
text.foregroundColor(.primaryTxt)
} else {
Image.tabIconNotifications
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.notifications)
.badge(pushNotificationService.badgeCount)

if let author = currentUser.author {
ProfileTab(author: author, path: $router.profilePath)
.tabItem {
VStack {
let text = Text(.localizable.profileTitle)
if $router.selectedTab.wrappedValue == .profile {
Image.tabProfileSelected
text.foregroundColor(.primaryTxt)
} else {
Image.tabProfile
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.profile)
}
}
.onChange(of: router.selectedTab) { _, newTab in
if case let AppDestination.noteComposer(contents) = newTab {
newPostContents = contents
showNewPost = true
router.selectedTab = lastSelectedTab
} else if !showNewPost {
lastSelectedTab = newTab
}
}
.overlay {
if router.isLoading {
ZStack {
Rectangle().fill(.black.opacity(0.4))
ProgressView()
}
}
}
.sheet(isPresented: $showNewPost, content: {
NoteComposer(initialContents: newPostContents, isPresented: $showNewPost)
.environment(currentUser)
.interactiveDismissDisabled()
})

case .loggedIn:
tabView

SideMenu(
menuWidth: 300,
menuOpened: router.sideMenuOpened,
Expand All @@ -159,6 +48,128 @@ struct AppView: View {
.tint(.primaryTxt)
}

private var tabView: some View {
TabView(selection: $router.selectedTab) {
if let author = currentUser.author {
HomeTab(user: author)
.tabItem {
VStack {
let text = Text(.localizable.homeFeed)
if $router.selectedTab.wrappedValue == .home {
Image.tabIconHomeSelected
text
} else {
Image.tabIconHome
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.home)
.onAppear {
// TODO: Move this somewhere better like CurrentUser when it becomes the source of truth
// for who is logged in
if let keyPair = currentUser.keyPair {
analytics.identify(
with: keyPair,
nip05: currentUser.author?.nip05
)
crashReporting.identify(with: keyPair)
}
}
}

DiscoverTab()
.tabItem {
VStack {
let text = Text(.localizable.discover)
if $router.selectedTab.wrappedValue == .discover {
Image.tabIconEveryoneSelected
text.foregroundColor(.primaryTxt)
} else {
Image.tabIconEveryone
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.discover)

VStack {}
.tabItem {
VStack {
Image.newPostButton
Text(.localizable.post)
}
}
.tag(AppDestination.noteComposer(nil))

NotificationsView(user: currentUser.author)
.tabItem {
VStack {
let text = Text(.localizable.notifications)
if $router.selectedTab.wrappedValue == .notifications {
Image.tabIconNotificationsSelected
text.foregroundColor(.primaryTxt)
} else {
Image.tabIconNotifications
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.notifications)
.badge(pushNotificationService.badgeCount)

if let author = currentUser.author {
ProfileTab(author: author, path: $router.profilePath)
.tabItem {
VStack {
let text = Text(.localizable.profileTitle)
if $router.selectedTab.wrappedValue == .profile {
Image.tabProfileSelected
text.foregroundColor(.primaryTxt)
} else {
Image.tabProfile
text.foregroundColor(.secondaryTxt)
}
}
}
.toolbarBackground(.visible, for: .tabBar)
.toolbarBackground(Color.cardBgBottom, for: .tabBar)
.tag(AppDestination.profile)
}
}
.onChange(of: router.selectedTab) { _, newTab in
if case let AppDestination.noteComposer(contents) = newTab {
newPostContents = contents
showNewPost = true
router.selectedTab = lastSelectedTab
} else if !showNewPost {
lastSelectedTab = newTab
}
}
.overlay {
if router.isLoading {
ZStack {
Rectangle().fill(.black.opacity(0.4))
ProgressView()
}
}
}
.sheet(isPresented: $showNewPost) {
NoteComposer(initialContents: newPostContents, isPresented: $showNewPost)
.environment(currentUser)
.interactiveDismissDisabled()
}
}
}

extension AppView {

private func presentNIP05SheetIfNeeded() async {
guard let author = currentUser.author, let npub = author.npubString else {
return
Expand Down
21 changes: 21 additions & 0 deletions Nos/Views/SplashScreenView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import SwiftUI

/// Displays our splash screen as a SwiftUI view
struct SplashScreenView: UIViewControllerRepresentable {

let storyboardName = "Launch Screen"

// This function loads the storyboard and returns the view controller
func makeUIViewController(context: Context) -> UIViewController {
let storyboard = UIStoryboard(name: storyboardName, bundle: Bundle.main)
let viewController = storyboard.instantiateInitialViewController() ?? UIViewController()
return viewController
}

// Required but typically unused
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

#Preview {
SplashScreenView()
}

0 comments on commit aebbcb7

Please sign in to comment.