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

Navigation enhancements: Bottom Navigation, screen transitions, back button #670

Merged
merged 4 commits into from
Jun 15, 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
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ dependencies {
implementation 'com.google.accompanist:accompanist-pager:0.30.1'
implementation 'com.google.accompanist:accompanist-pager-indicators:0.30.1'
implementation 'com.google.accompanist:accompanist-flowlayout:0.30.1'
implementation "com.google.accompanist:accompanist-navigation-animation:0.30.1"

// LiveData
implementation 'androidx.compose.runtime:runtime-livedata:1.4.3'
Expand Down
799 changes: 252 additions & 547 deletions app/src/main/java/com/jerboa/MainActivity.kt

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions app/src/main/java/com/jerboa/nav/AboutNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.jerboa.nav

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import com.google.accompanist.navigation.animation.composable
import com.jerboa.db.AppSettings
import com.jerboa.ui.components.settings.about.AboutActivity

private const val aboutRoutePattern = "about"

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.aboutScreen(
navController: NavController,
appSettings: AppSettings?,
) {
composable(
route = aboutRoutePattern,
) {
AboutActivity(
navController = navController,
useCustomTabs = appSettings?.useCustomTabs ?: true,
usePrivateTabs = appSettings?.usePrivateTabs ?: false,
)
}
}
36 changes: 36 additions & 0 deletions app/src/main/java/com/jerboa/nav/AccountSettingsNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.jerboa.nav

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.navDeepLink
import com.google.accompanist.navigation.animation.composable
import com.jerboa.DEFAULT_LEMMY_INSTANCES
import com.jerboa.db.AccountViewModel
import com.jerboa.ui.components.home.SiteViewModel
import com.jerboa.ui.components.settings.account.AccountSettingsActivity
import com.jerboa.ui.components.settings.account.AccountSettingsViewModel

private const val accountSettingsRoutePattern = "accountSettings"

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.accountSettingsScreen(
navController: NavController,
accountSettingsViewModel: AccountSettingsViewModel,
accountViewModel: AccountViewModel,
siteViewModel: SiteViewModel,
) {
composable(
route = accountSettingsRoutePattern,
deepLinks = DEFAULT_LEMMY_INSTANCES.map { instance ->
navDeepLink { uriPattern = "$instance/settings" }
},
) {
AccountSettingsActivity(
navController = navController,
accountViewModel = accountViewModel,
siteViewModel = siteViewModel,
accountSettingsViewModel = accountSettingsViewModel,
)
}
}
34 changes: 34 additions & 0 deletions app/src/main/java/com/jerboa/nav/CommentEditNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.jerboa.nav

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import com.google.accompanist.navigation.animation.composable
import com.jerboa.db.AccountViewModel
import com.jerboa.ui.components.comment.edit.CommentEditActivity
import com.jerboa.ui.components.comment.edit.CommentEditViewModel
import com.jerboa.ui.components.person.PersonProfileViewModel
import com.jerboa.ui.components.post.PostViewModel

private const val commentEditRoutePattern = "commentEdit"

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.commentEditScreen(
accountViewModel: AccountViewModel,
navController: NavController,
commentEditViewModel: CommentEditViewModel,
personProfileViewModel: PersonProfileViewModel,
postViewModel: PostViewModel,
) {
composable(
route = commentEditRoutePattern,
) {
CommentEditActivity(
commentEditViewModel = commentEditViewModel,
accountViewModel = accountViewModel,
navController = navController,
personProfileViewModel = personProfileViewModel,
postViewModel = postViewModel,
)
}
}
99 changes: 99 additions & 0 deletions app/src/main/java/com/jerboa/nav/CommentNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.jerboa.nav

import android.content.Context
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.runtime.LaunchedEffect
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import arrow.core.Either
import com.google.accompanist.navigation.animation.composable
import com.jerboa.DEFAULT_LEMMY_INSTANCES
import com.jerboa.db.Account
import com.jerboa.db.AccountViewModel
import com.jerboa.db.AppSettings
import com.jerboa.db.AppSettingsViewModel
import com.jerboa.ui.components.comment.edit.CommentEditViewModel
import com.jerboa.ui.components.comment.reply.CommentReplyViewModel
import com.jerboa.ui.components.home.SiteViewModel
import com.jerboa.ui.components.post.PostActivity
import com.jerboa.ui.components.post.PostViewModel
import com.jerboa.ui.components.post.edit.PostEditViewModel

private class CommentArgs(val id: Int) {
constructor(navBackStackEntry: NavBackStackEntry) :
this(navBackStackEntry.arguments?.getInt(ID)!!)

companion object {
const val ID = "id"
}
}

private const val commentRoutePattern = "comment/{${CommentArgs.ID}}"

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.commentScreen(
postViewModel: PostViewModel,
siteViewModel: SiteViewModel,
accountViewModel: AccountViewModel,
commentEditViewModel: CommentEditViewModel,
commentReplyViewModel: CommentReplyViewModel,
postEditViewModel: PostEditViewModel,
navController: NavController,
appSettingsViewModel: AppSettingsViewModel,
account: Account?,
appSettings: AppSettings?,
ctx: Context,
) {
composable(
route = commentRoutePattern,
deepLinks = DEFAULT_LEMMY_INSTANCES.map { instance ->
navDeepLink { uriPattern = "$instance/$commentRoutePattern" }
},
arguments = listOf(
navArgument(CommentArgs.ID) {
type = NavType.IntType
},
),
) {
val args = CommentArgs(it)

LaunchedEffect(Unit) {
val commentId = args.id
postViewModel.fetchPost(
id = Either.Right(commentId),
account = account,
clearPost = true,
clearComments = true,
ctx = ctx,
)
}
PostActivity(
postViewModel = postViewModel,
accountViewModel = accountViewModel,
commentEditViewModel = commentEditViewModel,
commentReplyViewModel = commentReplyViewModel,
postEditViewModel = postEditViewModel,
navController = navController,
showCollapsedCommentContent = appSettings?.showCollapsedCommentContent ?: false,
showActionBarByDefault = appSettings?.showCommentActionBarByDefault ?: true,
showVotingArrowsInListView = appSettings?.showVotingArrowsInListView ?: true,
onClickSortType = { commentSortType ->
val commentId = args.id
postViewModel.fetchPost(
id = Either.Right(commentId),
account = account,
clearPost = false,
clearComments = true,
ctx = ctx,
changeSortType = commentSortType,
)
},
selectedSortType = postViewModel.sortType.value,
siteViewModel = siteViewModel,
)
}
}
37 changes: 37 additions & 0 deletions app/src/main/java/com/jerboa/nav/CommentReplyNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.jerboa.nav

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import com.google.accompanist.navigation.animation.composable
import com.jerboa.db.AccountViewModel
import com.jerboa.ui.components.comment.reply.CommentReplyActivity
import com.jerboa.ui.components.comment.reply.CommentReplyViewModel
import com.jerboa.ui.components.home.SiteViewModel
import com.jerboa.ui.components.person.PersonProfileViewModel
import com.jerboa.ui.components.post.PostViewModel

private const val commentReplyRoutePattern = "commentReply"

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.commentReplyScreen(
commentReplyViewModel: CommentReplyViewModel,
accountViewModel: AccountViewModel,
personProfileViewModel: PersonProfileViewModel,
postViewModel: PostViewModel,
navController: NavController,
siteViewModel: SiteViewModel,
) {
composable(
route = commentReplyRoutePattern,
) {
CommentReplyActivity(
commentReplyViewModel = commentReplyViewModel,
postViewModel = postViewModel,
accountViewModel = accountViewModel,
personProfileViewModel = personProfileViewModel,
navController = navController,
siteViewModel = siteViewModel,
)
}
}
47 changes: 47 additions & 0 deletions app/src/main/java/com/jerboa/nav/CommentReportNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.jerboa.nav

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.google.accompanist.navigation.animation.composable
import com.jerboa.db.AccountViewModel
import com.jerboa.ui.components.report.CreateReportViewModel
import com.jerboa.ui.components.report.comment.CreateCommentReportActivity

private class CommentReportArgs(val id: Int) {
constructor(navBackStackEntry: NavBackStackEntry) :
this(navBackStackEntry.arguments?.getInt(ID)!!)

companion object {
const val ID = "id"
}
}

private const val commentReportRoutePattern = "commentReport/{${CommentReportArgs.ID}}"

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.commentReportScreen(
accountViewModel: AccountViewModel,
navController: NavController,
createReportViewModel: CreateReportViewModel,
) {
composable(
route = commentReportRoutePattern,
arguments = listOf(
navArgument(CommentReportArgs.ID) {
type = NavType.IntType
},
),
) {
val args = CommentReportArgs(it)
createReportViewModel.setCommentId(args.id)
CreateCommentReportActivity(
createReportViewModel = createReportViewModel,
accountViewModel = accountViewModel,
navController = navController,
)
}
}
63 changes: 63 additions & 0 deletions app/src/main/java/com/jerboa/nav/CommunityListNavigation.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.jerboa.nav

import androidx.compose.animation.ExperimentalAnimationApi
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.google.accompanist.navigation.animation.composable
import com.jerboa.db.AccountViewModel
import com.jerboa.ui.components.community.list.CommunityListActivity
import com.jerboa.ui.components.community.list.CommunityListViewModel
import com.jerboa.ui.components.home.SiteViewModel

private class CommunityListArgs(val select: Boolean) {
constructor(navBackStackEntry: NavBackStackEntry) :
this(navBackStackEntry.arguments?.getBoolean(SELECT)!!)

companion object {
const val SELECT = "select"
}
}

private const val communityListRoutePattern = "communityList?select={${CommunityListArgs.SELECT}}"

fun NavBackStackEntry.bottomNavIsSearch() = destination.route == communityListRoutePattern

@OptIn(ExperimentalAnimationApi::class)
fun NavGraphBuilder.communityListScreen(
navController: NavController,
communityListViewModel: CommunityListViewModel,
accountViewModel: AccountViewModel,
siteViewModel: SiteViewModel,
) {
composable(
route = communityListRoutePattern,
arguments = listOf(
navArgument(CommunityListArgs.SELECT) {
defaultValue = false
type = NavType.BoolType
},
),
) {
val args = CommunityListArgs(it)

// Whenever navigating here, reset the list with your followed communities
communityListViewModel.setCommunityListFromFollowed(siteViewModel)

CommunityListActivity(
navController = navController,
accountViewModel = accountViewModel,
communityListViewModel = communityListViewModel,
selectMode = args.select,
)
}
}

fun NavController.bottomNavSelectSearch() {
navigate(communityListRoutePattern) {
launchSingleTop = true
popUpTo(0)
}
}
Loading