From 29f5716664b44820a7c50dbd43796cc14c121050 Mon Sep 17 00:00:00 2001 From: Tinsae Date: Fri, 30 Jan 2026 22:21:01 +0100 Subject: [PATCH] progress to exporting filtered content --- .../java/net/tinsae/clocked/LoginScreen.kt | 2 +- .../java/net/tinsae/clocked/MainActivity.kt | 56 +++------------- .../biometric/BiometricAuthenticator.kt | 3 - .../ui/screens/anonymous/RegistrationForm.kt | 41 ++++++++++-- .../clocked/ui/screens/editor/EditorScreen.kt | 67 +++++++++++++++++++ .../ui/screens/editor/EditorViewModel.kt | 4 ++ app/src/main/res/values/strings.xml | 1 + 7 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorScreen.kt create mode 100644 app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorViewModel.kt diff --git a/app/src/main/java/net/tinsae/clocked/LoginScreen.kt b/app/src/main/java/net/tinsae/clocked/LoginScreen.kt index 677a184..719c15c 100644 --- a/app/src/main/java/net/tinsae/clocked/LoginScreen.kt +++ b/app/src/main/java/net/tinsae/clocked/LoginScreen.kt @@ -27,7 +27,7 @@ fun LoginScreen(viewModel: AuthViewModel) { modifier = modifier, uiState = uiState, onRegister = viewModel::signUp, - onTogleForm = viewModel::setFormType + onToggleForm = viewModel::setFormType ) } diff --git a/app/src/main/java/net/tinsae/clocked/MainActivity.kt b/app/src/main/java/net/tinsae/clocked/MainActivity.kt index 922d42c..2f182bd 100644 --- a/app/src/main/java/net/tinsae/clocked/MainActivity.kt +++ b/app/src/main/java/net/tinsae/clocked/MainActivity.kt @@ -23,10 +23,8 @@ import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -36,7 +34,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.capitalize import androidx.compose.ui.unit.dp import androidx.core.os.LocaleListCompat import androidx.lifecycle.lifecycleScope @@ -45,12 +42,10 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import net.tinsae.clocked.biometric.GlobalAuthenticator -import net.tinsae.clocked.ui.components.ShowLoadingScreen -import net.tinsae.clocked.ui.screens.dashboard.DashboardScreen import net.tinsae.clocked.data.Locale -import net.tinsae.clocked.data.LogRepository import net.tinsae.clocked.data.Theme import net.tinsae.clocked.ui.components.TopBar +import net.tinsae.clocked.ui.screens.dashboard.DashboardScreen import net.tinsae.clocked.ui.screens.history.HistoryScreen import net.tinsae.clocked.ui.screens.settings.SettingsScreen import net.tinsae.clocked.ui.screens.settings.SettingsViewModel @@ -92,17 +87,13 @@ class MainActivity : AppCompatActivity() { settingsViewModel.uiState .map { it.pendingCsvContent } .distinctUntilChanged() - .collect { csvContent -> + .collect { + csvContent -> if (csvContent != null) { val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", java.util.Locale.US).format(Date()) createDocumentLauncher.launch("Clocked-Export-$timestamp.csv") } } - /*authViewModel.sessionStatus.collect { - if (it is SessionStatus.Authenticated) { - LogRepository.subscribeRealTime() - } - }*/ } enableEdgeToEdge() @@ -114,23 +105,14 @@ class MainActivity : AppCompatActivity() { } - /*override fun onDestroy() { - super.onDestroy() - // When the app is being completely destroyed, ensure the connection is closed. - LogRepository.unsubscribeRealTime() - }*/ + } @Composable fun AppEntry(settingsViewModel: SettingsViewModel, authViewModel: AuthViewModel) { val settingsState by settingsViewModel.uiState.collectAsState() val sessionStatus by authViewModel.sessionStatus.collectAsState() - // Trigger fetching of logs when the session status changes. - LaunchedEffect(sessionStatus) { - if (sessionStatus is SessionStatus.Authenticated){ - //LogRepository. - } - } + val useDarkTheme = when (settingsState.theme) { @@ -148,21 +130,6 @@ fun AppEntry(settingsViewModel: SettingsViewModel, authViewModel: AuthViewModel) }else{ ClockedApp(settingsViewModel, authViewModel) } - /*when (sessionStatus) { - /*is SessionStatus.Initializing -> { - // Only show loading for the initial session check. - ShowLoadingScreen() - }*/ - - is SessionStatus.Authenticated -> { - // Just show the app. The ViewModels inside will manage their own loading UI. - ClockedApp(settingsViewModel, authViewModel) - } - - else -> { - LoginScreen(authViewModel) - } - }*/ } } @@ -180,7 +147,6 @@ fun updateLocale(context: Context, locale: Locale) { fun ClockedApp(settingsViewModel: SettingsViewModel, authViewModel: AuthViewModel) { var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) } - NavigationSuiteScaffold( modifier = Modifier.fillMaxSize(), navigationSuiteItems = { @@ -190,16 +156,18 @@ fun ClockedApp(settingsViewModel: SettingsViewModel, authViewModel: AuthViewMode Icon( imageVector = destination.icon, contentDescription = stringResource(destination.label), - modifier = Modifier.padding(1.dp).size(24.dp) + modifier = Modifier + //.padding(1.dp) + .size(24.dp) ) }, alwaysShowLabel = false, - label = { Text(stringResource(destination.label)) }, + //label = { Text(stringResource(destination.label)) }, selected = destination == currentDestination, onClick = { currentDestination = destination } ) } - } + }, ) { Scaffold( modifier = Modifier.fillMaxSize(), @@ -235,10 +203,6 @@ fun ClockedApp(settingsViewModel: SettingsViewModel, authViewModel: AuthViewMode modifier = modifier, viewModel = settingsViewModel ) - - /*AppDestinations.LOGOUT -> { - authViewModel.logout() - }*/ } } } diff --git a/app/src/main/java/net/tinsae/clocked/biometric/BiometricAuthenticator.kt b/app/src/main/java/net/tinsae/clocked/biometric/BiometricAuthenticator.kt index b678e1c..4aa5d5d 100644 --- a/app/src/main/java/net/tinsae/clocked/biometric/BiometricAuthenticator.kt +++ b/app/src/main/java/net/tinsae/clocked/biometric/BiometricAuthenticator.kt @@ -41,9 +41,6 @@ class BiometricAuthenticator(private val activity: FragmentActivity) { onSuccess() } - override fun onAuthenticationFailed() { - super.onAuthenticationFailed() - } }) when (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL)) { diff --git a/app/src/main/java/net/tinsae/clocked/ui/screens/anonymous/RegistrationForm.kt b/app/src/main/java/net/tinsae/clocked/ui/screens/anonymous/RegistrationForm.kt index 9458ebe..7c5e31c 100644 --- a/app/src/main/java/net/tinsae/clocked/ui/screens/anonymous/RegistrationForm.kt +++ b/app/src/main/java/net/tinsae/clocked/ui/screens/anonymous/RegistrationForm.kt @@ -42,11 +42,14 @@ fun RegistrationForm( modifier: Modifier = Modifier, uiState: AuthUiState, onRegister: (String, String, String) -> Unit, - onTogleForm: (FormType) -> Unit + onToggleForm: (FormType) -> Unit ) { var name by rememberSaveable { mutableStateOf("") } var email by rememberSaveable { mutableStateOf("") } var password by rememberSaveable { mutableStateOf("") } + var cPassword by rememberSaveable { mutableStateOf("") } + var error: String? by rememberSaveable { mutableStateOf(null) } + Scaffold(modifier = modifier.fillMaxSize()) { innerPadding -> Column( @@ -103,6 +106,31 @@ fun RegistrationForm( singleLine = true, isError = uiState.error != null ) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField( + value = cPassword, + onValueChange = { + run { + cPassword = it + error = if (it != password) { + "Passwords do not match" + } else { + null + } + } + }, + label = { Text(stringResource(R.string.confirm_password)) }, + modifier = Modifier.fillMaxWidth(), + visualTransformation = PasswordVisualTransformation(), + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), + singleLine = true, + isError = error != null, + supportingText = { + error?.let { + Text(text = it, color = MaterialTheme.colorScheme.error) + } + } + ) uiState.error?.let { Spacer(modifier = Modifier.height(8.dp)) @@ -112,7 +140,12 @@ fun RegistrationForm( Spacer(modifier = Modifier.height(32.dp)) Button( - onClick = { onRegister(name,email, password) }, + onClick = { + if (password == cPassword) { + onRegister(name, email, password) + error = null + } + }, modifier = Modifier.fillMaxWidth(), enabled = !uiState.isLoading ) { @@ -128,7 +161,7 @@ fun RegistrationForm( verticalAlignment = Alignment.CenterVertically ) { Text("Have an account?") - TextButton(onClick = { onTogleForm(FormType.LOGIN) }) { + TextButton(onClick = { onToggleForm(FormType.LOGIN) }) { Text("Sign in", color = Color.Blue) } } @@ -144,7 +177,7 @@ fun RegisterPreview(){ RegistrationForm( uiState = AuthUiState(), onRegister = { _, _, _ -> }, - onTogleForm = { _ ->} + onToggleForm = { _ ->} ) } } \ No newline at end of file diff --git a/app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorScreen.kt b/app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorScreen.kt new file mode 100644 index 0000000..7f1ef06 --- /dev/null +++ b/app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorScreen.kt @@ -0,0 +1,67 @@ +package net.tinsae.clocked.ui.screens.editor + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import net.tinsae.clocked.data.Log +import net.tinsae.clocked.ui.components.ListItem + +@Composable +private fun EditorScreen(modifier: Modifier = Modifier){ + + val viewModel = EditorViewModel() + Surface(modifier = modifier.padding(16.dp).fillMaxSize()) { + + FilterLogs(modifier = modifier, viewModel = viewModel) + + ShowLogs(modifier = modifier, logs = listOf()) + } +} + + + +@Composable +private fun FilterLogs(modifier: Modifier = Modifier, viewModel: EditorViewModel){ + Column(modifier = modifier) { + Text(modifier = Modifier.fillMaxWidth().padding(16.dp), text = "Filter") + Row(modifier = Modifier.fillMaxWidth()) { + Text(modifier = Modifier.weight(1f).padding(16.dp), text = "By date") + Text(modifier = Modifier.weight(1f).padding(16.dp), text = "from") + Text(modifier = Modifier.weight(1f).padding(16.dp), text = "to") + } + } +} + + +@Composable +private fun ShowLogs(logs: List, modifier: Modifier = Modifier){ + + LazyColumn { + items(logs, key = { it.id }) { log -> + ListItem( + modifier = Modifier.padding(horizontal = 16.dp), + log = log, + onEdit = { }, + onDelete = { }, + // When the item is clicked, set it as the selected log for the dialog + onClick = { } + ) + } + } +} + +@Preview +@Composable +private fun EditorPreview () { + EditorScreen(); +} diff --git a/app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorViewModel.kt b/app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorViewModel.kt new file mode 100644 index 0000000..00e9b5f --- /dev/null +++ b/app/src/main/java/net/tinsae/clocked/ui/screens/editor/EditorViewModel.kt @@ -0,0 +1,4 @@ +package net.tinsae.clocked.ui.screens.editor + +class EditorViewModel { +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a88e85..2ad8d46 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,5 +74,6 @@ Add a new entry Log out loading + Confirm password \ No newline at end of file