Skip to content

Commit

Permalink
Add About screen (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
X1nto authored Oct 28, 2023
1 parent 237a4ef commit 08cf3f9
Show file tree
Hide file tree
Showing 15 changed files with 349 additions and 7 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ src="fastlane/metadata/android/en-US/images/phoneScreenshots/6.png?raw=true">
src="fastlane/metadata/android/en-US/images/phoneScreenshots/7.png?raw=true">
<img width=200 alt="Account selection"
src="fastlane/metadata/android/en-US/images/phoneScreenshots/8.png?raw=true">
<img width=200 alt="Settings"
<img width=200 alt="Settings screen"
src="fastlane/metadata/android/en-US/images/phoneScreenshots/9.png?raw=true">
<img width=200 alt="About screen"
src="fastlane/metadata/android/en-US/images/phoneScreenshots/10.png?raw=true">

# Download
Mauth is available on F-Droid and GitHub Releases page.
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ android {

buildFeatures {
compose = true
buildConfig = true
}

composeOptions {
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/xinto/mauth/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.xinto.mauth.domain.SettingsRepository
import com.xinto.mauth.domain.account.model.DomainAccountInfo
import com.xinto.mauth.domain.otp.OtpRepository
import com.xinto.mauth.ui.navigation.MauthDestination
import com.xinto.mauth.ui.screen.about.AboutScreen
import com.xinto.mauth.ui.screen.account.AddAccountScreen
import com.xinto.mauth.ui.screen.account.EditAccountScreen
import com.xinto.mauth.ui.screen.auth.AuthScreen
Expand Down Expand Up @@ -162,6 +163,9 @@ class MainActivity : FragmentActivity() {
onSettingsClick = {
navigator.navigate(MauthDestination.Settings)
},
onAboutClick = {
navigator.navigate(MauthDestination.About)
},
onAccountEdit = {
navigator.navigate(MauthDestination.EditAccount(it))
}
Expand All @@ -186,6 +190,9 @@ class MainActivity : FragmentActivity() {
}
)
}
is MauthDestination.About -> {
AboutScreen(onBack = navigator::pop)
}
is MauthDestination.AddAccount -> {
AddAccountScreen(
prefilled = screen.params,
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/java/com/xinto/mauth/ui/component/Uri.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.xinto.mauth.ui.component

import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext

@Composable
fun rememberUriHandler(): UriHandler {
val context = LocalContext.current
return remember(context) {
UriHandler(context)
}
}

@Immutable
class UriHandler(private val context: Context) {

fun openUrl(url: String) {
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ sealed class MauthDestination(val isFullscreenDialog: Boolean = false) : Parcela
@Parcelize
data object Settings : MauthDestination()

@Parcelize
data object About : MauthDestination()

@Parcelize
data object PinSetup : MauthDestination()

Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/com/xinto/mauth/ui/screen/about/AboutLinks.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.xinto.mauth.ui.screen.about

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.runtime.Immutable
import com.xinto.mauth.R

@Immutable
data class AboutLink(
@DrawableRes
val icon: Int,

@StringRes
val title: Int,

val url: String
) {
companion object {
val defaultLinks = setOf(
AboutLink(
icon = R.drawable.ic_github,
title = R.string.about_links_source,
url = "https://github.com/X1nto/Mauth"
),
AboutLink(
icon = R.drawable.ic_bug,
title = R.string.about_links_feedback,
url = "https://github.com/X1nto/Mauth/issues"
),
)
}
}
115 changes: 115 additions & 0 deletions app/src/main/java/com/xinto/mauth/ui/screen/about/AboutScreen.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.xinto.mauth.ui.screen.about

import android.content.res.Configuration
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.xinto.mauth.BuildConfig
import com.xinto.mauth.R
import com.xinto.mauth.ui.component.rememberUriHandler
import com.xinto.mauth.ui.screen.about.component.LinkedButton
import com.xinto.mauth.ui.screen.about.component.LinkedButtonsRow
import com.xinto.mauth.ui.theme.MauthTheme

@Composable
fun AboutScreen(
modifier: Modifier = Modifier,
onBack: () -> Unit,
) {
val uriHandler = rememberUriHandler()
BackHandler(onBack = onBack)
Scaffold(
modifier = modifier,
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.about_title)) },
navigationIcon = {
IconButton(onClick = onBack) {
Icon(
painter = painterResource(R.drawable.ic_arrow_back),
contentDescription = null
)
}
}
)
}
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(it)
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Surface(
shape = CircleShape,
color = MaterialTheme.colorScheme.tertiaryContainer
) {
Icon(
modifier = Modifier.padding(0.dp),
painter = painterResource(R.drawable.ic_launcher_foreground),
contentDescription = null,
)
}
Text(
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.titleLarge
)
Text(
text = stringResource(R.string.about_version, BuildConfig.VERSION_NAME),
style = MaterialTheme.typography.bodyLarge,
color = LocalContentColor.current.copy(alpha = 0.7f)
)
LinkedButtonsRow(
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp)
) {
AboutLink.defaultLinks.forEach {
LinkedButton(
onClick = { uriHandler.openUrl(it.url) },
icon = {
Icon(
painter = painterResource(it.icon),
contentDescription = null
)
},
title = { Text(stringResource(it.title)) }
)
}
}
}
}
}

