More onboarding screen additions

This commit is contained in:
arkon 2023-12-09 17:49:35 -05:00
parent 8b57169e92
commit e3404cd3d3
8 changed files with 114 additions and 19 deletions

View file

@ -2,7 +2,7 @@ package eu.kanade.presentation.crash
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.BugReport
@ -47,7 +47,7 @@ fun CrashScreen(
modifier = Modifier
.padding(vertical = MaterialTheme.padding.small)
.clip(MaterialTheme.shapes.small)
.fillMaxWidth()
.fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceVariant),
) {
Text(

View file

@ -0,0 +1,47 @@
package eu.kanade.presentation.more.onboarding
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.i18n.stringResource
@Composable
internal fun GuidesStep(
onRestoreBackup: () -> Unit,
) {
val handler = LocalUriHandler.current
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(stringResource(MR.strings.onboarding_guides_new_user, stringResource(MR.strings.app_name)))
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { handler.openUri(GETTING_STARTED_URL) },
) {
Text(stringResource(MR.strings.getting_started_guide))
}
HorizontalDivider()
Text(stringResource(MR.strings.onboarding_guides_returning_user, stringResource(MR.strings.app_name)))
Button(
modifier = Modifier.fillMaxWidth(),
onClick = onRestoreBackup,
) {
Text(stringResource(MR.strings.pref_restore_backup))
}
}
}
const val GETTING_STARTED_URL = "https://tachiyomi.org/docs/guides/getting-started"

View file

@ -1,18 +1,27 @@
package eu.kanade.presentation.more.onboarding
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.RocketLaunch
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import eu.kanade.domain.ui.UiPreferences
import soup.compose.material.motion.animation.materialSharedAxisX
import soup.compose.material.motion.animation.rememberSlideDistance
import tachiyomi.domain.storage.service.StoragePreferences
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.InfoScreen
@ -21,16 +30,20 @@ fun OnboardingScreen(
storagePreferences: StoragePreferences,
uiPreferences: UiPreferences,
onComplete: () -> Unit,
onRestoreBackup: () -> Unit,
) {
var currentStep by remember { mutableIntStateOf(0) }
val steps: List<@Composable () -> Unit> = listOf(
{ ThemeStep(uiPreferences = uiPreferences) },
{ StorageStep(storagePref = storagePreferences.baseStorageDirectory()) },
// TODO: prompt for notification permissions when bumping target to Android 13
{ GuidesStep(onRestoreBackup = onRestoreBackup) },
)
val isLastStep = currentStep == steps.size - 1
val slideDistance = rememberSlideDistance()
BackHandler(enabled = currentStep != 0, onBack = { currentStep-- })
InfoScreen(
icon = Icons.Outlined.RocketLaunch,
headingText = stringResource(MR.strings.onboarding_heading),
@ -52,17 +65,25 @@ fun OnboardingScreen(
rejectText = stringResource(MR.strings.onboarding_action_skip),
onRejectClick = onComplete,
) {
AnimatedContent(
targetState = currentStep,
transitionSpec = {
materialSharedAxisX(
forward = true,
slideDistance = slideDistance,
)
},
label = "stepContent",
Box(
modifier = Modifier
.padding(vertical = MaterialTheme.padding.small)
.clip(MaterialTheme.shapes.small)
.fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceVariant),
) {
steps[it]()
AnimatedContent(
targetState = currentStep,
transitionSpec = {
materialSharedAxisX(
forward = true,
slideDistance = slideDistance,
)
},
label = "stepContent",
) {
steps[it]()
}
}
}
}

View file

@ -3,8 +3,11 @@ package eu.kanade.presentation.more.onboarding
import android.content.ActivityNotFoundException
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.more.settings.screen.SettingsDataScreen
@ -22,11 +25,19 @@ internal fun StorageStep(
val pickStorageLocation = SettingsDataScreen.storageLocationPicker(storagePref)
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(stringResource(MR.strings.onboarding_storage_info))
Text(
stringResource(
MR.strings.onboarding_storage_info,
stringResource(MR.strings.app_name),
SettingsDataScreen.storageLocationText(storagePref),
),
)
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
try {
pickStorageLocation.launch(null)
@ -35,7 +46,7 @@ internal fun StorageStep(
}
},
) {
Text(SettingsDataScreen.storageLocationText(storagePref))
Text(stringResource(MR.strings.onboarding_storage_action_select))
}
}
}

View file

@ -110,6 +110,10 @@ object SettingsDataScreen : SearchableSettings {
val context = LocalContext.current
val storageDir by storageDirPref.collectAsState()
if (storageDir == storageDirPref.defaultValue()) {
return stringResource(MR.strings.no_location_set)
}
return remember(storageDir) {
val file = UniFile.fromUri(context, storageDir.toUri())
file?.filePath ?: file?.uri?.toString()

View file

@ -33,6 +33,7 @@ import eu.kanade.presentation.library.LibrarySettingsDialog
import eu.kanade.presentation.library.components.LibraryContent
import eu.kanade.presentation.library.components.LibraryToolbar
import eu.kanade.presentation.manga.components.LibraryBottomActionMenu
import eu.kanade.presentation.more.onboarding.GETTING_STARTED_URL
import eu.kanade.presentation.util.Tab
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
@ -163,7 +164,7 @@ object LibraryTab : Tab {
EmptyScreenAction(
stringRes = MR.strings.getting_started_guide,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = { handler.openUri("https://tachiyomi.org/docs/guides/getting-started") },
onClick = { handler.openUri(GETTING_STARTED_URL) },
),
),
)

View file

@ -8,6 +8,7 @@ import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.more.onboarding.OnboardingScreen
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.ui.setting.SettingsScreen
import tachiyomi.domain.storage.service.StoragePreferences
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -22,12 +23,18 @@ class OnboardingScreen : Screen() {
val storagePreferences = remember { Injekt.get<StoragePreferences>() }
val uiPreferences = remember { Injekt.get<UiPreferences>() }
val finishOnboarding = {
basePreferences.shownOnboardingFlow().set(true)
navigator.pop()
}
OnboardingScreen(
storagePreferences = storagePreferences,
uiPreferences = uiPreferences,
onComplete = {
basePreferences.shownOnboardingFlow().set(true)
navigator.pop()
onComplete = { finishOnboarding() },
onRestoreBackup = {
finishOnboarding()
navigator.push(SettingsScreen.toDataAndStorageScreen())
},
)
}

View file

@ -180,7 +180,10 @@
<string name="onboarding_action_next">Next</string>
<string name="onboarding_action_finish">Get started</string>
<string name="onboarding_action_skip">Skip</string>
<string name="onboarding_storage_info">Select a storage location where chapter downloads, backups, and local source content will be stored.</string>
<string name="onboarding_storage_info">Select a folder where %1$s will store chapter downloads, backups, and more.\n\nA dedicated folder is recommended.\n\nSelected folder: %2$s</string>
<string name="onboarding_storage_action_select">Select a folder</string>
<string name="onboarding_guides_new_user">New to %s? We recommend checking out the getting started guide.</string>
<string name="onboarding_guides_returning_user">Already used %s before?</string>
<!-- Preferences -->
<!-- Subsections -->
@ -439,6 +442,7 @@
<string name="pref_remove_after_read">After reading automatically delete</string>
<string name="pref_remove_bookmarked_chapters">Allow deleting bookmarked chapters</string>
<string name="pref_remove_exclude_categories">Excluded categories</string>
<string name="no_location_set">No storage location set</string>
<string name="invalid_location">Invalid location: %s</string>
<string name="disabled">Disabled</string>
<string name="last_read_chapter">Last read chapter</string>