diff --git a/app/build.gradle b/app/build.gradle index 0bbe8ab..5677c32 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'com.mikepenz.aboutlibraries.plugin' } Properties properties = new Properties() @@ -16,8 +17,8 @@ android { applicationId "com.henrikherzig.playintegritychecker" minSdk 26 targetSdk 33 - versionCode 6 - versionName "1.3.0" + versionCode 7 + versionName "1.4.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -87,6 +88,8 @@ dependencies { implementation "com.google.accompanist:accompanist-pager:0.23.1" + implementation "com.mikepenz:aboutlibraries-compose:10.5.2" + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/app/src/main/java/com/henrikherzig/playintegritychecker/ui/about/AboutPage.kt b/app/src/main/java/com/henrikherzig/playintegritychecker/ui/about/AboutPage.kt index 7357015..233afe0 100644 --- a/app/src/main/java/com/henrikherzig/playintegritychecker/ui/about/AboutPage.kt +++ b/app/src/main/java/com/henrikherzig/playintegritychecker/ui/about/AboutPage.kt @@ -3,25 +3,25 @@ package com.henrikherzig.playintegritychecker.ui.about import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Text +import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Code import androidx.compose.material.icons.outlined.OpenInNew +import androidx.compose.material.icons.outlined.ReadMore import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.navigation.NavHostController import com.henrikherzig.playintegritychecker.R -import androidx.compose.material.icons.outlined.ReadMore -import com.henrikherzig.playintegritychecker.ui.CustomButton -import com.henrikherzig.playintegritychecker.ui.CustomCard -import com.henrikherzig.playintegritychecker.ui.CustomCardTitle -import com.henrikherzig.playintegritychecker.ui.openLink +import com.henrikherzig.playintegritychecker.ui.* @Composable -fun AboutPage(playServiceVersion: String?) { +fun AboutPage(navController: NavHostController) { val context = LocalContext.current Box( modifier = Modifier @@ -86,11 +86,10 @@ fun AboutPage(playServiceVersion: String?) { Row( modifier = Modifier .fillMaxWidth(), - //.padding(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp) ) { /* workaround: .weight is not accessible in button directly and also not if box - is extracted to other method, have to investigate this */ + is extracted to other method */ Box( modifier = Modifier .fillMaxWidth() @@ -131,26 +130,35 @@ fun AboutPage(playServiceVersion: String?) { .fillMaxWidth() .weight(1f) ) { - /* Source Code Link */ + /* License */ + val openedRecognition = remember { mutableStateOf(false) } CustomButton( - { }, + { openedRecognition.value = true }, Icons.Outlined.ReadMore, stringResource(id = R.string.about_licenseButton) ) + if (openedRecognition.value) { + openedRecognition.value=false + navController.navigate("licence") { + + } + } } Box( modifier = Modifier .fillMaxWidth() .weight(1f) ) { - /* Play Integrity API Link */ + /* Privacy */ + val link = stringResource(id = R.string.about_privacyLink) CustomButton( - { }, + { openLink(link, context) }, Icons.Outlined.ReadMore, stringResource(id = R.string.about_privacyButton) // policy ) } } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/henrikherzig/playintegritychecker/ui/navigationbar/NavigationBarWrapper.kt b/app/src/main/java/com/henrikherzig/playintegritychecker/ui/navigationbar/NavigationBarWrapper.kt index 0af7059..3646c28 100644 --- a/app/src/main/java/com/henrikherzig/playintegritychecker/ui/navigationbar/NavigationBarWrapper.kt +++ b/app/src/main/java/com/henrikherzig/playintegritychecker/ui/navigationbar/NavigationBarWrapper.kt @@ -2,14 +2,21 @@ package com.henrikherzig.playintegritychecker.ui.navigationbar import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination @@ -22,12 +29,14 @@ import com.henrikherzig.playintegritychecker.R import com.henrikherzig.playintegritychecker.attestation.PlayIntegrityStatement import com.henrikherzig.playintegritychecker.attestation.safetynet.SafetyNetStatement import com.henrikherzig.playintegritychecker.dataStore +import com.henrikherzig.playintegritychecker.ui.CustomCardTitle import com.henrikherzig.playintegritychecker.ui.about.AboutPage import com.henrikherzig.playintegritychecker.ui.playintegrity.PlayIntegrity import com.henrikherzig.playintegritychecker.ui.safetynet.SafetyNet import com.henrikherzig.playintegritychecker.ui.ResponseType import com.henrikherzig.playintegritychecker.ui.settings.Settings import com.henrikherzig.playintegritychecker.ui.CustomViewModel +import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer @Composable fun BottomNavigationBar( @@ -47,6 +56,7 @@ fun BottomNavigationBar( BottomNavItem.Settings, BottomNavItem.About, ) + val navBackStackEntry by navController.currentBackStackEntryAsState() // TODO: very ugly better solution in the future // check @@ -87,6 +97,11 @@ fun BottomNavigationBar( } val urlValue = viewModel.stateURL.observeAsState().value + val appBarHorizontalPadding = 0.dp + val titleIconModifier = Modifier + .fillMaxHeight() + .width(72.dp - appBarHorizontalPadding) + Scaffold( topBar = { TopAppBar( @@ -95,30 +110,64 @@ fun BottomNavigationBar( * first line: short app name variant in bigger font * second line: full app name variant in smaller font */ + modifier= Modifier.fillMaxWidth(), title = { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center, - ) { - Text( - text = stringResource(id = R.string.app_name_short), - style = MaterialTheme.typography.subtitle2, - fontSize = 18.sp, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - Text( - text = stringResource(id = R.string.app_name), - style = MaterialTheme.typography.caption, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) + // TopAppBar Content + Box(Modifier.height(40.dp)) { + + // Navigation Icon + if (navBackStackEntry?.destination?.route == "licence") { + Row(titleIconModifier, verticalAlignment = Alignment.CenterVertically) { + IconButton( + onClick = { navController.navigateUp() }, + enabled = true, + ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Back", + ) + } + } + } + + // Title + Row(Modifier.fillMaxSize(), + verticalAlignment = Alignment.CenterVertically) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + ) { + Text( + text = stringResource(id = R.string.app_name_short), + style = MaterialTheme.typography.subtitle2, + fontSize = 18.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + Text( + text = stringResource(id = R.string.app_name), + style = MaterialTheme.typography.caption, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + + } + + } + + // Actions + /* CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { + Row( + Modifier.fillMaxHeight(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically, + ){} + } */ } }, - modifier = Modifier.fillMaxWidth() ) }, bottomBar = { BottomNavigation { - val navBackStackEntry by navController.currentBackStackEntryAsState() + // val navBackStackEntry by navController.currentBackStackEntryAsState() val currentDestination = navBackStackEntry?.destination appPages.forEach { screen -> BottomNavigationItem( @@ -134,7 +183,7 @@ fun BottomNavigationBar( // Avoid multiple versions of same page launchSingleTop = true // Restore state when selecting a previous page again - restoreState = true + // restoreState = true } } ) @@ -188,7 +237,17 @@ fun BottomNavigationBar( Settings(playServiceVersion) } composable(BottomNavItem.About.screen_route) { - AboutPage(playServiceVersion) + AboutPage(navController) + } + composable("licence") { + // Licenses Page + Column( + modifier = Modifier + .padding(all = 12.dp) + ) { + CustomCardTitle(stringResource(id = R.string.about_licenseButton)) + LibrariesContainer() + } } } } diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 31e0471..0ae014a 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -90,21 +90,15 @@ API Info Play Integrity - https://developer.android.com/google/play/integrity SafetyNet - https://developer.android.com/training/safetynet/attestation Source Code Android App - https://github.com/herzhenr/spic-android Check Server - https://github.com/herzhenr/spic-server Lizenz und Privatsphäre - Lizenz - TODO + Lizenzen Privatsphäre - https://github.com/herzhenr/spic-android/blob/main/privacyPolicy.md PlayIntegrity diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5597807..36230d5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -91,21 +91,20 @@ API Info Play Integrity - https://developer.android.com/google/play/integrity + https://developer.android.com/google/play/integrity SafetyNet - https://developer.android.com/training/safetynet/attestation + https://developer.android.com/training/safetynet/attestation Source Code Android App - https://github.com/herzhenr/spic-android + https://github.com/herzhenr/spic-android Check Server - https://github.com/herzhenr/spic-server + https://github.com/herzhenr/spic-server License and privacy policy - License - TODO + Licenses Privacy - https://github.com/herzhenr/spic-android/blob/main/privacyPolicy.md + https://github.com/herzhenr/spic-android/blob/main/privacyPolicy.md Play Integ. diff --git a/build.gradle b/build.gradle index e111beb..bd80072 100644 --- a/build.gradle +++ b/build.gradle @@ -3,11 +3,18 @@ buildscript { compose_version = '1.3.0-beta01' accompanist_version = '0.24.12-rc' } + repositories { + google() // maven { url "https://maven.google.com" } for Gradle <= 3 + } + dependencies { + classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6' + } }// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id 'com.android.application' version '7.2.2' apply false id 'com.android.library' version '7.2.2' apply false id 'org.jetbrains.kotlin.android' version '1.7.10' apply false + id 'com.mikepenz.aboutlibraries.plugin' version "10.5.2" apply false } task clean(type: Delete) {