mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-05-24 16:35:49 -04:00
Fix issues with onboarding hints
Also use opportunity to re-format Main.kt
This commit is contained in:
@@ -21,7 +21,7 @@ glide = "5.0.5"
|
||||
glideCompose = "1.0.0-beta08"
|
||||
coilCompose = "3.3.0"
|
||||
molecule = "2.2.0"
|
||||
hints = "1.1.1"
|
||||
hints = "2.0.1"
|
||||
|
||||
androidxCoreKtx = "1.17.0"
|
||||
androidxAppcompat = "1.7.1"
|
||||
|
||||
@@ -18,12 +18,14 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
||||
import androidx.navigation3.runtime.NavEntry
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.runtime.rememberNavBackStack
|
||||
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_MEDIUM_LOWER_BOUND
|
||||
import com.viktormykhailiv.compose.hints.HintHost
|
||||
import org.fdroid.R
|
||||
import org.fdroid.database.AppListSortOrder
|
||||
import org.fdroid.fdroid.ui.theme.FDroidContent
|
||||
@@ -75,215 +77,219 @@ fun Main(onListeningForIntent: () -> Unit = {}) {
|
||||
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND)
|
||||
}
|
||||
val listDetailStrategy = rememberListDetailSceneStrategy<NavKey>(directive = directive)
|
||||
FDroidContent {
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
sceneStrategy = listDetailStrategy,
|
||||
entryDecorators = listOf(
|
||||
rememberSaveableStateHolderNavEntryDecorator(),
|
||||
rememberViewModelStoreNavEntryDecorator(),
|
||||
),
|
||||
entryProvider = entryProvider {
|
||||
entry<NavigationKey.Discover>(
|
||||
metadata = ListDetailSceneStrategy.listPane("appdetails") {
|
||||
Text(stringResource(R.string.no_app_selected))
|
||||
},
|
||||
) {
|
||||
val viewModel = hiltViewModel<DiscoverViewModel>()
|
||||
val numUpdates = viewModel.numUpdates.collectAsStateWithLifecycle(0).value
|
||||
Discover(
|
||||
discoverModel = viewModel.discoverModel.collectAsStateWithLifecycle().value,
|
||||
onListTap = {
|
||||
backStack.add(NavigationKey.AppList(it))
|
||||
},
|
||||
onAppTap = {
|
||||
backStack.add(NavigationKey.AppDetails(it.packageName))
|
||||
},
|
||||
onNav = { backStack.add(it) },
|
||||
numUpdates = numUpdates,
|
||||
isBigScreen = isBigScreen,
|
||||
onSearch = viewModel::search,
|
||||
onSearchCleared = viewModel::onSearchCleared,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
entry<NavigationKey.MyApps>(
|
||||
metadata = ListDetailSceneStrategy.listPane("appdetails") {
|
||||
Text(stringResource(R.string.no_app_selected))
|
||||
},
|
||||
) {
|
||||
val myAppsViewModel = hiltViewModel<MyAppsViewModel>()
|
||||
val myAppsInfo = object : MyAppsInfo {
|
||||
override val model =
|
||||
myAppsViewModel.myAppsModel.collectAsStateWithLifecycle().value
|
||||
|
||||
override fun refresh() = myAppsViewModel.refresh()
|
||||
override fun updateAll() = myAppsViewModel.updateAll()
|
||||
override fun changeSortOrder(sort: AppListSortOrder) =
|
||||
myAppsViewModel.changeSortOrder(sort)
|
||||
|
||||
override fun search(query: String) = myAppsViewModel.search(query)
|
||||
override fun confirmAppInstall(
|
||||
packageName: String,
|
||||
state: InstallState.UserConfirmationNeeded,
|
||||
) = myAppsViewModel.confirmAppInstall(packageName, state)
|
||||
}
|
||||
MyApps(
|
||||
myAppsInfo = myAppsInfo,
|
||||
currentPackageName = if (isBigScreen) {
|
||||
(backStack.last() as? NavigationKey.AppDetails)?.packageName
|
||||
} else null,
|
||||
onAppItemClick = {
|
||||
backStack.add(NavigationKey.AppDetails(it))
|
||||
},
|
||||
onNav = { backStack.add(it) },
|
||||
isBigScreen = isBigScreen,
|
||||
)
|
||||
}
|
||||
entry<NavigationKey.AppDetails>(
|
||||
metadata = ListDetailSceneStrategy.detailPane("appdetails")
|
||||
) {
|
||||
val appDetailsViewModel = hiltViewModel<AppDetailsViewModel>()
|
||||
LaunchedEffect(it.packageName) {
|
||||
appDetailsViewModel.setAppDetails(it.packageName)
|
||||
}
|
||||
AppDetails(
|
||||
item = appDetailsViewModel.appDetails.collectAsStateWithLifecycle().value,
|
||||
onNav = { navKey -> backStack.add(navKey) },
|
||||
onBackNav = if (isBigScreen) null else {
|
||||
{ backStack.removeLastOrNull() }
|
||||
},
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
entry<NavigationKey.AppList>(
|
||||
metadata = ListDetailSceneStrategy.listPane("appdetails") {
|
||||
Text(stringResource(R.string.no_app_selected))
|
||||
},
|
||||
) {
|
||||
val appListViewModel = hiltViewModel<AppListViewModel>()
|
||||
LaunchedEffect(it.type) {
|
||||
appListViewModel.load(it.type)
|
||||
}
|
||||
val appListInfo = object : AppListInfo {
|
||||
override val model =
|
||||
appListViewModel.appListModel.collectAsStateWithLifecycle().value
|
||||
override val actions: AppListActions = appListViewModel
|
||||
override val list: AppListType =
|
||||
appListViewModel.currentList.collectAsStateWithLifecycle().value
|
||||
override val showFilters: Boolean =
|
||||
appListViewModel.showFilters.collectAsStateWithLifecycle().value
|
||||
override val showOnboarding: Boolean =
|
||||
appListViewModel.showOnboarding.collectAsStateWithLifecycle().value
|
||||
}
|
||||
AppList(
|
||||
appListInfo = appListInfo,
|
||||
currentPackageName = if (isBigScreen) {
|
||||
(backStack.last() as? NavigationKey.AppDetails)?.packageName
|
||||
} else null,
|
||||
onBackClicked = { backStack.removeLastOrNull() },
|
||||
modifier = Modifier,
|
||||
) { packageName ->
|
||||
backStack.add(NavigationKey.AppDetails(packageName))
|
||||
}
|
||||
}
|
||||
entry<NavigationKey.Repos>(
|
||||
metadata = ListDetailSceneStrategy.listPane("repos") {
|
||||
Text(text = stringResource(R.string.no_repository_selected))
|
||||
},
|
||||
) {
|
||||
val viewModel = hiltViewModel<RepositoriesViewModel>()
|
||||
val info = object : RepositoryInfo {
|
||||
override val model: RepositoryModel =
|
||||
viewModel.model.collectAsStateWithLifecycle().value
|
||||
|
||||
override val currentRepositoryId: Long? = if (isBigScreen) {
|
||||
(backStack.last() as? NavigationKey.RepoDetails)?.repoId
|
||||
} else null
|
||||
|
||||
override fun onOnboardingSeen() = viewModel.onOnboardingSeen()
|
||||
|
||||
override fun onRepositorySelected(repositoryItem: RepositoryItem) {
|
||||
backStack.add(NavigationKey.RepoDetails(repositoryItem.repoId))
|
||||
}
|
||||
|
||||
override fun onRepositoryEnabled(repoId: Long, enabled: Boolean) =
|
||||
viewModel.onRepositoryEnabled(repoId, enabled)
|
||||
|
||||
override fun onAddRepo() {
|
||||
backStack.add(NavigationKey.AddRepo())
|
||||
}
|
||||
|
||||
override fun onRepositoryMoved(fromRepoId: Long, toRepoId: Long) =
|
||||
viewModel.onRepositoriesMoved(fromRepoId, toRepoId)
|
||||
|
||||
override fun onRepositoriesFinishedMoving(
|
||||
fromRepoId: Long,
|
||||
toRepoId: Long,
|
||||
) = viewModel.onRepositoriesFinishedMoving(fromRepoId, toRepoId)
|
||||
}
|
||||
Repositories(info) {
|
||||
backStack.removeLastOrNull()
|
||||
}
|
||||
}
|
||||
entry<NavigationKey.RepoDetails>(
|
||||
metadata = ListDetailSceneStrategy.detailPane("repos")
|
||||
) { navKey ->
|
||||
val viewModel = hiltViewModel<RepoDetailsViewModel>()
|
||||
LaunchedEffect(navKey) {
|
||||
viewModel.setRepoId(navKey.repoId)
|
||||
}
|
||||
RepoDetails(
|
||||
info = object : RepoDetailsInfo {
|
||||
override val model = viewModel.model.collectAsStateWithLifecycle().value
|
||||
override val actions = viewModel
|
||||
},
|
||||
onShowAppsClicked = { title, repoId ->
|
||||
val type = AppListType.Repository(title, repoId)
|
||||
backStack.add(NavigationKey.AppList(type))
|
||||
},
|
||||
) {
|
||||
backStack.removeLastOrNull()
|
||||
}
|
||||
}
|
||||
entry<NavigationKey.AddRepo> { navKey ->
|
||||
val viewModel = hiltViewModel<AddRepoViewModel>()
|
||||
LaunchedEffect(navKey) {
|
||||
if (navKey.uri != null) {
|
||||
viewModel.onFetchRepo(navKey.uri)
|
||||
}
|
||||
}
|
||||
AddRepo(
|
||||
state = viewModel.state.collectAsStateWithLifecycle().value,
|
||||
onFetchRepo = viewModel::onFetchRepo,
|
||||
onAddRepo = viewModel::addFetchedRepository,
|
||||
onExistingRepo = { repoId ->
|
||||
backStack.removeLastOrNull()
|
||||
backStack.add(NavigationKey.RepoDetails(repoId))
|
||||
},
|
||||
onRepoAdded = { title, repoId ->
|
||||
backStack.removeLastOrNull()
|
||||
backStack.add(NavigationKey.RepoDetails(repoId))
|
||||
val type = AppListType.Repository(title, repoId)
|
||||
backStack.add(NavigationKey.AppList(type))
|
||||
},
|
||||
onBackClicked = { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
entry(NavigationKey.Settings) {
|
||||
val viewModel = hiltViewModel<SettingsViewModel>()
|
||||
Settings(
|
||||
onSaveLogcat = {
|
||||
viewModel.onSaveLogcat(it)
|
||||
backStack.removeLastOrNull()
|
||||
},
|
||||
onBackClicked = { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
entry(NavigationKey.About) {
|
||||
About { backStack.removeLastOrNull() }
|
||||
}
|
||||
val entryProvider: (NavKey) -> NavEntry<NavKey> = entryProvider {
|
||||
entry<NavigationKey.Discover>(
|
||||
metadata = ListDetailSceneStrategy.listPane("appdetails") {
|
||||
Text(stringResource(R.string.no_app_selected))
|
||||
},
|
||||
)
|
||||
) {
|
||||
val viewModel = hiltViewModel<DiscoverViewModel>()
|
||||
val numUpdates = viewModel.numUpdates.collectAsStateWithLifecycle(0).value
|
||||
Discover(
|
||||
discoverModel = viewModel.discoverModel.collectAsStateWithLifecycle().value,
|
||||
onListTap = {
|
||||
backStack.add(NavigationKey.AppList(it))
|
||||
},
|
||||
onAppTap = {
|
||||
backStack.add(NavigationKey.AppDetails(it.packageName))
|
||||
},
|
||||
onNav = { backStack.add(it) },
|
||||
numUpdates = numUpdates,
|
||||
isBigScreen = isBigScreen,
|
||||
onSearch = viewModel::search,
|
||||
onSearchCleared = viewModel::onSearchCleared,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
entry<NavigationKey.MyApps>(
|
||||
metadata = ListDetailSceneStrategy.listPane("appdetails") {
|
||||
Text(stringResource(R.string.no_app_selected))
|
||||
},
|
||||
) {
|
||||
val myAppsViewModel = hiltViewModel<MyAppsViewModel>()
|
||||
val myAppsInfo = object : MyAppsInfo {
|
||||
override val model = myAppsViewModel.myAppsModel.collectAsStateWithLifecycle().value
|
||||
|
||||
override fun refresh() = myAppsViewModel.refresh()
|
||||
override fun updateAll() = myAppsViewModel.updateAll()
|
||||
override fun changeSortOrder(sort: AppListSortOrder) =
|
||||
myAppsViewModel.changeSortOrder(sort)
|
||||
|
||||
override fun search(query: String) = myAppsViewModel.search(query)
|
||||
override fun confirmAppInstall(
|
||||
packageName: String,
|
||||
state: InstallState.UserConfirmationNeeded,
|
||||
) = myAppsViewModel.confirmAppInstall(packageName, state)
|
||||
}
|
||||
MyApps(
|
||||
myAppsInfo = myAppsInfo,
|
||||
currentPackageName = if (isBigScreen) {
|
||||
(backStack.last() as? NavigationKey.AppDetails)?.packageName
|
||||
} else null,
|
||||
onAppItemClick = {
|
||||
backStack.add(NavigationKey.AppDetails(it))
|
||||
},
|
||||
onNav = { backStack.add(it) },
|
||||
isBigScreen = isBigScreen,
|
||||
)
|
||||
}
|
||||
entry<NavigationKey.AppDetails>(
|
||||
metadata = ListDetailSceneStrategy.detailPane("appdetails")
|
||||
) {
|
||||
val appDetailsViewModel = hiltViewModel<AppDetailsViewModel>()
|
||||
LaunchedEffect(it.packageName) {
|
||||
appDetailsViewModel.setAppDetails(it.packageName)
|
||||
}
|
||||
AppDetails(
|
||||
item = appDetailsViewModel.appDetails.collectAsStateWithLifecycle().value,
|
||||
onNav = { navKey -> backStack.add(navKey) },
|
||||
onBackNav = if (isBigScreen) null else {
|
||||
{ backStack.removeLastOrNull() }
|
||||
},
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
entry<NavigationKey.AppList>(
|
||||
metadata = ListDetailSceneStrategy.listPane("appdetails") {
|
||||
Text(stringResource(R.string.no_app_selected))
|
||||
},
|
||||
) {
|
||||
val appListViewModel = hiltViewModel<AppListViewModel>()
|
||||
LaunchedEffect(it.type) {
|
||||
appListViewModel.load(it.type)
|
||||
}
|
||||
val appListInfo = object : AppListInfo {
|
||||
override val model =
|
||||
appListViewModel.appListModel.collectAsStateWithLifecycle().value
|
||||
override val actions: AppListActions = appListViewModel
|
||||
override val list: AppListType =
|
||||
appListViewModel.currentList.collectAsStateWithLifecycle().value
|
||||
override val showFilters: Boolean =
|
||||
appListViewModel.showFilters.collectAsStateWithLifecycle().value
|
||||
override val showOnboarding: Boolean =
|
||||
appListViewModel.showOnboarding.collectAsStateWithLifecycle().value
|
||||
}
|
||||
AppList(
|
||||
appListInfo = appListInfo,
|
||||
currentPackageName = if (isBigScreen) {
|
||||
(backStack.last() as? NavigationKey.AppDetails)?.packageName
|
||||
} else null,
|
||||
onBackClicked = { backStack.removeLastOrNull() },
|
||||
modifier = Modifier,
|
||||
) { packageName ->
|
||||
backStack.add(NavigationKey.AppDetails(packageName))
|
||||
}
|
||||
}
|
||||
entry<NavigationKey.Repos>(
|
||||
metadata = ListDetailSceneStrategy.listPane("repos") {
|
||||
Text(text = stringResource(R.string.no_repository_selected))
|
||||
},
|
||||
) {
|
||||
val viewModel = hiltViewModel<RepositoriesViewModel>()
|
||||
val info = object : RepositoryInfo {
|
||||
override val model: RepositoryModel =
|
||||
viewModel.model.collectAsStateWithLifecycle().value
|
||||
|
||||
override val currentRepositoryId: Long? = if (isBigScreen) {
|
||||
(backStack.last() as? NavigationKey.RepoDetails)?.repoId
|
||||
} else null
|
||||
|
||||
override fun onOnboardingSeen() = viewModel.onOnboardingSeen()
|
||||
|
||||
override fun onRepositorySelected(repositoryItem: RepositoryItem) {
|
||||
backStack.add(NavigationKey.RepoDetails(repositoryItem.repoId))
|
||||
}
|
||||
|
||||
override fun onRepositoryEnabled(repoId: Long, enabled: Boolean) =
|
||||
viewModel.onRepositoryEnabled(repoId, enabled)
|
||||
|
||||
override fun onAddRepo() {
|
||||
backStack.add(NavigationKey.AddRepo())
|
||||
}
|
||||
|
||||
override fun onRepositoryMoved(fromRepoId: Long, toRepoId: Long) =
|
||||
viewModel.onRepositoriesMoved(fromRepoId, toRepoId)
|
||||
|
||||
override fun onRepositoriesFinishedMoving(
|
||||
fromRepoId: Long,
|
||||
toRepoId: Long,
|
||||
) = viewModel.onRepositoriesFinishedMoving(fromRepoId, toRepoId)
|
||||
}
|
||||
Repositories(info) {
|
||||
backStack.removeLastOrNull()
|
||||
}
|
||||
}
|
||||
entry<NavigationKey.RepoDetails>(
|
||||
metadata = ListDetailSceneStrategy.detailPane("repos")
|
||||
) { navKey ->
|
||||
val viewModel = hiltViewModel<RepoDetailsViewModel>()
|
||||
LaunchedEffect(navKey) {
|
||||
viewModel.setRepoId(navKey.repoId)
|
||||
}
|
||||
RepoDetails(
|
||||
info = object : RepoDetailsInfo {
|
||||
override val model =
|
||||
viewModel.model.collectAsStateWithLifecycle().value
|
||||
override val actions = viewModel
|
||||
},
|
||||
onShowAppsClicked = { title, repoId ->
|
||||
val type = AppListType.Repository(title, repoId)
|
||||
backStack.add(NavigationKey.AppList(type))
|
||||
},
|
||||
) {
|
||||
backStack.removeLastOrNull()
|
||||
}
|
||||
}
|
||||
entry<NavigationKey.AddRepo> { navKey ->
|
||||
val viewModel = hiltViewModel<AddRepoViewModel>()
|
||||
LaunchedEffect(navKey) {
|
||||
if (navKey.uri != null) {
|
||||
viewModel.onFetchRepo(navKey.uri)
|
||||
}
|
||||
}
|
||||
AddRepo(
|
||||
state = viewModel.state.collectAsStateWithLifecycle().value,
|
||||
onFetchRepo = viewModel::onFetchRepo,
|
||||
onAddRepo = viewModel::addFetchedRepository,
|
||||
onExistingRepo = { repoId ->
|
||||
backStack.removeLastOrNull()
|
||||
backStack.add(NavigationKey.RepoDetails(repoId))
|
||||
},
|
||||
onRepoAdded = { title, repoId ->
|
||||
backStack.removeLastOrNull()
|
||||
backStack.add(NavigationKey.RepoDetails(repoId))
|
||||
val type = AppListType.Repository(title, repoId)
|
||||
backStack.add(NavigationKey.AppList(type))
|
||||
},
|
||||
onBackClicked = { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
entry(NavigationKey.Settings) {
|
||||
val viewModel = hiltViewModel<SettingsViewModel>()
|
||||
Settings(
|
||||
onSaveLogcat = {
|
||||
viewModel.onSaveLogcat(it)
|
||||
backStack.removeLastOrNull()
|
||||
},
|
||||
onBackClicked = { backStack.removeLastOrNull() },
|
||||
)
|
||||
}
|
||||
entry(NavigationKey.About) {
|
||||
About { backStack.removeLastOrNull() }
|
||||
}
|
||||
}
|
||||
FDroidContent {
|
||||
HintHost {
|
||||
NavDisplay(
|
||||
backStack = backStack,
|
||||
sceneStrategy = listDetailStrategy,
|
||||
entryDecorators = listOf(
|
||||
rememberSaveableStateHolderNavEntryDecorator(),
|
||||
rememberViewModelStoreNavEntryDecorator(),
|
||||
),
|
||||
entryProvider = entryProvider,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user