@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, showSystemUi = true)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showSystemUi = true)
@Composable
fun AboutScreenPreview() {
MauthTheme {
AboutScreen(onBack = {})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.xinto.mauth.ui.screen.about.component

import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.xinto.mauth.R
import com.xinto.mauth.ui.theme.MauthTheme

@Composable
fun LinkedButtonsRow(
modifier: Modifier = Modifier,
content: @Composable RowScope.() -> Unit
) {
Row(
modifier = modifier
.heightIn(min = 64.dp)
.clip(MaterialTheme.shapes.extraLarge),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(2.dp)
) {
content()
}
}

@Composable
fun RowScope.LinkedButton(
onClick: () -> Unit,
icon: @Composable () -> Unit,
title: @Composable () -> Unit,
modifier: Modifier = Modifier,
) {
Surface(
modifier = modifier.weight(1f),
onClick = onClick,
shape = MaterialTheme.shapes.extraSmall,
color = MaterialTheme.colorScheme.secondaryContainer
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier.size(24.dp),
propagateMinConstraints = true
) {
icon()
}
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodyLarge) {
title()
}
}
}
}

@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Composable
fun LinkedButtonsPreview() {
MauthTheme {
val data = remember {
listOf(
R.drawable.ic_info to "Info",
R.drawable.ic_edit to "Edit",
R.drawable.ic_settings to "Settings",
)
}
LinkedButtonsRow {
data.forEach {
LinkedButton(
onClick = { /*TODO*/ },
icon = {
Icon(
painter = painterResource(it.first),
contentDescription = null
)
},
title = {
Text(it.second)
}
)
}
}
}
}
13 changes: 9 additions & 4 deletions app/src/main/java/com/xinto/mauth/ui/screen/home/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ fun HomeScreen(
onAddAccountViaScanning: () -> Unit,
onAddAccountFromImage: (DomainAccountInfo) -> Unit,
onSettingsClick: () -> Unit,
onAboutClick: () -> Unit,
onAccountEdit: (UUID) -> Unit
) {
val viewModel: HomeViewModel = koinViewModel()
val state by viewModel.state.collectAsStateWithLifecycle()
val realTimeData by viewModel.realTimeData.collectAsStateWithLifecycle()
val selectedAccounts by viewModel.selectedAccounts.collectAsStateWithLifecycle()
val activeSortSetting by viewModel.activeSortSetting.collectAsStateWithLifecycle()

val photoPickerLauncher = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
viewModel.getAccountInfoFromQrUri(uri)?.let {
onAddAccountFromImage(it)
}
}
val state by viewModel.state.collectAsStateWithLifecycle()
val realTimeData by viewModel.realTimeData.collectAsStateWithLifecycle()
val selectedAccounts by viewModel.selectedAccounts.collectAsStateWithLifecycle()
val activeSortSetting by viewModel.activeSortSetting.collectAsStateWithLifecycle()
HomeScreen(
onAddAccountManually = onAddAccountManually,
onAddAccountViaScanning = onAddAccountViaScanning,
Expand All @@ -62,6 +64,7 @@ fun HomeScreen(
)
},
onSettingsClick = onSettingsClick,
onAboutClick = onAboutClick,
onAccountSelect = viewModel::toggleAccountSelection,
onCancelAccountSelection = viewModel::clearAccountSelection,
onDeleteSelectedAccounts = viewModel::deleteSelectedAccounts,
Expand All @@ -82,6 +85,7 @@ fun HomeScreen(
onAddAccountViaScanning: () -> Unit,
onAddAccountFromImage: () -> Unit,
onSettingsClick: () -> Unit,
onAboutClick: () -> Unit,
onAccountSelect: (UUID) -> Unit,
onCancelAccountSelection: () -> Unit,
onDeleteSelectedAccounts: () -> Unit,
Expand Down Expand Up @@ -117,6 +121,7 @@ fun HomeScreen(
showDeleteDialog = true
},
onSettingsClick = onSettingsClick,
onAboutClick = onAboutClick,
activeSortSetting = activeSortSetting,
onActiveSortChange = onActiveSortChange
)
Expand Down
Loading

0 comments on commit 08cf3f9

Please sign in to comment.