Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restructured onboarding #613

Merged
merged 3 commits into from
Sep 18, 2023
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
24 changes: 20 additions & 4 deletions Mlem.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
504106CD2A744D7F000AAEF8 /* CommentRepository+Dependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504106CC2A744D7F000AAEF8 /* CommentRepository+Dependency.swift */; };
504ECBAE2AB45B2A006C0B96 /* LemmyURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504ECBAD2AB45B2A006C0B96 /* LemmyURL.swift */; };
504ECBB12AB4B101006C0B96 /* LemmyURLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504ECBB02AB4B101006C0B96 /* LemmyURLTests.swift */; };
504ECBAA2AB27C73006C0B96 /* LandingPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504ECBA92AB27C73006C0B96 /* LandingPage.swift */; };
504ECBAC2AB27CB1006C0B96 /* OnboardingRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504ECBAB2AB27CB1006C0B96 /* OnboardingRoute.swift */; };
505240E32A86916500EA4558 /* FavoriteCommunitiesTracker+Dependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505240E22A86916500EA4558 /* FavoriteCommunitiesTracker+Dependency.swift */; };
505240E52A86E32700EA4558 /* CommunityListModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505240E42A86E32700EA4558 /* CommunityListModel.swift */; };
505240E72A88D36D00EA4558 /* SectionIndexTitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505240E62A88D36D00EA4558 /* SectionIndexTitles.swift */; };
Expand Down Expand Up @@ -384,7 +386,7 @@
CDDCF6512A677E1B003DA3AC /* FancyTabItemPreferenceKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF6502A677E1B003DA3AC /* FancyTabItemPreferenceKeys.swift */; };
CDDCF6532A677F45003DA3AC /* TabSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF6522A677F45003DA3AC /* TabSelection.swift */; };
CDDCF6572A678298003DA3AC /* FancyTabBarSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCF6562A678298003DA3AC /* FancyTabBarSelection.swift */; };
CDE3BA872A8C25B000B972E2 /* Onboarding View.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE3BA862A8C25B000B972E2 /* Onboarding View.swift */; };
CDE3BA872A8C25B000B972E2 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE3BA862A8C25B000B972E2 /* OnboardingView.swift */; };
CDE3BA892A8C64BD00B972E2 /* Collapsible Text Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE3BA882A8C64BD00B972E2 /* Collapsible Text Item.swift */; };
CDE6A80B2A43E9F00062D161 /* CommentSortType.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE6A80A2A43E9F00062D161 /* CommentSortType.swift */; };
CDE6A80D2A45EAB30062D161 /* Embedded Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDE6A80C2A45EAB30062D161 /* Embedded Post.swift */; };
Expand Down Expand Up @@ -489,6 +491,8 @@
504106CC2A744D7F000AAEF8 /* CommentRepository+Dependency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CommentRepository+Dependency.swift"; sourceTree = "<group>"; };
504ECBAD2AB45B2A006C0B96 /* LemmyURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LemmyURL.swift; sourceTree = "<group>"; };
504ECBB02AB4B101006C0B96 /* LemmyURLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LemmyURLTests.swift; sourceTree = "<group>"; };
504ECBA92AB27C73006C0B96 /* LandingPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LandingPage.swift; sourceTree = "<group>"; };
504ECBAB2AB27CB1006C0B96 /* OnboardingRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingRoute.swift; sourceTree = "<group>"; };
505240E22A86916500EA4558 /* FavoriteCommunitiesTracker+Dependency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavoriteCommunitiesTracker+Dependency.swift"; sourceTree = "<group>"; };
505240E42A86E32700EA4558 /* CommunityListModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunityListModel.swift; sourceTree = "<group>"; };
505240E62A88D36D00EA4558 /* SectionIndexTitles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionIndexTitles.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -827,7 +831,7 @@
CDDCF6502A677E1B003DA3AC /* FancyTabItemPreferenceKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FancyTabItemPreferenceKeys.swift; sourceTree = "<group>"; };
CDDCF6522A677F45003DA3AC /* TabSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabSelection.swift; sourceTree = "<group>"; };
CDDCF6562A678298003DA3AC /* FancyTabBarSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FancyTabBarSelection.swift; sourceTree = "<group>"; };
CDE3BA862A8C25B000B972E2 /* Onboarding View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Onboarding View.swift"; sourceTree = "<group>"; };
CDE3BA862A8C25B000B972E2 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
CDE3BA882A8C64BD00B972E2 /* Collapsible Text Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collapsible Text Item.swift"; sourceTree = "<group>"; };
CDE6A80A2A43E9F00062D161 /* CommentSortType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentSortType.swift; sourceTree = "<group>"; };
CDE6A80C2A45EAB30062D161 /* Embedded Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Embedded Post.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1078,6 +1082,16 @@
path = Model;
sourceTree = "<group>";
};
504ECBA82AB27C4C006C0B96 /* Onboarding */ = {
isa = PBXGroup;
children = (
504ECBA92AB27C73006C0B96 /* LandingPage.swift */,
CDE3BA862A8C25B000B972E2 /* OnboardingView.swift */,
504ECBAB2AB27CB1006C0B96 /* OnboardingRoute.swift */,
);
path = Onboarding;
sourceTree = "<group>";
};
5064D03B2A6DE05000B22EE3 /* Notifications */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1364,7 +1378,6 @@
CDCBD7292A8EC06D00387A2C /* Components */,
6332FDCE27EFDD2E0009A98A /* Accounts Page.swift */,
63F0C7B82A0533C700A18C5D /* Add Account View.swift */,
CDE3BA862A8C25B000B972E2 /* Onboarding View.swift */,
CDCBD7252A8D69A200387A2C /* Instance Picker View.swift */,
CDCBD7272A8D6B7700387A2C /* Instance Picker View Logic.swift */,
CDC65D902A86B830007205E5 /* DeleteAccountView.swift */,
Expand Down Expand Up @@ -1515,6 +1528,7 @@
6363D5F327EE1BA900E34822 /* Views */ = {
isa = PBXGroup;
children = (
504ECBA82AB27C4C006C0B96 /* Onboarding */,
6386E03E2A04570F006B3C1D /* Shared */,
6363D5F427EE1BAE00E34822 /* Tabs */,
);
Expand Down Expand Up @@ -2581,6 +2595,7 @@
504ECBAE2AB45B2A006C0B96 /* LemmyURL.swift in Sources */,
CDA217EA2A63093E00BDA173 /* ReportComment.swift in Sources */,
CDA217E82A63029B00BDA173 /* ReportMention.swift in Sources */,
504ECBAA2AB27C73006C0B96 /* LandingPage.swift in Sources */,
508845CF2A3641160088E483 /* JSONDecoder+Default.swift in Sources */,
637218672A3A2AAD008C4816 /* GetPersonDetails.swift in Sources */,
B1A26FE12A44AAB200B91A32 /* Navigation getter.swift in Sources */,
Expand Down Expand Up @@ -2721,6 +2736,7 @@
637218432A3A2AAD008C4816 /* APIClient.swift in Sources */,
CD82A2572A716D7C00111034 /* PersonRepository+Dependency.swift in Sources */,
63DF71F12A02999C002AC14E /* App Constants.swift in Sources */,
504ECBAC2AB27CB1006C0B96 /* OnboardingRoute.swift in Sources */,
CD82A2532A716B8100111034 /* PersonRepository.swift in Sources */,
CD69F55F2A40121D0028D4F7 /* Ellipsis Menu.swift in Sources */,
638535712A1779BC00815781 /* GeneralSettingsView.swift in Sources */,
Expand Down Expand Up @@ -2754,7 +2770,7 @@
CD6483A62A82FAF200A5AE84 /* ProfileTabLabel.swift in Sources */,
CDEBC3252A9A57D200518D9D /* Content Type.swift in Sources */,
6386E0402A045723006B3C1D /* Website Icon Complex.swift in Sources */,
CDE3BA872A8C25B000B972E2 /* Onboarding View.swift in Sources */,
CDE3BA872A8C25B000B972E2 /* OnboardingView.swift in Sources */,
5064D0412A6E63E000B22EE3 /* Task+Notifiable.swift in Sources */,
63F0C7BD2A058CD200A18C5D /* Check if Endpoint Exists.swift in Sources */,
E4D4DBA02A7C7B9D00C4F3DE /* Comments.swift in Sources */,
Expand Down
63 changes: 63 additions & 0 deletions Mlem/Views/Onboarding/LandingPage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// LandingPage.swift
// Mlem
//
// Created by mormaer on 14/09/2023.
//
//

import SwiftUI

struct LandingPage: View {
@State private var navigationPath = NavigationPath()

var body: some View {
NavigationStack(path: $navigationPath) {
VStack(spacing: 40) {
Text("Welcome to Mlem!")
.bold()

LogoView()

VStack {
newUserButton
existingUserButton
}
}
.padding(.horizontal)
.frame(maxHeight: .infinity)
.navigationDestination(for: OnboardingRoute.self) { route in
switch route {
case .onboard:
OnboardingView(navigationPath: $navigationPath)
case let .login(url):
AddSavedInstanceView(onboarding: true, givenInstance: url?.absoluteString)
}
}
}
}

@ViewBuilder
var newUserButton: some View {
Button {
navigationPath.append(OnboardingRoute.onboard)
} label: {
Text("I'm new here")
.padding(.vertical, 5)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
}

@ViewBuilder
var existingUserButton: some View {
Button {
navigationPath.append(OnboardingRoute.login(nil))
} label: {
Text("I have a Lemmy account")
.padding(.vertical, 5)
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
}
}
14 changes: 14 additions & 0 deletions Mlem/Views/Onboarding/OnboardingRoute.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// OnboardingRoute.swift
// Mlem
//
// Created by mormaer on 14/09/2023.
//
//

import Foundation

enum OnboardingRoute: Hashable {
case onboard
case login(URL?)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Onboarding View.swift
// OnboardingView.swift
// Mlem
//
// Created by Eric Andrews on 2023-08-15.
Expand All @@ -10,93 +10,41 @@ import SwiftUI

struct OnboardingView: View {
enum OnboardingTab {
case welcome, about, instances, addAccount
case about, instances
}

@Binding var flow: AppFlow
@Binding var navigationPath: NavigationPath

@State var selectedTab: OnboardingTab = .welcome
@State var selectedTab: OnboardingTab = .about
@State var hideNav: Bool = true

@State var selectedInstance: InstanceMetadata?

var body: some View {
TabView(selection: $selectedTab) {
onboardingTab
.tag(OnboardingTab.welcome)

aboutTab
.tag(OnboardingTab.about)

instancesTab
.tag(OnboardingTab.instances)

AddSavedInstanceView(onboarding: true, givenInstance: selectedInstance?.url.absoluteString)
.tag(OnboardingTab.addAccount)
}
.onChange(of: selectedInstance) { _ in
selectedTab = .addAccount
.onChange(of: selectedInstance) { instance in
guard let instanceUrl = instance?.url else { return }
navigationPath.append(OnboardingRoute.login(instanceUrl))
}
.animation(.spring(response: 0.5), value: selectedTab)
.tabViewStyle(PageTabViewStyle())
}

// MARK: - Onboarding Tab

@ViewBuilder
var onboardingTab: some View {
VStack(spacing: 40) {
Text("Welcome to Mlem!")
.bold()

LogoView()

VStack {
newUserButton
existingUserButton
}
}
.padding(.horizontal)
.frame(maxHeight: .infinity)
}

@ViewBuilder
var newUserButton: some View {
Button {
selectedTab = .about
} label: {
Text("I'm new here")
.padding(.vertical, 5)
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.tabViewStyle(.page(indexDisplayMode: .always))
.indexViewStyle(.page(backgroundDisplayMode: .always))
}

@ViewBuilder
var existingUserButton: some View {
Button {
selectedTab = .addAccount
} label: {
Text("I have a Lemmy account")
.padding(.vertical, 5)
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
}


// MARK: - About Tab

@ViewBuilder
var aboutTab: some View {
ScrollView {
VStack(spacing: 40) {
Group {
Text("What is Lemmy?")
.bold()

Text(.init(whatIsLemmy))
}
.padding()
Text(.init(whatIsLemmy))
.padding()

VStack(spacing: 0) {
Divider()
Expand Down Expand Up @@ -125,9 +73,10 @@ struct OnboardingView: View {

// add a little space for the tab selection indicator
Spacer()
.frame(height: 20)
.frame(height: 36)
}
}
.navigationTitle("What is Lemmy?")
}

@ViewBuilder
Expand All @@ -146,5 +95,6 @@ struct OnboardingView: View {

var instancesTab: some View {
InstancePickerView(selectedInstance: $selectedInstance, onboarding: true)
.padding(.bottom, 36)
}
}
30 changes: 17 additions & 13 deletions Mlem/Views/Shared/Accounts/Accounts Page.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ struct AccountsPage: View {
let instances = Array(accountsTracker.accountsByInstance.keys).sorted()

Group {
if instances.isEmpty || isShowingInstanceAdditionSheet {
if instances.isEmpty {
AddSavedInstanceView(onboarding: false)
} else {
List {
ForEach(instances, id: \.self) { instance in
Section(header: Text(instance)) {
ForEach(accountsTracker.accountsByInstance[instance] ?? []) { account in
Button(account.username) {
dismiss()
Button(account.nickname) {
setFlow(using: account)
dismiss()
}
.disabled(isActiveAccount(account))
.swipeActions {
Button("Remove", role: .destructive) {
dismiss()
accountsTracker.removeAccount(account: account)
if account == appState.currentActiveAccount {
if isActiveAccount(account) {
// if we just deleted the current account we (currently!) have a decision to make
if let first = accountsTracker.savedAccounts.first {
// if we have another account available, go to that...
Expand All @@ -54,6 +54,8 @@ struct AccountsPage: View {
// no accounts, so go to onboarding
setFlow(using: nil)
}

dismiss()
}
}
}
Expand Down Expand Up @@ -93,15 +95,17 @@ struct AccountsPage: View {
return account == currentAccount ? .secondary : .primary
}

private func isActiveAccount(_ account: SavedAccount) -> Bool {
guard let currentAccount = appState.currentActiveAccount else { return false }
return account == currentAccount
}

private func setFlow(using account: SavedAccount?) {
// this tiny delay prevents the modal dismiss animation from being cancelled
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
if let account {
setFlow(.account(account))
return
}

setFlow(.onboarding)
if let account {
setFlow(.account(account))
return
}

setFlow(.onboarding)
}
}
Loading