Skip to content

Commit

Permalink
feat: Added theme, usage/diagnostics settings, and providers
Browse files Browse the repository at this point in the history
- Added `ThemeSettingsList` composable to manage theme preferences.
- Added `UsageAndDiagnosticsList` composable to manage usage and diagnostics settings.
- Added `UsageAndDiagnosticsSettingsProvider` interface for usage and diagnostics settings.
- Added `DrawerStyle` enum for drawer styling.
- Added `DisplaySettingsProvider` interface for display settings.
- Added `PrivacySettingsProvider` interface for privacy settings.
- Added `AdvancedSettingsProvider` interface for advanced settings.
- Added `AboutSettingsProvider` interface for about settings.
- Updated version to `0.0.39`.
  • Loading branch information
Mihai-Cristian Condrea committed Jan 25, 2025
1 parent c99888a commit 0e709c6
Show file tree
Hide file tree
Showing 9 changed files with 399 additions and 2 deletions.
2 changes: 1 addition & 1 deletion apptoolkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ publishing {
register<MavenPublication>("release") {
groupId = "com.github.D4rK7355608"
artifactId = "AppToolkit"
version = "0.0.38"
version = "0.0.39"

afterEvaluate {
from(components["release"])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.d4rk.android.libs.apptoolkit.ui.screens.settings.display.theme

import android.content.Context
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.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.d4rk.android.libs.apptoolkit.R
import com.d4rk.android.libs.apptoolkit.data.datastore.CommonDataStore
import com.d4rk.android.libs.apptoolkit.ui.components.modifiers.bounceClick
import com.d4rk.android.libs.apptoolkit.ui.components.preferences.SwitchCardComposable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

@Composable
fun ThemeSettingsList(paddingValues : PaddingValues) {
val context : Context = LocalContext.current
val dataStore : CommonDataStore = CommonDataStore.getInstance(context = context)
val coroutineScope : CoroutineScope = rememberCoroutineScope()
val themeMode : String = dataStore.themeMode.collectAsState(initial = "follow_system").value
val isAmoledMode : State<Boolean> = dataStore.amoledMode.collectAsState(initial = false)

val themeOptions : List<String> = listOf(
stringResource(id = R.string.follow_system) ,
stringResource(id = R.string.dark_mode) ,
stringResource(id = R.string.light_mode) ,
)

Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues = paddingValues) ,
) {
item {
SwitchCardComposable(
title = stringResource(id = R.string.amoled_mode) ,
switchState = isAmoledMode
) { isChecked ->
coroutineScope.launch {
dataStore.saveAmoledMode(isChecked = isChecked)
}
}
}
item {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp)
) {
themeOptions.forEach { text ->
Row(
Modifier.fillMaxWidth() ,
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(modifier = Modifier.bounceClick() ,
selected = (text == themeMode) ,
onClick = {
coroutineScope.launch {
dataStore.saveThemeMode(mode = text)
dataStore.themeModeState.value = text
}
})
Text(
text = text ,
style = MaterialTheme.typography.bodyMedium.merge() ,
modifier = Modifier.padding(start = 16.dp)
)
}
}
}
}
item {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(all = 24.dp)
) {
Icon(imageVector = Icons.Outlined.Info , contentDescription = null)
Spacer(modifier = Modifier.height(height = 24.dp))
Text(text = stringResource(id = R.string.summary_dark_theme))
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.d4rk.android.libs.apptoolkit.ui.screens.settings.privacy.usage

import android.content.Context
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import com.d4rk.android.libs.apptoolkit.R
import com.d4rk.android.libs.apptoolkit.data.datastore.CommonDataStore
import com.d4rk.android.libs.apptoolkit.ui.components.modifiers.bounceClick
import com.d4rk.android.libs.apptoolkit.ui.components.preferences.SwitchCardComposable
import com.d4rk.android.libs.apptoolkit.utils.helpers.IntentsHelper
import com.d4rk.android.libs.apptoolkit.utils.interfaces.providers.UsageAndDiagnosticsSettingsProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

@Composable
fun UsageAndDiagnosticsList(paddingValues : PaddingValues , provider : UsageAndDiagnosticsSettingsProvider) {
val context : Context = LocalContext.current
val dataStore : CommonDataStore = CommonDataStore.getInstance(context = context)
val switchState : State<Boolean> = dataStore.usageAndDiagnostics.collectAsState(initial = ! provider.isDebugBuild)
val coroutineScope : CoroutineScope = rememberCoroutineScope()

Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues = paddingValues) ,
) {
item {
SwitchCardComposable(
title = stringResource(id = R.string.usage_and_diagnostics) , switchState = switchState
) { isChecked ->
coroutineScope.launch {
dataStore.saveUsageAndDiagnostics(isChecked = isChecked)
}
}
}
item {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(all = 24.dp)
) {
Icon(imageVector = Icons.Outlined.Info , contentDescription = null)
Spacer(modifier = Modifier.height(height = 24.dp))
Text(text = stringResource(id = R.string.summary_usage_and_diagnostics))
val annotatedString : AnnotatedString = buildAnnotatedString {
val startIndex : Int = length
withStyle(
style = SpanStyle(
color = MaterialTheme.colorScheme.primary , textDecoration = TextDecoration.Underline
)
) {
append(stringResource(id = R.string.learn_more))
}
val endIndex : Int = length

addStringAnnotation(
tag = "URL" , annotation = "https://sites.google.com/view/d4rk7355608/more/apps/privacy-policy" , start = startIndex , end = endIndex
)
}
Text(text = annotatedString , modifier = Modifier
.bounceClick()
.clickable {
annotatedString.getStringAnnotations(
tag = "URL" , start = 0 , end = annotatedString.length
).firstOrNull()?.let { annotation ->
IntentsHelper.openUrl(
context = context , url = annotation.item
)
}
})
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package com.d4rk.android.libs.apptoolkit.utils.constants.ui

/**
* Defines the different styles for a drawer component.
*
* A drawer is a panel that slides in from the side of the screen to display
* navigation or other content. The style determines how the drawer interacts
* with the rest of the screen content.
*/
enum class DrawerStyle {
MODAL , PERMANENT
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package com.d4rk.android.libs.apptoolkit.utils.interfaces.providers

/**
* Interface for providing settings related to the "About" section of an application.
* This interface defines properties that describe the application itself,
* such as its name, version, and copyright information. Implement this interface
* to provide the necessary data for displaying an "About" screen or similar
* informational views within the application.
*/
interface AboutSettingsProvider {
val appName : String
val packageName : String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.d4rk.android.libs.apptoolkit.utils.interfaces.providers

/**
* Interface for providing advanced settings, typically used for
* configuration or information that is not part of the core user experience
* but may be useful for power users, developers, or for debugging.
*/
interface AdvancedSettingsProvider {
val bugReportUrl : String
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,80 @@
package com.d4rk.android.libs.apptoolkit.utils.interfaces.providers

import android.content.Context
import androidx.compose.runtime.Composable

/**
* Interface for providing access to display-related settings and UI components.
*
* This interface defines methods and properties for interacting with display settings,
* such as managing the startup page, selecting the language, and opening the theme settings.
*/
interface DisplaySettingsProvider {

/**
* Indicates whether this component supports a startup page.
*
* A startup page is a designated page that is displayed to the user when the component is first launched or accessed.
* If `true`, the component can display a specific page on startup. If `false`, the component does not have a dedicated
* startup page and might default to a different initial view.
*
* @return `true` if the component supports a startup page, `false` otherwise.
*/
val supportsStartupPage: Boolean
get() = false

/**
* Displays a dialog that allows the user to select a startup option.
*
* This dialog presents the user with a choice of different startup modes or configurations.
* Upon the user selecting an option, the dialog will dismiss and call the `onStartupSelected` callback.
* If the user dismisses the dialog without making a selection, the `onDismiss` callback will be triggered.
*
* @param onDismiss Callback invoked when the dialog is dismissed without a selection being made.
* This typically occurs when the user taps outside the dialog or presses the back button.
* @param onStartupSelected Callback invoked when a startup option is selected by the user.
* It provides the selected option as a `String`.
* The specific format and meaning of this string are defined by the caller.
*/
@Composable
fun StartupPageDialog(
onDismiss: () -> Unit,
onStartupSelected: (String) -> Unit
)

/**
* A composable dialog for selecting a language.
*
* This dialog presents the user with a list of available languages to choose from.
* When a language is selected, the `onLanguageSelected` callback is invoked with the
* selected language's string identifier (e.g., "en", "es", "fr").
*
* @param onDismiss A callback invoked when the dialog is dismissed, either by
* clicking outside the dialog or by pressing the back button.
* @param onLanguageSelected A callback invoked when a language is selected from the list.
* It receives the string identifier of the selected language.
*/
@Composable
fun LanguageSelectionDialog(
onDismiss: () -> Unit,
onLanguageSelected: (String) -> Unit
)

/**
* Opens the theme settings screen or activity.
*
* This function is responsible for initiating the navigation or display of
* the user interface where the user can customize the application's theme.
* This might include options for:
* - Switching between light and dark mode.
* - Selecting a custom color scheme.
* - Adjusting font sizes or styles.
* - Enabling high contrast mode.
*
* The exact implementation details of how the theme settings are opened
* (e.g., launching a new activity, displaying a dialog, etc.) are
* handled internally by this function.
*
* @see [closeThemeSettings] for closing the theme settings
*/
fun openThemeSettings()
}
Loading

0 comments on commit 0e709c6

Please sign in to comment.