From c064979832895762fcc009f76ca848dab7d007b6 Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Thu, 22 Feb 2024 14:20:23 +0000 Subject: [PATCH 1/7] rename savedItem val --- .../java/app/omnivore/omnivore/feature/library/LibraryView.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt index d749a709d..fea94ab3d 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/library/LibraryView.kt @@ -411,7 +411,7 @@ fun LibraryViewContent( dismissContent = { val selected = currentItem.savedItemId == selectedItem?.savedItem?.savedItemId - val test = SavedItemWithLabelsAndHighlights( + val savedItem = SavedItemWithLabelsAndHighlights( savedItem = cardDataWithLabels.savedItem, labels = cardDataWithLabels.labels, highlights = cardDataWithLabels.highlights @@ -419,7 +419,7 @@ fun LibraryViewContent( SavedItemCard( selected = selected, savedItemViewModel = libraryViewModel, - savedItem = test, + savedItem = savedItem, onClickHandler = { libraryViewModel.actionsMenuItemLiveData.postValue(null) val activityClass = From ddb85a4f6e2a4e826066690f70df706ce9e219b4 Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Thu, 22 Feb 2024 16:05:05 +0000 Subject: [PATCH 2/7] rename and format settings files --- .../omnivore/feature/root/RootView.kt | 4 +- .../omnivore/feature/settings/LogoutDialog.kt | 48 +++-- .../feature/settings/ManageAccount.kt | 16 +- .../feature/settings/PolicyWebView.kt | 98 ++++----- .../feature/settings/SettingsContent.kt | 175 ---------------- .../feature/settings/SettingsScreen.kt | 189 ++++++++++++++++++ .../feature/settings/SettingsViewModel.kt | 44 ++-- 7 files changed, 291 insertions(+), 283 deletions(-) delete mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsContent.kt create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt index f68b250b8..6c55b21ce 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt @@ -17,7 +17,7 @@ import app.omnivore.omnivore.feature.library.SearchView import app.omnivore.omnivore.feature.library.SearchViewModel import app.omnivore.omnivore.feature.save.SaveViewModel import app.omnivore.omnivore.feature.settings.PolicyWebView -import app.omnivore.omnivore.feature.settings.SettingsView +import app.omnivore.omnivore.feature.settings.SettingsScreen import app.omnivore.omnivore.feature.settings.SettingsViewModel import app.omnivore.omnivore.navigation.Routes @@ -84,7 +84,7 @@ fun PrimaryNavigator( } composable(Routes.Settings.route) { - SettingsView( + SettingsScreen( loginViewModel = loginViewModel, settingsViewModel = settingsViewModel, navController = navController diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt index 993944f8f..6c95a0092 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt @@ -12,31 +12,29 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions @Composable fun LogoutDialog(onClose: (Boolean) -> Unit) { - val context = LocalContext.current + val context = LocalContext.current - AlertDialog( - onDismissRequest = { onClose(false) }, - title = { Text(text = stringResource(R.string.logout_dialog_title)) }, - text = { - Text(stringResource(R.string.logout_dialog_confirm_msg)) - }, - confirmButton = { - Button(onClick = { - // Sign out google users - val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .build() + AlertDialog(onDismissRequest = { onClose(false) }, + title = { Text(text = stringResource(R.string.logout_dialog_title)) }, + text = { + Text(stringResource(R.string.logout_dialog_confirm_msg)) + }, + confirmButton = { + Button(onClick = { + // Sign out google users + val signInOptions = + GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build() - val googleSignIn = GoogleSignIn.getClient(context, signInOptions) - googleSignIn.signOut() - onClose(true) - }) { - Text(stringResource(R.string.logout_dialog_action_confirm)) - } - }, - dismissButton = { - Button(onClick = { onClose(false) }) { - Text(stringResource(R.string.logout_dialog_action_cancel)) - } - } - ) + val googleSignIn = GoogleSignIn.getClient(context, signInOptions) + googleSignIn.signOut() + onClose(true) + }) { + Text(stringResource(R.string.logout_dialog_action_confirm)) + } + }, + dismissButton = { + Button(onClick = { onClose(false) }) { + Text(stringResource(R.string.logout_dialog_action_cancel)) + } + }) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt index daeec8318..fddcb4a46 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt @@ -31,8 +31,7 @@ fun ManageAccountDialog(onDismiss: () -> Unit, settingsViewModel: SettingsViewMo Surface( shape = RoundedCornerShape(16.dp), color = Color.White, - modifier = Modifier - .height(300.dp) + modifier = Modifier.height(300.dp) ) { ManageAccountView(settingsViewModel = settingsViewModel) } @@ -42,26 +41,23 @@ fun ManageAccountDialog(onDismiss: () -> Unit, settingsViewModel: SettingsViewMo @Composable fun ManageAccountView(settingsViewModel: SettingsViewModel) { Column( - modifier = Modifier - .padding(top = 6.dp, start = 6.dp, end = 6.dp, bottom = 6.dp) + modifier = Modifier.padding(top = 6.dp, start = 6.dp, end = 6.dp, bottom = 6.dp) ) { Row( modifier = Modifier - .fillMaxWidth() - .padding(top = 12.dp, bottom = 12.dp), + .fillMaxWidth() + .padding(top = 12.dp, bottom = 12.dp), horizontalArrangement = Arrangement.Center ) { Text(stringResource(R.string.manage_account_title)) } Column( - modifier = Modifier - .verticalScroll(rememberScrollState()) + modifier = Modifier.verticalScroll(rememberScrollState()) ) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .clickable(onClick = { settingsViewModel.resetDataCache() }) + modifier = Modifier.clickable(onClick = { settingsViewModel.resetDataCache() }) ) { Text(stringResource(R.string.manage_account_action_reset_data_cache)) Spacer(modifier = Modifier.weight(1.0F)) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt index b7f7d6d8f..2839faa6d 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt @@ -8,70 +8,70 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Settings -import androidx.compose.material3.* +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.viewinterop.AndroidView import androidx.navigation.NavHostController -import app.omnivore.omnivore.navigation.Routes import app.omnivore.omnivore.R +import app.omnivore.omnivore.navigation.Routes @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "SetJavaScriptEnabled") @OptIn(ExperimentalMaterial3Api::class) @Composable fun PolicyWebView(navController: NavHostController, url: String) { - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.policy_webview_title)) }, - actions = { - IconButton(onClick = { navController.navigate(Routes.Settings.route) }) { - Icon( - imageVector = Icons.Default.Settings, - contentDescription = null - ) - } - }, colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant - ) - ) - } - ) { - val isDarkMode = isSystemInDarkTheme() - - Box { - AndroidView(factory = { - WebView(it).apply { - if (isDarkMode) { - setBackgroundColor(Color.Transparent.hashCode()) - } - - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - - settings.javaScriptEnabled = true - settings.allowContentAccess = true - settings.allowFileAccess = true - settings.domStorageEnabled = true - - alpha = 0.0f - - webViewClient = object : WebViewClient() { - override fun onPageFinished(view: WebView?, url: String?) { - super.onPageFinished(view, url) - view?.animate()?.alpha(1.0f)?.duration = 200 + Scaffold(topBar = { + TopAppBar(title = { Text(stringResource(R.string.policy_webview_title)) }, actions = { + IconButton(onClick = { navController.navigate(Routes.Settings.route) }) { + Icon( + imageVector = Icons.Default.Settings, contentDescription = null + ) } - } + }, colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) + ) + }) { + val isDarkMode = isSystemInDarkTheme() + + Box { + AndroidView(factory = { + WebView(it).apply { + if (isDarkMode) { + setBackgroundColor(Color.Transparent.hashCode()) + } + + layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT + ) + + settings.javaScriptEnabled = true + settings.allowContentAccess = true + settings.allowFileAccess = true + settings.domStorageEnabled = true + + alpha = 0.0f + + webViewClient = object : WebViewClient() { + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) + view?.animate()?.alpha(1.0f)?.duration = 200 + } + } // val themeID = if (isDarkMode) "Gray" else "LightGray" // loadUrl(url, mutableMapOf("Set-Cookie" to "theme=$themeID; Max-Age=31536000;")) - loadUrl(url, mutableMapOf()) + loadUrl(url, mutableMapOf()) + } + }, update = {}) } - }, update = {} - ) } - } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsContent.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsContent.kt deleted file mode 100644 index a2e34294d..000000000 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsContent.kt +++ /dev/null @@ -1,175 +0,0 @@ -package app.omnivore.omnivore.feature.settings - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Home -import androidx.compose.material3.* -import androidx.compose.runtime.* -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.unit.dp -import androidx.compose.ui.unit.sp -import androidx.navigation.NavHostController -import app.omnivore.omnivore.BuildConfig -import app.omnivore.omnivore.R -import app.omnivore.omnivore.navigation.Routes -import app.omnivore.omnivore.feature.auth.LoginViewModel - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun SettingsView( - loginViewModel: LoginViewModel, - settingsViewModel: SettingsViewModel, - navController: NavHostController, -) { - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.settings_view_title)) }, - actions = { - IconButton(onClick = { navController.navigate(Routes.Library.route) }) { - Icon( - imageVector = Icons.Default.Home, - contentDescription = null - ) - } - }, colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant - ) - ) - } - ) { paddingValues -> - SettingsViewContent( - loginViewModel = loginViewModel, - settingsViewModel = settingsViewModel, - navController = navController, - modifier = Modifier - .padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding() - ) - ) - } -} - -@Composable -fun SettingsViewContent(loginViewModel: LoginViewModel, settingsViewModel: SettingsViewModel, navController: NavHostController, modifier: Modifier) { - val showLogoutDialog = remember { mutableStateOf(false) } - val showManageAccountDialog = remember { mutableStateOf(false ) } - - Box( - modifier = modifier.fillMaxSize() - ) { - - val version = "Omnivore Version: " + BuildConfig.VERSION_NAME - - Column( - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.Start, - modifier = Modifier - .background(MaterialTheme.colorScheme.background) - .fillMaxSize() - .padding(horizontal = 6.dp) - .verticalScroll(rememberScrollState()) - ) { - - - SettingRow(text = stringResource(R.string.settings_view_setting_row_documentation)) { - navController.navigate(Routes.Documentation.route) - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_feedback)) { - settingsViewModel.presentIntercom() - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_privacy_policy)) { - navController.navigate(Routes.PrivacyPolicy.route) - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_terms_and_conditions)) { - navController.navigate(Routes.TermsAndConditions.route) - } - - SectionSpacer() - - SettingRow(text = stringResource(R.string.settings_view_setting_row_manage_account)) { - showManageAccountDialog.value = true - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_logout), includeIcon = false) { - showLogoutDialog.value = true - } - RowDivider() - - Text( - text = version, - fontSize = 12.sp, - modifier = Modifier - .padding(15.dp) - ) - } - - if (showLogoutDialog.value) { - LogoutDialog { performLogout -> - if (performLogout) { - loginViewModel.logout() - } - showLogoutDialog.value = false - } - } - - if (showManageAccountDialog.value) { - ManageAccountDialog( - onDismiss = { showManageAccountDialog.value = false }, - settingsViewModel = settingsViewModel - ) - } - } -} - -@Composable -private fun RowDivider() { - Divider( - modifier = Modifier.padding(horizontal = 12.dp), - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f) - ) -} - -@Composable -private fun SectionSpacer() { - RowDivider() - Spacer(Modifier.height(60.dp)) - RowDivider() -} - -@Composable -private fun SettingRow(text: String, includeIcon: Boolean = true, tapAction: () -> Unit) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clickable { tapAction() } - ) { - Text( - text = text, - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(16.dp), - style = MaterialTheme.typography.titleMedium - ) - - if (includeIcon) { - Icon( - painter = painterResource(id = R.drawable.chevron_right), - contentDescription = null - ) - } - } -} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt new file mode 100644 index 000000000..c4b8ec1ce --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt @@ -0,0 +1,189 @@ +package app.omnivore.omnivore.feature.settings + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +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.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavHostController +import app.omnivore.omnivore.BuildConfig +import app.omnivore.omnivore.R +import app.omnivore.omnivore.feature.auth.LoginViewModel +import app.omnivore.omnivore.navigation.Routes + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingsScreen( + loginViewModel: LoginViewModel, + settingsViewModel: SettingsViewModel, + navController: NavHostController, +) { + Scaffold(topBar = { + TopAppBar(title = { Text(stringResource(R.string.settings_view_title)) }, actions = { + IconButton(onClick = { navController.navigate(Routes.Library.route) }) { + Icon( + imageVector = Icons.Default.Home, contentDescription = null + ) + } + }, colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant + ) + ) + }) { paddingValues -> + SettingsViewContent( + loginViewModel = loginViewModel, + settingsViewModel = settingsViewModel, + navController = navController, + modifier = Modifier.padding( + top = paddingValues.calculateTopPadding(), + bottom = paddingValues.calculateBottomPadding() + ) + ) + } +} + +@Composable +fun SettingsViewContent( + loginViewModel: LoginViewModel, + settingsViewModel: SettingsViewModel, + navController: NavHostController, + modifier: Modifier +) { + val showLogoutDialog = remember { mutableStateOf(false) } + val showManageAccountDialog = remember { mutableStateOf(false) } + + Box( + modifier = modifier.fillMaxSize() + ) { + + val version = "Omnivore Version: " + BuildConfig.VERSION_NAME + + Column( + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.Start, + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + .fillMaxSize() + .padding(horizontal = 6.dp) + .verticalScroll(rememberScrollState()) + ) { + + + SettingRow(text = stringResource(R.string.settings_view_setting_row_documentation)) { + navController.navigate(Routes.Documentation.route) + } + RowDivider() + SettingRow(text = stringResource(R.string.settings_view_setting_row_feedback)) { + settingsViewModel.presentIntercom() + } + RowDivider() + SettingRow(text = stringResource(R.string.settings_view_setting_row_privacy_policy)) { + navController.navigate(Routes.PrivacyPolicy.route) + } + RowDivider() + SettingRow(text = stringResource(R.string.settings_view_setting_row_terms_and_conditions)) { + navController.navigate(Routes.TermsAndConditions.route) + } + + SectionSpacer() + + SettingRow(text = stringResource(R.string.settings_view_setting_row_manage_account)) { + showManageAccountDialog.value = true + } + RowDivider() + SettingRow( + text = stringResource(R.string.settings_view_setting_row_logout), + includeIcon = false + ) { + showLogoutDialog.value = true + } + RowDivider() + + Text( + text = version, fontSize = 12.sp, modifier = Modifier.padding(15.dp) + ) + } + + if (showLogoutDialog.value) { + LogoutDialog { performLogout -> + if (performLogout) { + loginViewModel.logout() + } + showLogoutDialog.value = false + } + } + + if (showManageAccountDialog.value) { + ManageAccountDialog( + onDismiss = { showManageAccountDialog.value = false }, + settingsViewModel = settingsViewModel + ) + } + } +} + +@Composable +private fun RowDivider() { + HorizontalDivider( + modifier = Modifier.padding(horizontal = 12.dp), + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f) + ) +} + +@Composable +private fun SectionSpacer() { + RowDivider() + Spacer(Modifier.height(60.dp)) + RowDivider() +} + +@Composable +private fun SettingRow(text: String, includeIcon: Boolean = true, tapAction: () -> Unit) { + Row(horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { tapAction() }) { + Text( + text = text, + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(16.dp), + style = MaterialTheme.typography.titleMedium + ) + + if (includeIcon) { + Icon( + painter = painterResource(id = R.drawable.chevron_right), contentDescription = null + ) + } + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt index 6dde3d23f..4f048e856 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt @@ -2,11 +2,11 @@ package app.omnivore.omnivore.feature.settings import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import app.omnivore.omnivore.utils.DatastoreKeys -import app.omnivore.omnivore.core.datastore.DatastoreRepository import app.omnivore.omnivore.core.data.DataService +import app.omnivore.omnivore.core.datastore.DatastoreRepository import app.omnivore.omnivore.core.network.Networker import app.omnivore.omnivore.core.network.viewer +import app.omnivore.omnivore.utils.DatastoreKeys import dagger.hilt.android.lifecycle.HiltViewModel import io.intercom.android.sdk.Intercom import io.intercom.android.sdk.IntercomSpace @@ -15,26 +15,26 @@ import javax.inject.Inject @HiltViewModel class SettingsViewModel @Inject constructor( - private val networker: Networker, - private val dataService: DataService, - private val datastoreRepo: DatastoreRepository -): ViewModel() { - fun resetDataCache() { - viewModelScope.launch { - datastoreRepo.clearValue(DatastoreKeys.libraryLastSyncTimestamp) - dataService.clearDatabase() - } - } - - fun presentIntercom() { - viewModelScope.launch { - val viewer = networker.viewer() - viewer?.let { v -> - v.intercomHash?.let { intercomHash -> - Intercom.client().setUserHash(intercomHash) + private val networker: Networker, + private val dataService: DataService, + private val datastoreRepo: DatastoreRepository +) : ViewModel() { + fun resetDataCache() { + viewModelScope.launch { + datastoreRepo.clearValue(DatastoreKeys.libraryLastSyncTimestamp) + dataService.clearDatabase() + } + } + + fun presentIntercom() { + viewModelScope.launch { + val viewer = networker.viewer() + viewer?.let { v -> + v.intercomHash?.let { intercomHash -> + Intercom.client().setUserHash(intercomHash) + } + Intercom.client().present(space = IntercomSpace.Messages) + } } - Intercom.client().present(space = IntercomSpace.Messages) - } } - } } From 9944acd63c896b76e7dc8990b51b5b8a9d6bcc86 Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Thu, 22 Feb 2024 17:52:35 +0000 Subject: [PATCH 3/7] restyle settings items --- .../omnivore/feature/root/RootView.kt | 8 +- .../feature/settings/ManageAccount.kt | 2 +- .../feature/settings/SettingsScreen.kt | 158 ++++++++---------- .../PolicyWebView.kt => web/WebViewScreen.kt} | 7 +- 4 files changed, 74 insertions(+), 101 deletions(-) rename android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/{settings/PolicyWebView.kt => web/WebViewScreen.kt} (91%) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt index 6c55b21ce..02567659d 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt @@ -16,9 +16,9 @@ import app.omnivore.omnivore.feature.library.LibraryView import app.omnivore.omnivore.feature.library.SearchView import app.omnivore.omnivore.feature.library.SearchViewModel import app.omnivore.omnivore.feature.save.SaveViewModel -import app.omnivore.omnivore.feature.settings.PolicyWebView import app.omnivore.omnivore.feature.settings.SettingsScreen import app.omnivore.omnivore.feature.settings.SettingsViewModel +import app.omnivore.omnivore.feature.web.WebViewScreen import app.omnivore.omnivore.navigation.Routes @Composable @@ -92,15 +92,15 @@ fun PrimaryNavigator( } composable(Routes.Documentation.route) { - PolicyWebView(navController = navController, url = "https://docs.omnivore.app") + WebViewScreen(navController = navController, url = "https://docs.omnivore.app") } composable(Routes.PrivacyPolicy.route) { - PolicyWebView(navController = navController, url = "https://omnivore.app/privacy") + WebViewScreen(navController = navController, url = "https://omnivore.app/privacy") } composable(Routes.TermsAndConditions.route) { - PolicyWebView(navController = navController, url = "https://omnivore.app/app/terms") + WebViewScreen(navController = navController, url = "https://omnivore.app/app/terms") } } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt index fddcb4a46..2d9da4b58 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt @@ -11,11 +11,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Refresh import androidx.compose.material3.Icon import androidx.compose.material3.Surface +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt index c4b8ec1ce..2f1714b92 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt @@ -1,20 +1,15 @@ package app.omnivore.omnivore.feature.settings -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.automirrored.outlined.ArrowBack import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -29,7 +24,6 @@ import androidx.compose.runtime.mutableStateOf 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.unit.dp import androidx.compose.ui.unit.sp @@ -41,31 +35,32 @@ import app.omnivore.omnivore.navigation.Routes @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SettingsScreen( +internal fun SettingsScreen( loginViewModel: LoginViewModel, settingsViewModel: SettingsViewModel, navController: NavHostController, ) { Scaffold(topBar = { - TopAppBar(title = { Text(stringResource(R.string.settings_view_title)) }, actions = { - IconButton(onClick = { navController.navigate(Routes.Library.route) }) { - Icon( - imageVector = Icons.Default.Home, contentDescription = null - ) - } - }, colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant - ) + TopAppBar( + title = { Text(stringResource(R.string.settings_view_title)) }, + navigationIcon = { + IconButton(onClick = { navController.navigateUp() }) { + Icon( + imageVector = Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = null + ) + } + + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ), ) }) { paddingValues -> SettingsViewContent( loginViewModel = loginViewModel, settingsViewModel = settingsViewModel, navController = navController, - modifier = Modifier.padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding() - ) + paddingValues = paddingValues ) } } @@ -75,61 +70,64 @@ fun SettingsViewContent( loginViewModel: LoginViewModel, settingsViewModel: SettingsViewModel, navController: NavHostController, - modifier: Modifier + paddingValues: PaddingValues ) { val showLogoutDialog = remember { mutableStateOf(false) } val showManageAccountDialog = remember { mutableStateOf(false) } - Box( - modifier = modifier.fillMaxSize() - ) { - + val state = rememberLazyListState() val version = "Omnivore Version: " + BuildConfig.VERSION_NAME - Column( - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.Start, - modifier = Modifier - .background(MaterialTheme.colorScheme.background) - .fillMaxSize() - .padding(horizontal = 6.dp) - .verticalScroll(rememberScrollState()) + LazyColumn( + state = state, + contentPadding = paddingValues, ) { - - SettingRow(text = stringResource(R.string.settings_view_setting_row_documentation)) { - navController.navigate(Routes.Documentation.route) - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_feedback)) { - settingsViewModel.presentIntercom() - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_privacy_policy)) { - navController.navigate(Routes.PrivacyPolicy.route) - } - RowDivider() - SettingRow(text = stringResource(R.string.settings_view_setting_row_terms_and_conditions)) { - navController.navigate(Routes.TermsAndConditions.route) + item { + SettingRow(text = stringResource(R.string.settings_view_setting_row_documentation)) { + navController.navigate(Routes.Documentation.route) + } } - SectionSpacer() - - SettingRow(text = stringResource(R.string.settings_view_setting_row_manage_account)) { - showManageAccountDialog.value = true + item { + SettingRow(text = stringResource(R.string.settings_view_setting_row_feedback)) { + settingsViewModel.presentIntercom() + } } - RowDivider() - SettingRow( - text = stringResource(R.string.settings_view_setting_row_logout), - includeIcon = false - ) { - showLogoutDialog.value = true - } - RowDivider() - Text( - text = version, fontSize = 12.sp, modifier = Modifier.padding(15.dp) - ) + item { + SettingRow(text = stringResource(R.string.settings_view_setting_row_privacy_policy)) { + navController.navigate(Routes.PrivacyPolicy.route) + } + } + + item { + SettingRow(text = stringResource(R.string.settings_view_setting_row_terms_and_conditions)) { + navController.navigate(Routes.TermsAndConditions.route) + } + } + + item { HorizontalDivider() } + + item { + SettingRow(text = stringResource(R.string.settings_view_setting_row_manage_account)) { + showManageAccountDialog.value = true + } + } + + item { + SettingRow( + text = stringResource(R.string.settings_view_setting_row_logout) + ) { + showLogoutDialog.value = true + } + } + + item { + Text( + text = version, fontSize = 12.sp, modifier = Modifier.padding(15.dp) + ) + } } if (showLogoutDialog.value) { @@ -147,26 +145,11 @@ fun SettingsViewContent( settingsViewModel = settingsViewModel ) } - } } -@Composable -private fun RowDivider() { - HorizontalDivider( - modifier = Modifier.padding(horizontal = 12.dp), - color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f) - ) -} @Composable -private fun SectionSpacer() { - RowDivider() - Spacer(Modifier.height(60.dp)) - RowDivider() -} - -@Composable -private fun SettingRow(text: String, includeIcon: Boolean = true, tapAction: () -> Unit) { +private fun SettingRow(text: String, tapAction: () -> Unit) { Row(horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = Modifier @@ -176,14 +159,7 @@ private fun SettingRow(text: String, includeIcon: Boolean = true, tapAction: () text = text, modifier = Modifier .align(Alignment.CenterVertically) - .padding(16.dp), - style = MaterialTheme.typography.titleMedium + .padding(16.dp) ) - - if (includeIcon) { - Icon( - painter = painterResource(id = R.drawable.chevron_right), contentDescription = null - ) - } } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/web/WebViewScreen.kt similarity index 91% rename from android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt rename to android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/web/WebViewScreen.kt index 2839faa6d..d0dfc0f9c 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/PolicyWebView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/web/WebViewScreen.kt @@ -1,4 +1,4 @@ -package app.omnivore.omnivore.feature.settings +package app.omnivore.omnivore.feature.web import android.annotation.SuppressLint import android.view.ViewGroup @@ -27,7 +27,7 @@ import app.omnivore.omnivore.navigation.Routes @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter", "SetJavaScriptEnabled") @OptIn(ExperimentalMaterial3Api::class) @Composable -fun PolicyWebView(navController: NavHostController, url: String) { +fun WebViewScreen(navController: NavHostController, url: String) { Scaffold(topBar = { TopAppBar(title = { Text(stringResource(R.string.policy_webview_title)) }, actions = { IconButton(onClick = { navController.navigate(Routes.Settings.route) }) { @@ -66,9 +66,6 @@ fun PolicyWebView(navController: NavHostController, url: String) { view?.animate()?.alpha(1.0f)?.duration = 200 } } - -// val themeID = if (isDarkMode) "Gray" else "LightGray" -// loadUrl(url, mutableMapOf("Set-Cookie" to "theme=$themeID; Max-Age=31536000;")) loadUrl(url, mutableMapOf()) } }, update = {}) From dd6860908b97afcbfc756aca5d18d3b46b18e7ec Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Fri, 23 Feb 2024 00:08:07 +0000 Subject: [PATCH 4/7] add about screen --- .../omnivore/feature/root/RootView.kt | 8 + .../omnivore/feature/settings/LogoHeader.kt | 34 ++++ .../feature/settings/SettingsScreen.kt | 150 +++++++++--------- .../feature/settings/about/AboutScreen.kt | 111 +++++++++++++ .../AccountScreen.kt} | 3 +- .../omnivore/omnivore/navigation/Routes.kt | 1 + .../app/src/main/res/drawable/ic_omnivore.xml | 11 ++ .../app/src/main/res/values/strings.xml | 5 + 8 files changed, 248 insertions(+), 75 deletions(-) create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt rename android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/{ManageAccount.kt => account/AccountScreen.kt} (95%) create mode 100644 android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt index 02567659d..9afd0ec0b 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt @@ -18,6 +18,7 @@ import app.omnivore.omnivore.feature.library.SearchViewModel import app.omnivore.omnivore.feature.save.SaveViewModel import app.omnivore.omnivore.feature.settings.SettingsScreen import app.omnivore.omnivore.feature.settings.SettingsViewModel +import app.omnivore.omnivore.feature.settings.about.AboutScreen import app.omnivore.omnivore.feature.web.WebViewScreen import app.omnivore.omnivore.navigation.Routes @@ -91,6 +92,13 @@ fun PrimaryNavigator( ) } + composable(Routes.About.route) { + AboutScreen( + navController = navController, + settingsViewModel = settingsViewModel + ) + } + composable(Routes.Documentation.route) { WebViewScreen(navController = navController, url = "https://docs.omnivore.app") } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt new file mode 100644 index 000000000..e32491e03 --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt @@ -0,0 +1,34 @@ +package app.omnivore.omnivore.feature.settings + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import app.omnivore.omnivore.R + +@Composable +fun LogoHeader() { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Icon( + painter = painterResource(R.drawable.ic_omnivore), + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurface, + modifier = Modifier + .padding(vertical = 56.dp) + .size(64.dp), + ) + + HorizontalDivider() + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt index 2f1714b92..22bc7b891 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt @@ -1,7 +1,7 @@ package app.omnivore.omnivore.feature.settings import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -11,7 +11,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -24,13 +23,15 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavHostController -import app.omnivore.omnivore.BuildConfig import app.omnivore.omnivore.R import app.omnivore.omnivore.feature.auth.LoginViewModel +import app.omnivore.omnivore.feature.settings.account.ManageAccountDialog import app.omnivore.omnivore.navigation.Routes @OptIn(ExperimentalMaterial3Api::class) @@ -46,7 +47,8 @@ internal fun SettingsScreen( navigationIcon = { IconButton(onClick = { navController.navigateUp() }) { Icon( - imageVector = Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = null + imageVector = Icons.AutoMirrored.Outlined.ArrowBack, + contentDescription = null ) } @@ -76,90 +78,90 @@ fun SettingsViewContent( val showManageAccountDialog = remember { mutableStateOf(false) } val state = rememberLazyListState() - val version = "Omnivore Version: " + BuildConfig.VERSION_NAME - LazyColumn( - state = state, - contentPadding = paddingValues, - ) { + LazyColumn( + state = state, + contentPadding = paddingValues, + ) { - item { - SettingRow(text = stringResource(R.string.settings_view_setting_row_documentation)) { - navController.navigate(Routes.Documentation.route) - } - } - - item { - SettingRow(text = stringResource(R.string.settings_view_setting_row_feedback)) { - settingsViewModel.presentIntercom() - } - } - - item { - SettingRow(text = stringResource(R.string.settings_view_setting_row_privacy_policy)) { - navController.navigate(Routes.PrivacyPolicy.route) - } - } - - item { - SettingRow(text = stringResource(R.string.settings_view_setting_row_terms_and_conditions)) { - navController.navigate(Routes.TermsAndConditions.route) - } - } - - item { HorizontalDivider() } - - item { - SettingRow(text = stringResource(R.string.settings_view_setting_row_manage_account)) { - showManageAccountDialog.value = true - } - } - - item { - SettingRow( - text = stringResource(R.string.settings_view_setting_row_logout) - ) { - showLogoutDialog.value = true - } - } - - item { - Text( - text = version, fontSize = 12.sp, modifier = Modifier.padding(15.dp) - ) + item { + SettingRow(title = stringResource(R.string.settings_view_setting_row_manage_account)) { + showManageAccountDialog.value = true } } - if (showLogoutDialog.value) { - LogoutDialog { performLogout -> - if (performLogout) { - loginViewModel.logout() - } - showLogoutDialog.value = false + item { + SettingRow( + title = stringResource(R.string.settings_view_setting_row_logout) + ) { + showLogoutDialog.value = true } } - if (showManageAccountDialog.value) { - ManageAccountDialog( - onDismiss = { showManageAccountDialog.value = false }, - settingsViewModel = settingsViewModel - ) + item { + SettingRow(title = stringResource(R.string.about_view_title)) { + navController.navigate(Routes.About.route) + } } + } + + if (showLogoutDialog.value) { + LogoutDialog { performLogout -> + if (performLogout) { + loginViewModel.logout() + } + showLogoutDialog.value = false + } + } + + if (showManageAccountDialog.value) { + ManageAccountDialog( + onDismiss = { showManageAccountDialog.value = false }, + settingsViewModel = settingsViewModel + ) + } } @Composable -private fun SettingRow(text: String, tapAction: () -> Unit) { - Row(horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, +internal fun SettingRow( + title: String, subtitle: String? = null, onClick: (() -> Unit)? +) { + Row( modifier = Modifier - .fillMaxWidth() - .clickable { tapAction() }) { - Text( - text = text, + .clickable(enabled = onClick != null, onClick = { onClick?.invoke() }) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically + ) { + Column( modifier = Modifier - .align(Alignment.CenterVertically) - .padding(16.dp) - ) + .weight(1f) + .padding(vertical = SettingsVerticalPadding) + ) { + Text( + modifier = Modifier.padding(horizontal = SettingsHorizontalPadding), + text = title, + overflow = TextOverflow.Ellipsis, + maxLines = 2, + style = MaterialTheme.typography.titleLarge, + fontSize = SettingsTitleFontSize, + ) + if (!subtitle.isNullOrBlank()) { + Text( + text = subtitle, + modifier = Modifier + .padding(horizontal = SettingsHorizontalPadding) + .alpha(SettingsSecondaryItemAlpha), + style = MaterialTheme.typography.bodySmall, + maxLines = 10, + ) + } + } } } + +internal val SettingsHorizontalPadding = 16.dp +internal val SettingsVerticalPadding = 16.dp +internal const val SettingsSecondaryItemAlpha = .78f +internal val SettingsTitleFontSize = 16.sp + +internal const val RELEASE_URL = "https://github.com/omnivore-app/omnivore/releases" diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt new file mode 100644 index 000000000..9e0b1220c --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt @@ -0,0 +1,111 @@ +package app.omnivore.omnivore.feature.settings.about + +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.stringResource +import androidx.navigation.NavHostController +import app.omnivore.omnivore.BuildConfig +import app.omnivore.omnivore.R +import app.omnivore.omnivore.feature.settings.LogoHeader +import app.omnivore.omnivore.feature.settings.RELEASE_URL +import app.omnivore.omnivore.feature.settings.SettingRow +import app.omnivore.omnivore.feature.settings.SettingsViewModel +import app.omnivore.omnivore.navigation.Routes + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun AboutScreen( + navController: NavHostController, + settingsViewModel: SettingsViewModel +) { + + val uriHandler = LocalUriHandler.current + + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.about_view_title)) }, + navigationIcon = { + IconButton(onClick = { navController.navigateUp() }) { + Icon( + imageVector = Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = null + ) + } + + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ), + ) + }, + ) { contentPadding -> + LazyColumn( + contentPadding = contentPadding, + ) { + item { + LogoHeader() + } + + item { + SettingRow( + title = stringResource(R.string.about_view_row_version), + subtitle = getVersionName(), + onClick = { }, + ) + } + + item { + SettingRow( + title = stringResource(R.string.about_view_row_whats_new), + onClick = { uriHandler.openUri(RELEASE_URL) }, + ) + } + + item { + SettingRow(title = stringResource(R.string.settings_view_setting_row_documentation)) { + navController.navigate(Routes.Documentation.route) + } + } + + item { + SettingRow(title = stringResource(R.string.settings_view_setting_row_feedback)) { + settingsViewModel.presentIntercom() + } + } + + item { + SettingRow(title = stringResource(R.string.settings_view_setting_row_privacy_policy)) { + navController.navigate(Routes.PrivacyPolicy.route) + } + } + + item { + SettingRow(title = stringResource(R.string.settings_view_setting_row_terms_and_conditions)) { + navController.navigate(Routes.TermsAndConditions.route) + } + } + } + } +} + +fun getVersionName(): String { + return when { + BuildConfig.DEBUG -> { + "Debug ${BuildConfig.VERSION_NAME}" + } + else -> { + "Stable ${BuildConfig.VERSION_NAME}" + } + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt similarity index 95% rename from android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt rename to android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt index 2d9da4b58..57d8cde41 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/ManageAccount.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt @@ -1,4 +1,4 @@ -package app.omnivore.omnivore.feature.settings +package app.omnivore.omnivore.feature.settings.account import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -24,6 +24,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import app.omnivore.omnivore.R +import app.omnivore.omnivore.feature.settings.SettingsViewModel @Composable fun ManageAccountDialog(onDismiss: () -> Unit, settingsViewModel: SettingsViewModel) { diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt index 62f1a780b..e10ee6e94 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt @@ -3,6 +3,7 @@ package app.omnivore.omnivore.navigation sealed class Routes(val route: String) { object Library : Routes("Library") object Settings : Routes("Settings") + object About : Routes("About") object Search : Routes("Search") object Documentation : Routes("Documentation") object PrivacyPolicy : Routes("PrivacyPolicy") diff --git a/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml b/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml new file mode 100644 index 000000000..8608e8300 --- /dev/null +++ b/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml @@ -0,0 +1,11 @@ + + + diff --git a/android/Omnivore/app/src/main/res/values/strings.xml b/android/Omnivore/app/src/main/res/values/strings.xml index d1cce247c..d737b53fd 100644 --- a/android/Omnivore/app/src/main/res/values/strings.xml +++ b/android/Omnivore/app/src/main/res/values/strings.xml @@ -212,6 +212,11 @@ Manage Account Logout + + About + Version + What\'s new + Inbox Non-Feed Items From 77f04ea0c3a5247f41c8460c6a73eebe6229d529 Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Fri, 23 Feb 2024 00:40:45 +0000 Subject: [PATCH 5/7] add social icons --- .../app/omnivore/omnivore/core/ui/LinkIcon.kt | 33 +++++++++++++++ .../omnivore/feature/settings/LogoHeader.kt | 4 +- .../feature/settings/about/AboutScreen.kt | 41 +++++++++++++++++++ .../app/src/main/res/drawable/ic_discord.xml | 9 ++++ .../app/src/main/res/drawable/ic_github.xml | 10 +++++ .../app/src/main/res/drawable/ic_omnivore.xml | 4 +- .../app/src/main/res/drawable/ic_x.xml | 9 ++++ .../app/src/main/res/values/strings.xml | 1 + 8 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/ui/LinkIcon.kt create mode 100644 android/Omnivore/app/src/main/res/drawable/ic_discord.xml create mode 100644 android/Omnivore/app/src/main/res/drawable/ic_github.xml create mode 100644 android/Omnivore/app/src/main/res/drawable/ic_x.xml diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/ui/LinkIcon.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/ui/LinkIcon.kt new file mode 100644 index 000000000..79e6f83fa --- /dev/null +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/core/ui/LinkIcon.kt @@ -0,0 +1,33 @@ +package app.omnivore.omnivore.core.ui + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.unit.dp + +@Composable +fun LinkIcon( + label: String, + icon: ImageVector, + url: String, + modifier: Modifier = Modifier, +) { + val uriHandler = LocalUriHandler.current + IconButton( + modifier = modifier.padding(4.dp), + onClick = { uriHandler.openUri(url) }, + ) { + Icon( + imageVector = icon, + contentDescription = label, + modifier = Modifier.size(24.dp), + tint = MaterialTheme.colorScheme.onSurface + ) + } +} diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt index e32491e03..9fc95df41 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt @@ -25,8 +25,8 @@ fun LogoHeader() { contentDescription = null, tint = MaterialTheme.colorScheme.onSurface, modifier = Modifier - .padding(vertical = 56.dp) - .size(64.dp), + .padding(vertical = 32.dp) + .size(128.dp), ) HorizontalDivider() diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt index 9e0b1220c..984c62301 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt @@ -1,8 +1,13 @@ package app.omnivore.omnivore.feature.settings.about +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack +import androidx.compose.material.icons.outlined.Public import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -12,11 +17,16 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import app.omnivore.omnivore.BuildConfig import app.omnivore.omnivore.R +import app.omnivore.omnivore.core.ui.LinkIcon import app.omnivore.omnivore.feature.settings.LogoHeader import app.omnivore.omnivore.feature.settings.RELEASE_URL import app.omnivore.omnivore.feature.settings.SettingRow @@ -95,6 +105,37 @@ internal fun AboutScreen( navController.navigate(Routes.TermsAndConditions.route) } } + + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + horizontalArrangement = Arrangement.Center, + ) { + LinkIcon( + label = stringResource(R.string.website), + icon = Icons.Outlined.Public, + url = "https://omnivore.app", + ) + LinkIcon( + label = "Discord", + icon = ImageVector.vectorResource(R.drawable.ic_discord), + url = "https://discord.gg/h2z5rppzz9", + ) + LinkIcon( + label = "X", + icon = ImageVector.vectorResource(R.drawable.ic_x), + url = "https://x.com/omnivoreapp", + ) + + LinkIcon( + label = "GitHub", + icon = ImageVector.vectorResource(R.drawable.ic_github), + url = "https://github.com/omnivore-app", + ) + } + } } } } diff --git a/android/Omnivore/app/src/main/res/drawable/ic_discord.xml b/android/Omnivore/app/src/main/res/drawable/ic_discord.xml new file mode 100644 index 000000000..bdec4191f --- /dev/null +++ b/android/Omnivore/app/src/main/res/drawable/ic_discord.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/Omnivore/app/src/main/res/drawable/ic_github.xml b/android/Omnivore/app/src/main/res/drawable/ic_github.xml new file mode 100644 index 000000000..34241eaa3 --- /dev/null +++ b/android/Omnivore/app/src/main/res/drawable/ic_github.xml @@ -0,0 +1,10 @@ + + + diff --git a/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml b/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml index 8608e8300..ecaad383b 100644 --- a/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml +++ b/android/Omnivore/app/src/main/res/drawable/ic_omnivore.xml @@ -1,7 +1,7 @@ + + diff --git a/android/Omnivore/app/src/main/res/values/strings.xml b/android/Omnivore/app/src/main/res/values/strings.xml index d737b53fd..451b66fa4 100644 --- a/android/Omnivore/app/src/main/res/values/strings.xml +++ b/android/Omnivore/app/src/main/res/values/strings.xml @@ -216,6 +216,7 @@ About Version What\'s new + Website Inbox From a156c6dbdc52f613e1f79778b6b2fc4058516f2d Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Fri, 23 Feb 2024 22:10:55 +0000 Subject: [PATCH 6/7] add account screen --- .../app/omnivore/omnivore/MainActivity.kt | 2 - .../omnivore/feature/root/RootView.kt | 23 +++-- .../omnivore/feature/settings/LogoutDialog.kt | 7 +- .../feature/settings/SettingsScreen.kt | 16 +--- .../feature/settings/about/AboutScreen.kt | 20 ++-- .../settings/{ => about}/LogoHeader.kt | 2 +- .../feature/settings/account/AccountScreen.kt | 93 ++++++++----------- .../omnivore/omnivore/navigation/Routes.kt | 1 + .../app/src/main/res/values/strings.xml | 2 +- 9 files changed, 71 insertions(+), 95 deletions(-) rename android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/{ => about}/LogoHeader.kt (95%) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt index 688db9601..233a285d4 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/MainActivity.kt @@ -35,7 +35,6 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) val loginViewModel: LoginViewModel by viewModels() - val settingsViewModel: SettingsViewModel by viewModels() val searchViewModel: SearchViewModel by viewModels() val labelsViewModel: LabelsViewModel by viewModels() val saveViewModel: SaveViewModel by viewModels() @@ -64,7 +63,6 @@ class MainActivity : ComponentActivity() { RootView( loginViewModel, searchViewModel, - settingsViewModel, labelsViewModel, saveViewModel, editInfoViewModel diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt index 9afd0ec0b..4d8feacb8 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt @@ -17,8 +17,8 @@ import app.omnivore.omnivore.feature.library.SearchView import app.omnivore.omnivore.feature.library.SearchViewModel import app.omnivore.omnivore.feature.save.SaveViewModel import app.omnivore.omnivore.feature.settings.SettingsScreen -import app.omnivore.omnivore.feature.settings.SettingsViewModel import app.omnivore.omnivore.feature.settings.about.AboutScreen +import app.omnivore.omnivore.feature.settings.account.AccountScreen import app.omnivore.omnivore.feature.web.WebViewScreen import app.omnivore.omnivore.navigation.Routes @@ -26,7 +26,6 @@ import app.omnivore.omnivore.navigation.Routes fun RootView( loginViewModel: LoginViewModel, searchViewModel: SearchViewModel, - settingsViewModel: SettingsViewModel, labelsViewModel: LabelsViewModel, saveViewModel: SaveViewModel, editInfoViewModel: EditInfoViewModel, @@ -38,7 +37,6 @@ fun RootView( PrimaryNavigator( loginViewModel = loginViewModel, searchViewModel = searchViewModel, - settingsViewModel = settingsViewModel, labelsViewModel = labelsViewModel, saveViewModel = saveViewModel, editInfoViewModel = editInfoViewModel, @@ -60,14 +58,16 @@ fun RootView( fun PrimaryNavigator( loginViewModel: LoginViewModel, searchViewModel: SearchViewModel, - settingsViewModel: SettingsViewModel, labelsViewModel: LabelsViewModel, saveViewModel: SaveViewModel, editInfoViewModel: EditInfoViewModel, ) { val navController = rememberNavController() - NavHost(navController = navController, startDestination = Routes.Library.route) { + NavHost( + navController = navController, + startDestination = Routes.Library.route + ) { composable(Routes.Library.route) { LibraryView( navController = navController, @@ -79,23 +79,26 @@ fun PrimaryNavigator( composable(Routes.Search.route) { SearchView( - viewModel = searchViewModel, - navController = navController + viewModel = searchViewModel, navController = navController ) } composable(Routes.Settings.route) { SettingsScreen( loginViewModel = loginViewModel, - settingsViewModel = settingsViewModel, navController = navController ) } composable(Routes.About.route) { AboutScreen( - navController = navController, - settingsViewModel = settingsViewModel + navController = navController + ) + } + + composable(Routes.Account.route) { + AccountScreen( + navController = navController ) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt index 6c95a0092..0e8804908 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt @@ -1,8 +1,8 @@ package app.omnivore.omnivore.feature.settings import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Button import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -20,8 +20,7 @@ fun LogoutDialog(onClose: (Boolean) -> Unit) { Text(stringResource(R.string.logout_dialog_confirm_msg)) }, confirmButton = { - Button(onClick = { - // Sign out google users + TextButton(onClick = { val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build() @@ -33,7 +32,7 @@ fun LogoutDialog(onClose: (Boolean) -> Unit) { } }, dismissButton = { - Button(onClick = { onClose(false) }) { + TextButton(onClick = { onClose(false) }) { Text(stringResource(R.string.logout_dialog_action_cancel)) } }) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt index 22bc7b891..4d99f2bdb 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsScreen.kt @@ -31,15 +31,13 @@ import androidx.compose.ui.unit.sp import androidx.navigation.NavHostController import app.omnivore.omnivore.R import app.omnivore.omnivore.feature.auth.LoginViewModel -import app.omnivore.omnivore.feature.settings.account.ManageAccountDialog import app.omnivore.omnivore.navigation.Routes @OptIn(ExperimentalMaterial3Api::class) @Composable internal fun SettingsScreen( loginViewModel: LoginViewModel, - settingsViewModel: SettingsViewModel, - navController: NavHostController, + navController: NavHostController ) { Scaffold(topBar = { TopAppBar( @@ -60,7 +58,6 @@ internal fun SettingsScreen( }) { paddingValues -> SettingsViewContent( loginViewModel = loginViewModel, - settingsViewModel = settingsViewModel, navController = navController, paddingValues = paddingValues ) @@ -70,12 +67,10 @@ internal fun SettingsScreen( @Composable fun SettingsViewContent( loginViewModel: LoginViewModel, - settingsViewModel: SettingsViewModel, navController: NavHostController, paddingValues: PaddingValues ) { val showLogoutDialog = remember { mutableStateOf(false) } - val showManageAccountDialog = remember { mutableStateOf(false) } val state = rememberLazyListState() @@ -86,7 +81,7 @@ fun SettingsViewContent( item { SettingRow(title = stringResource(R.string.settings_view_setting_row_manage_account)) { - showManageAccountDialog.value = true + navController.navigate(Routes.Account.route) } } @@ -113,13 +108,6 @@ fun SettingsViewContent( showLogoutDialog.value = false } } - - if (showManageAccountDialog.value) { - ManageAccountDialog( - onDismiss = { showManageAccountDialog.value = false }, - settingsViewModel = settingsViewModel - ) - } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt index 984c62301..13ee241d3 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/AboutScreen.kt @@ -23,11 +23,11 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import app.omnivore.omnivore.BuildConfig import app.omnivore.omnivore.R import app.omnivore.omnivore.core.ui.LinkIcon -import app.omnivore.omnivore.feature.settings.LogoHeader import app.omnivore.omnivore.feature.settings.RELEASE_URL import app.omnivore.omnivore.feature.settings.SettingRow import app.omnivore.omnivore.feature.settings.SettingsViewModel @@ -37,7 +37,7 @@ import app.omnivore.omnivore.navigation.Routes @Composable internal fun AboutScreen( navController: NavHostController, - settingsViewModel: SettingsViewModel + settingsViewModel: SettingsViewModel = hiltViewModel() ) { val uriHandler = LocalUriHandler.current @@ -67,14 +67,6 @@ internal fun AboutScreen( LogoHeader() } - item { - SettingRow( - title = stringResource(R.string.about_view_row_version), - subtitle = getVersionName(), - onClick = { }, - ) - } - item { SettingRow( title = stringResource(R.string.about_view_row_whats_new), @@ -106,6 +98,14 @@ internal fun AboutScreen( } } + item { + SettingRow( + title = stringResource(R.string.about_view_row_version), + subtitle = getVersionName(), + onClick = { }, + ) + } + item { Row( modifier = Modifier diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/LogoHeader.kt similarity index 95% rename from android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt rename to android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/LogoHeader.kt index 9fc95df41..9f2a77933 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoHeader.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/about/LogoHeader.kt @@ -1,4 +1,4 @@ -package app.omnivore.omnivore.feature.settings +package app.omnivore.omnivore.feature.settings.about import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt index 57d8cde41..bc7977bb0 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt @@ -1,70 +1,57 @@ package app.omnivore.omnivore.feature.settings.account -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Refresh +import androidx.compose.material.icons.automirrored.outlined.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.Surface +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController import app.omnivore.omnivore.R +import app.omnivore.omnivore.feature.settings.SettingRow import app.omnivore.omnivore.feature.settings.SettingsViewModel +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun ManageAccountDialog(onDismiss: () -> Unit, settingsViewModel: SettingsViewModel) { - Dialog(onDismissRequest = { onDismiss() }) { - Surface( - shape = RoundedCornerShape(16.dp), - color = Color.White, - modifier = Modifier.height(300.dp) - ) { - ManageAccountView(settingsViewModel = settingsViewModel) - } - } -} +internal fun AccountScreen( + navController: NavHostController, + settingsViewModel: SettingsViewModel = hiltViewModel() +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.manage_account_title)) }, + navigationIcon = { + IconButton(onClick = { navController.navigateUp() }) { + Icon( + imageVector = Icons.AutoMirrored.Outlined.ArrowBack, contentDescription = null + ) + } -@Composable -fun ManageAccountView(settingsViewModel: SettingsViewModel) { - Column( - modifier = Modifier.padding(top = 6.dp, start = 6.dp, end = 6.dp, bottom = 6.dp) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = 12.dp, bottom = 12.dp), - horizontalArrangement = Arrangement.Center + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background + ), + ) + }, + ) { contentPadding -> + LazyColumn( + contentPadding = contentPadding, ) { - Text(stringResource(R.string.manage_account_title)) - } - - Column( - modifier = Modifier.verticalScroll(rememberScrollState()) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.clickable(onClick = { settingsViewModel.resetDataCache() }) - ) { - Text(stringResource(R.string.manage_account_action_reset_data_cache)) - Spacer(modifier = Modifier.weight(1.0F)) - Icon(imageVector = Icons.Filled.Refresh, contentDescription = null) + item { + SettingRow( + title = stringResource(R.string.manage_account_action_reset_data_cache), + onClick = { settingsViewModel.resetDataCache() }, + ) } } } } - diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt index e10ee6e94..53a39b62d 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/navigation/Routes.kt @@ -4,6 +4,7 @@ sealed class Routes(val route: String) { object Library : Routes("Library") object Settings : Routes("Settings") object About : Routes("About") + object Account : Routes("Account") object Search : Routes("Search") object Documentation : Routes("Documentation") object PrivacyPolicy : Routes("PrivacyPolicy") diff --git a/android/Omnivore/app/src/main/res/values/strings.xml b/android/Omnivore/app/src/main/res/values/strings.xml index 451b66fa4..fba0f250b 100644 --- a/android/Omnivore/app/src/main/res/values/strings.xml +++ b/android/Omnivore/app/src/main/res/values/strings.xml @@ -212,7 +212,7 @@ Manage Account Logout - + About Version What\'s new From 4a27ce78275d157069c8455181c9d199c1c266b1 Mon Sep 17 00:00:00 2001 From: Stefano Sansone Date: Sat, 24 Feb 2024 00:15:33 +0000 Subject: [PATCH 7/7] add snackbar --- .../omnivore/feature/root/RootView.kt | 66 ++++++++++++++----- .../omnivore/feature/settings/LogoutDialog.kt | 15 ++++- .../feature/settings/SettingsViewModel.kt | 18 +++++ .../feature/settings/account/AccountScreen.kt | 29 +++++++- 4 files changed, 108 insertions(+), 20 deletions(-) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt index 4d8feacb8..5e48ad2ff 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/root/RootView.kt @@ -1,10 +1,23 @@ package app.omnivore.omnivore.feature.root import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.only +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @@ -31,25 +44,42 @@ fun RootView( editInfoViewModel: EditInfoViewModel, ) { val hasAuthToken: Boolean by loginViewModel.hasAuthTokenLiveData.observeAsState(false) + val snackbarHostState = remember { SnackbarHostState() } - Box { - if (hasAuthToken) { - PrimaryNavigator( - loginViewModel = loginViewModel, - searchViewModel = searchViewModel, - labelsViewModel = labelsViewModel, - saveViewModel = saveViewModel, - editInfoViewModel = editInfoViewModel, - ) - } else { - WelcomeScreen(viewModel = loginViewModel) - } - - DisposableEffect(hasAuthToken) { + Scaffold( + snackbarHost = { SnackbarHost(snackbarHostState) }, + ) { padding -> + Box( + modifier = Modifier + .fillMaxSize() + .padding(padding) + .consumeWindowInsets(padding) + .windowInsetsPadding( + WindowInsets.safeDrawing.only( + WindowInsetsSides.Horizontal, + ), + ) + ){ if (hasAuthToken) { - loginViewModel.registerUser() + PrimaryNavigator( + loginViewModel = loginViewModel, + searchViewModel = searchViewModel, + labelsViewModel = labelsViewModel, + saveViewModel = saveViewModel, + editInfoViewModel = editInfoViewModel, + snackbarHostState = snackbarHostState + + ) + } else { + WelcomeScreen(viewModel = loginViewModel) + } + + DisposableEffect(hasAuthToken) { + if (hasAuthToken) { + loginViewModel.registerUser() + } + onDispose {} } - onDispose {} } } } @@ -61,6 +91,7 @@ fun PrimaryNavigator( labelsViewModel: LabelsViewModel, saveViewModel: SaveViewModel, editInfoViewModel: EditInfoViewModel, + snackbarHostState: SnackbarHostState ) { val navController = rememberNavController() @@ -98,7 +129,8 @@ fun PrimaryNavigator( composable(Routes.Account.route) { AccountScreen( - navController = navController + navController = navController, + snackbarHostState = snackbarHostState, ) } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt index 0e8804908..02ca000c8 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/LogoutDialog.kt @@ -1,6 +1,8 @@ package app.omnivore.omnivore.feature.settings import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -19,8 +21,13 @@ fun LogoutDialog(onClose: (Boolean) -> Unit) { text = { Text(stringResource(R.string.logout_dialog_confirm_msg)) }, + containerColor = MaterialTheme.colorScheme.background, confirmButton = { - TextButton(onClick = { + TextButton( + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.onSurface + ), + onClick = { val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build() @@ -32,7 +39,11 @@ fun LogoutDialog(onClose: (Boolean) -> Unit) { } }, dismissButton = { - TextButton(onClick = { onClose(false) }) { + TextButton( + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.onSurface + ), + onClick = { onClose(false) }) { Text(stringResource(R.string.logout_dialog_action_cancel)) } }) diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt index 4f048e856..0058ba321 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/SettingsViewModel.kt @@ -1,5 +1,8 @@ package app.omnivore.omnivore.feature.settings +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import app.omnivore.omnivore.core.data.DataService @@ -10,6 +13,7 @@ import app.omnivore.omnivore.utils.DatastoreKeys import dagger.hilt.android.lifecycle.HiltViewModel import io.intercom.android.sdk.Intercom import io.intercom.android.sdk.IntercomSpace +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import javax.inject.Inject @@ -19,10 +23,24 @@ class SettingsViewModel @Inject constructor( private val dataService: DataService, private val datastoreRepo: DatastoreRepository ) : ViewModel() { + + var snackbarMessage by mutableStateOf("Resetting data...") + + var isResettingData by mutableStateOf(false) + var isDataResetCompleted by mutableStateOf(false) + fun resetDataCache() { + isResettingData = true + viewModelScope.launch { datastoreRepo.clearValue(DatastoreKeys.libraryLastSyncTimestamp) dataService.clearDatabase() + delay(1000) + isResettingData = false + + if (!isDataResetCompleted) { + isDataResetCompleted = true + } } } diff --git a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt index bc7977bb0..bb1988e84 100644 --- a/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt +++ b/android/Omnivore/app/src/main/java/app/omnivore/omnivore/feature/settings/account/AccountScreen.kt @@ -8,10 +8,14 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.SnackbarResult import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController @@ -23,8 +27,29 @@ import app.omnivore.omnivore.feature.settings.SettingsViewModel @Composable internal fun AccountScreen( navController: NavHostController, + snackbarHostState: SnackbarHostState, settingsViewModel: SettingsViewModel = hiltViewModel() ) { + LaunchedEffect(settingsViewModel.isResettingData) { + if (settingsViewModel.isResettingData) { + val result = snackbarHostState.showSnackbar( + message = settingsViewModel.snackbarMessage, + duration = SnackbarDuration.Indefinite, + ) + when (result) { + SnackbarResult.Dismissed -> { + settingsViewModel.isResettingData = false + } + SnackbarResult.ActionPerformed -> { } + } + } else if (settingsViewModel.isDataResetCompleted) { + snackbarHostState.showSnackbar( + message = "Data reset completed.", + duration = SnackbarDuration.Short + ) + } + } + Scaffold( topBar = { TopAppBar( @@ -49,7 +74,9 @@ internal fun AccountScreen( item { SettingRow( title = stringResource(R.string.manage_account_action_reset_data_cache), - onClick = { settingsViewModel.resetDataCache() }, + onClick = { + settingsViewModel.resetDataCache() + }, ) } }