Skip to content

Commit

Permalink
* version bump;
Browse files Browse the repository at this point in the history
* handle already connected usb device & permission;
* clear inputs when UsbWriteResult is success;
* open app on device attach;
* update hash inputs concat;
* kotlin 1.8.0; gradle 8.0-rc-1;
  • Loading branch information
ryanamaral committed Jan 22, 2023
1 parent 3c45deb commit 0b6747f
Show file tree
Hide file tree
Showing 19 changed files with 162 additions and 120 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {
applicationId = "com.turtlpass"
minSdk = internal.Android.minSdk
targetSdk = internal.Android.targetSdk
versionCode = 10100
versionName = "1.1.0"
versionCode = 10200
versionName = "1.2.0"
vectorDrawables { useSupportLibrary = true }
missingDimensionStrategy("device", "anyDevice")
buildConfigField("Long", "TIMEOUT_MILLIS", "5000L")
Expand Down
7 changes: 4 additions & 3 deletions app/plugins/internal/src/main/kotlin/internal/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ package internal

object Versions {
const val jetpackCore = "1.9.0" // https://developer.android.com/jetpack/androidx/releases/core
const val ktxCore = "1.7.21" // https://kotlinlang.org/docs/releases.html#release-details
const val compose = "1.4.0-alpha02" // https://developer.android.com/jetpack/androidx/versions/all-channel
//|> 1.4.0-alpha02 compatible with Kotlin 1.7.21
const val ktxCore = "1.8.0" // https://kotlinlang.org/docs/releases.html#release-details
const val compose = "1.4.0" // https://developer.android.com/jetpack/androidx/versions/all-channel
//|> 1.4.0 compatible with Kotlin 1.8.0
const val jetpack = "1.4.0-alpha03"
const val ktxCoroutinesAndroid = "1.6.0"
const val hilt = "1.0.0"
const val hiltCore = "2.44" // https://github.com/google/dagger/releases
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ package internal.dependencies
import internal.Versions

object Compose {
const val material = "androidx.compose.material:material:1.4.0-alpha03"
const val material3 = "androidx.compose.material3:material3:1.1.0-alpha03"
const val materialIcons = "androidx.compose.material:material-icons-extended:1.4.0-alpha03"
const val ui = "androidx.compose.ui:ui:1.4.0-alpha03"
const val foundation = "androidx.compose.foundation:foundation:1.4.0-alpha03"
const val foundationLayout = "androidx.compose.foundation:foundation-layout:1.4.0-alpha03"
const val uiToolingPreview = "androidx.compose.ui:ui-tooling-preview:1.4.0-alpha03"
const val uiTooling = "androidx.compose.ui:ui-tooling:1.4.0-alpha03"
const val material = "androidx.compose.material:material:${Versions.jetpack}"
const val materialIcons = "androidx.compose.material:material-icons-extended:${Versions.jetpack}"
const val ui = "androidx.compose.ui:ui:${Versions.jetpack}"
const val foundation = "androidx.compose.foundation:foundation:${Versions.jetpack}"
const val foundationLayout = "androidx.compose.foundation:foundation-layout:${Versions.jetpack}"
const val uiToolingPreview = "androidx.compose.ui:ui-tooling-preview:${Versions.jetpack}"
const val uiTooling = "androidx.compose.ui:ui-tooling:${Versions.jetpack}"
const val runtime = "androidx.compose.runtime:runtime:${Versions.jetpack}"
const val animation = "androidx.compose.animation:animation:${Versions.jetpack}"
const val activityCompose = "androidx.activity:activity-compose:1.6.1"
const val runtime = "androidx.compose.runtime:runtime:${Versions.compose}"
const val animation = "androidx.compose.animation:animation:1.4.0-alpha03"
const val constraintLayout = "androidx.constraintlayout:constraintlayout-compose:1.0.1"
const val coil = "io.coil-kt:coil-compose:2.2.2"
const val lottie = "com.airbnb.android:lottie-compose:5.2.0"
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>

<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>

<!-- Accessibility Service -->
Expand Down
31 changes: 7 additions & 24 deletions app/src/main/kotlin/com/turtlpass/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,13 @@ class MainActivity : AppCompatActivity() {
uiState = viewModel.uiState.collectAsState(),
usbState = viewModel.usbState.collectAsState(),
permissionState = viewModel.permissionState.collectAsState(),
onInstalledApp = { app ->
viewModel.updateInstalledApp(app)
},
onRecentApp = { app ->
viewModel.selectRecentApp(app)
},
onUserAccount = { account ->
viewModel.updateUserAccount(account)
},
onStoredAccount = { account ->
viewModel.selectStoredAccount(account)
},
onRequestUsbPermission = {
viewModel.requestUsbPermissionUseCase(it)
},
onPinCompleted = { pin ->
viewModel.updatePin(pin)
},
onWriteUsbSerial = {
viewModel.writeUsbSerial()
},
finishApp = {
finishAffinity() // closes the app and keeps it in the Recent apps screen
}
onInstalledApp = { app -> viewModel.updateInstalledApp(app) },
onRecentApp = { app -> viewModel.selectRecentApp(app) },
onUserAccount = { account -> viewModel.updateUserAccount(account) },
onStoredAccount = { account -> viewModel.selectStoredAccount(account) },
onPinCompleted = { pin -> viewModel.updatePin(pin) },
onWriteUsbSerial = { viewModel.writeUsbSerial() },
finishApp = { finish() }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.turtlpass.module.chooser
import android.hardware.usb.UsbDevice

data class UsbState(
val isUsbConnected: Boolean = false,
val usbPermission: UsbPermission = UsbPermission.NotGranted,
val usbDevice: UsbDevice? = null,
val usbWriteResult: UsbWriteResult? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.turtlpass.module.chooser.ui

import android.content.res.Configuration
import android.hardware.usb.UsbDevice
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
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.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
Expand All @@ -23,7 +27,12 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.turtlpass.R
import com.turtlpass.common.compose.button.PrimaryButton
import com.turtlpass.common.domain.Result
import com.turtlpass.module.chooser.*
import com.turtlpass.module.chooser.AccountsPermission
import com.turtlpass.module.chooser.ChooserDestination
import com.turtlpass.module.chooser.ChooserUiState
import com.turtlpass.module.chooser.PermissionState
import com.turtlpass.module.chooser.UsbPermission
import com.turtlpass.module.chooser.UsbState
import com.turtlpass.module.chooser.model.ChooserInputs
import com.turtlpass.module.installedapp.model.InstalledApp
import com.turtlpass.module.useraccount.model.UserAccount
Expand All @@ -42,7 +51,6 @@ fun ChooserContentScreen(
onRecentApp: (app: InstalledApp) -> Unit,
onAccountSelected: (account: UserAccount?) -> Unit,
onStoredAccount: (account: UserAccount) -> Unit,
onRequestUsbPermission: (usbDevice: UsbDevice) -> Unit,
navController: NavHostController,
) {
val focusManager = LocalFocusManager.current
Expand Down Expand Up @@ -133,8 +141,6 @@ fun ChooserContentScreen(
NotificationsContainer(
permissionState = permissionState,
uiState = uiState,
usbState = usbState,
onRequestUsbPermission = onRequestUsbPermission
)
}
}
Expand Down Expand Up @@ -193,7 +199,6 @@ private fun Preview() {
permissionState = permissionsState,
onAccountSelected = {},
onStoredAccount = {},
onRequestUsbPermission = {},
onRecentApp = {},
navController = navController,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.turtlpass.module.chooser.ui

import android.content.res.Configuration
import android.hardware.usb.UsbDevice
import android.view.Window
import androidx.activity.compose.BackHandler
import androidx.compose.animation.ExperimentalAnimationApi
Expand All @@ -10,7 +9,14 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.ExperimentalTextApi
Expand All @@ -28,7 +34,12 @@ import com.turtlpass.MainActivity
import com.turtlpass.common.compose.rememberBottomSheetNavigator
import com.turtlpass.common.compose.systemui.SystemUi
import com.turtlpass.common.domain.Result
import com.turtlpass.module.chooser.*
import com.turtlpass.module.chooser.AccountsPermission
import com.turtlpass.module.chooser.ChooserDestination
import com.turtlpass.module.chooser.ChooserUiState
import com.turtlpass.module.chooser.PermissionState
import com.turtlpass.module.chooser.UsbPermission
import com.turtlpass.module.chooser.UsbState
import com.turtlpass.module.chooser.model.ChooserInputs
import com.turtlpass.module.installedapp.model.InstalledApp
import com.turtlpass.module.installedapp.ui.InstalledAppsScreen
Expand Down Expand Up @@ -61,7 +72,6 @@ fun ChooserScreen(
onRecentApp: (app: InstalledApp) -> Unit,
onUserAccount: (account: UserAccount?) -> Unit,
onStoredAccount: (account: UserAccount) -> Unit,
onRequestUsbPermission: (usbDevice: UsbDevice) -> Unit,
onPinCompleted: (pin: List<Int>) -> Unit,
onWriteUsbSerial: () -> Unit,
finishApp: () -> Unit,
Expand Down Expand Up @@ -134,7 +144,6 @@ fun ChooserScreen(
onUserAccount(account)
},
navController = navController,
onRequestUsbPermission = onRequestUsbPermission,
)
}

Expand Down Expand Up @@ -173,7 +182,7 @@ fun ChooserScreen(
bottomSheet(route = ChooserDestination.SheetPin.name) {
UserPinScreen(onPinCompleted = { pin ->
onPinCompleted(pin)
if (usbState.value.usbDevice != null
if (usbState.value.isUsbConnected
&& usbState.value.usbPermission == UsbPermission.Granted
) {
navController.navigate(ChooserDestination.SheetLoader.name)
Expand All @@ -187,9 +196,6 @@ fun ChooserScreen(
bottomSheet(route = ChooserDestination.SheetConnectUsb.name) {
ConnectUsbScreen(
usbState = usbState,
onRequestUsbPermission = { usbDevice ->
onRequestUsbPermission(usbDevice)
},
onReadyClick = {
navController.navigate(ChooserDestination.SheetLoader.name)
onWriteUsbSerial()
Expand Down Expand Up @@ -265,7 +271,6 @@ private fun Preview() {
onRecentApp = {},
onUserAccount = {},
onStoredAccount = {},
onRequestUsbPermission = {},
onPinCompleted = {},
onWriteUsbSerial = {},
finishApp = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.turtlpass.module.chooser.ui

import android.content.Intent
import android.content.res.Configuration
import android.hardware.usb.UsbDevice
import android.net.Uri
import android.provider.Settings
import androidx.compose.animation.AnimatedVisibility
Expand All @@ -21,7 +20,11 @@ import androidx.compose.ui.tooling.preview.Preview
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.turtlpass.R
import com.turtlpass.common.domain.Result
import com.turtlpass.module.chooser.*
import com.turtlpass.module.chooser.AccountsPermission
import com.turtlpass.module.chooser.ChooserUiState
import com.turtlpass.module.chooser.PermissionState
import com.turtlpass.module.chooser.UsbPermission
import com.turtlpass.module.chooser.UsbState
import com.turtlpass.module.chooser.model.ChooserInputs
import com.turtlpass.module.installedapp.model.InstalledApp
import com.turtlpass.module.useraccount.model.UserAccount
Expand All @@ -32,31 +35,14 @@ import com.turtlpass.theme.AppTheme
fun NotificationsContainer(
modifier: Modifier = Modifier,
uiState: State<ChooserUiState>,
usbState: State<UsbState>,
permissionState: State<PermissionState>,
onRequestUsbPermission: (usbDevice: UsbDevice) -> Unit
) {
val context = LocalContext.current

Column(
modifier = modifier
.verticalScroll(rememberScrollState())
) {
// USB Permission
AnimatedVisibility(
visible = usbState.value.usbDevice != null
&& usbState.value.usbPermission == UsbPermission.NotGranted
) {
ActionCard(
text = stringResource(R.string.rationale_usb),
buttonText = stringResource(R.string.rationale_usb_button),
onClick = {
usbState.value.usbDevice?.let { usbDevice ->
onRequestUsbPermission(usbDevice)
}
},
)
}
// Accounts Permission
AccountsPermissionCard(
permissionState = permissionState,
Expand Down Expand Up @@ -121,9 +107,7 @@ private fun Preview() {

NotificationsContainer(
uiState = uiState,
usbState = usbState,
permissionState = permissionsState,
onRequestUsbPermission = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ fun PulseHeader(
tint = colors.default.accent,
initialValue = 0.35f,
bounded = false,
enabled = usbState.value.usbDevice != null
&& usbState.value.usbPermission == UsbPermission.Granted
enabled = usbState.value.isUsbConnected
)
Row(
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ class HashUserInputUseCase @Inject constructor(
operator fun invoke(chooserInputs: ChooserInputs): Flow<String> {
return flow {
val packageName = chooserInputs.installedApp?.packageName ?: ""
val pin = chooserInputs.pin ?: ""
val topLevelDomain = chooserInputs.installedApp?.topLevelDomain ?: ""
val accountId = chooserInputs.userAccount?.accountId ?: ""
val pin = chooserInputs.pin ?: ""
accountRepository.persistAccountId(packageName, accountId)
val hash = sha512(topLevelDomain + accountId + pin)
val hash = sha512(pin + topLevelDomain + accountId)
delay(2000L)
emit(hash)
}.catch {
Expand Down
Loading

0 comments on commit 0b6747f

Please sign in to comment.