Scaffold native Android build and enforce Rust boundaries (#89)
Dependency security audit / rustsec (push) Failing after 22s
Dependency security audit / rustsec (push) Failing after 22s
This commit is contained in:
1 parent
30d9119302
commit
e079b82b15
62 files changed
+5822
No files matched your search
@@ -0,0 +1,32 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.isHeading
|
||||
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
import de.rfc1437.ironstorage.core.ShellFixtures
|
||||
import de.rfc1437.ironstorage.core.ShellState
|
||||
import de.rfc1437.ironstorage.core.ShellTab
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class ShellScreenTest {
|
||||
@get:Rule val compose = createAndroidComposeRule<MainActivity>()
|
||||
|
||||
@Test
|
||||
fun allRustFixtureStatesRender() {
|
||||
ShellState.entries.forEach { state ->
|
||||
compose.onNodeWithText("Fixture: ${state.name}").performScrollTo().performClick()
|
||||
ShellTab.entries.forEach { tab ->
|
||||
compose.onNode(
|
||||
hasText(tab.name) and androidx.compose.ui.test.isSelectable()
|
||||
).performClick()
|
||||
val page = ShellFixtures.all.getValue(state).first { it.tab == tab }
|
||||
compose.onNode(hasText(page.stateTitle) and isHeading()).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import de.rfc1437.ironstorage.core.ShellFixtures
|
||||
import de.rfc1437.ironstorage.core.ShellRepository
|
||||
import de.rfc1437.ironstorage.core.ShellSnapshot
|
||||
import de.rfc1437.ironstorage.core.ShellState
|
||||
import de.rfc1437.ironstorage.core.ShellTab
|
||||
import javax.inject.Singleton
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class DebugShellRepository : ShellRepository {
|
||||
private val mutableSnapshot =
|
||||
MutableStateFlow(
|
||||
ShellSnapshot(ShellState.Empty, ShellFixtures.all.getValue(ShellState.Empty))
|
||||
)
|
||||
override val snapshot: StateFlow<ShellSnapshot> = mutableSnapshot
|
||||
|
||||
override fun selectTab(tab: ShellTab) {
|
||||
mutableSnapshot.value = mutableSnapshot.value.copy(selectedTab = tab)
|
||||
}
|
||||
|
||||
fun showFixture(state: ShellState) {
|
||||
mutableSnapshot.value =
|
||||
mutableSnapshot.value.copy(state = state, pages = ShellFixtures.all.getValue(state))
|
||||
}
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object DebugShellModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun shellRepository(): ShellRepository = DebugShellRepository()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import de.rfc1437.ironstorage.core.ShellRepository
|
||||
import de.rfc1437.ironstorage.core.ShellState
|
||||
import de.rfc1437.ironstorage.features.ShellScreen
|
||||
import de.rfc1437.ironstorage.features.ShellViewModel
|
||||
|
||||
@Composable
|
||||
fun VariantContent(viewModel: ShellViewModel, repository: ShellRepository) {
|
||||
Column(Modifier.statusBarsPadding()) {
|
||||
Row(Modifier.horizontalScroll(rememberScrollState())) {
|
||||
ShellState.entries.forEach { state ->
|
||||
TextButton(onClick = { (repository as DebugShellRepository).showFixture(state) }) {
|
||||
Text("Fixture: ${state.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
ShellScreen(viewModel)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:name=".IronStorageApplication"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.IronStorage"
|
||||
android:usesCleartextTraffic="false">
|
||||
<activity android:name=".MainActivity" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,7 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import android.app.Application
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
@HiltAndroidApp
|
||||
class IronStorageApplication : Application()
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import de.rfc1437.ironstorage.core.ShellRepository
|
||||
import de.rfc1437.ironstorage.features.ShellViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
@Inject lateinit var repository: ShellRepository
|
||||
|
||||
private val viewModel: ShellViewModel by viewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
MaterialTheme {
|
||||
VariantContent(viewModel, repository)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -0,0 +1,3 @@
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/ic_vault"
|
||||
android:inset="18dp" />
|
||||
@@ -0,0 +1,8 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp" android:height="108dp"
|
||||
android:viewportWidth="108" android:viewportHeight="108">
|
||||
<path android:fillColor="#00000000" android:strokeColor="#FFFFFFFF"
|
||||
android:strokeWidth="3" android:pathData="M54,24A30,30 0,1 1,54 84A30,30 0,1 1,54 24ZM54,31A23,23 0,1 1,54 77A23,23 0,1 1,54 31ZM54,41A13,13 0,1 1,54 67A13,13 0,1 1,54 41" />
|
||||
<path android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M52,41L56,41L56,52L66,58L64,62L54,56L44,62L42,58L52,52ZM50,50A5.7,5.7 0,1 1,58 58A5.7,5.7 0,1 1,50 50ZM79,37L85,37L85,71L79,71ZM73,39L79,39L79,44L73,44ZM73,64L79,64L79,69L73,69" />
|
||||
</vector>
|
||||
@@ -0,0 +1,5 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/icon_background" />
|
||||
<foreground android:drawable="@drawable/ic_vault_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_vault_monochrome" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<color name="icon_background">#30363F</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">IronStorage</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<resources>
|
||||
<style name="Theme.IronStorage" parent="android:style/Theme.Material.Light.NoActionBar">
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowActionModeOverlay">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,7 @@
|
||||
<full-backup-content>
|
||||
<exclude domain="root" path="." />
|
||||
<exclude domain="file" path="." />
|
||||
<exclude domain="database" path="." />
|
||||
<exclude domain="sharedpref" path="." />
|
||||
<exclude domain="external" path="." />
|
||||
</full-backup-content>
|
||||
@@ -0,0 +1,16 @@
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<exclude domain="root" path="." />
|
||||
<exclude domain="file" path="." />
|
||||
<exclude domain="database" path="." />
|
||||
<exclude domain="sharedpref" path="." />
|
||||
<exclude domain="external" path="." />
|
||||
</cloud-backup>
|
||||
<device-transfer>
|
||||
<exclude domain="root" path="." />
|
||||
<exclude domain="file" path="." />
|
||||
<exclude domain="database" path="." />
|
||||
<exclude domain="sharedpref" path="." />
|
||||
<exclude domain="external" path="." />
|
||||
</device-transfer>
|
||||
</data-extraction-rules>
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import de.rfc1437.ironstorage.core.ShellRepository
|
||||
import de.rfc1437.ironstorage.core.ShellSnapshot
|
||||
import de.rfc1437.ironstorage.core.ShellState
|
||||
import de.rfc1437.ironstorage.core.ShellTab
|
||||
import javax.inject.Singleton
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class ScaffoldShellRepository : ShellRepository {
|
||||
private val mutableSnapshot = MutableStateFlow(ShellSnapshot(ShellState.Empty, emptyList()))
|
||||
override val snapshot: StateFlow<ShellSnapshot> = mutableSnapshot
|
||||
|
||||
override fun selectTab(tab: ShellTab) {
|
||||
mutableSnapshot.value = mutableSnapshot.value.copy(selectedTab = tab)
|
||||
}
|
||||
}
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object ReleaseShellModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun shellRepository(): ShellRepository = ScaffoldShellRepository()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import de.rfc1437.ironstorage.core.ShellRepository
|
||||
import de.rfc1437.ironstorage.features.ShellScreen
|
||||
import de.rfc1437.ironstorage.features.ShellViewModel
|
||||
|
||||
@Composable
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun VariantContent(viewModel: ShellViewModel, repository: ShellRepository) {
|
||||
ShellScreen(viewModel)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package de.rfc1437.ironstorage
|
||||
|
||||
import de.rfc1437.ironstorage.core.ShellState
|
||||
import de.rfc1437.ironstorage.core.ShellTab
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class DebugShellRepositoryTest {
|
||||
@Test
|
||||
fun everyFixtureHasFivePagesAndSelectionSurvivesStateChanges() {
|
||||
val repository = DebugShellRepository()
|
||||
repository.selectTab(ShellTab.Totp)
|
||||
ShellState.entries.forEach { state ->
|
||||
repository.showFixture(state)
|
||||
assertEquals(state, repository.snapshot.value.state)
|
||||
assertEquals(ShellTab.entries, repository.snapshot.value.pages.map { it.tab })
|
||||
assertEquals(ShellTab.Totp, repository.snapshot.value.selectedTab)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user