From 0f2b92fcc4a0563eb9391a65a2a7b822981df78a Mon Sep 17 00:00:00 2001 From: James Barr Date: Wed, 27 Oct 2021 17:51:52 -0700 Subject: [PATCH] Update Compose, Coil, AnimatedNavHost, and Datastore --- app/build.gradle.kts | 42 +++++---- app/src/main/AndroidManifest.xml | 2 +- .../github/jbarr21/appdialer/app/AppModule.kt | 6 ++ .../appdialer/data/UserPreferencesRepo.kt | 26 +++--- .../jbarr21/appdialer/ui/AppDialerApp.kt | 17 ++-- .../appdialer/ui/main/MainAppBottomSheet.kt | 4 +- .../jbarr21/appdialer/ui/main/MainScreen.kt | 90 +++++++++++-------- .../appdialer/ui/main/MainViewModel.kt | 11 ++- .../jbarr21/appdialer/ui/main/apps/AppGrid.kt | 8 +- .../jbarr21/appdialer/ui/main/apps/AppItem.kt | 37 +++----- .../appdialer/ui/main/dialer/ColorButtons.kt | 57 ++++++++++++ .../appdialer/ui/main/dialer/DialerGrid.kt | 35 +------- .../ui/settings/SettingsViewModel.kt | 8 -- build.gradle.kts | 4 +- 14 files changed, 195 insertions(+), 152 deletions(-) create mode 100644 app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/ColorButtons.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 30c9087..5bfd400 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,8 +1,9 @@ -val composeVersion = "1.0.0" +val accompanistVersion = "0.20.0" +val composeVersion = "1.0.4" val coroutinesVersion = "1.3.8" val flipperVersion = "0.55.0" val hiltVersion = "2.36" -val kotlinVersion = "1.5.10" +val kotlinVersion = "1.5.31" val roomVersion = "2.3.0" plugins { @@ -13,12 +14,12 @@ plugins { } android { - compileSdkVersion(30) + compileSdkVersion(31) buildToolsVersion = "30.0.3" defaultConfig { applicationId = "io.github.jbarr21.appdialer" minSdkVersion(23) - targetSdkVersion(30) + targetSdkVersion(31) versionCode = 2 versionName = "0.0.3" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -57,40 +58,37 @@ android { dependencies { kapt("androidx.room:room-compiler:2.3.0") kapt("com.google.dagger:hilt-android-compiler:$hiltVersion") - kapt("androidx.lifecycle:lifecycle-compiler:2.3.1") + kapt("androidx.lifecycle:lifecycle-compiler:2.4.0") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion") - implementation("androidx.activity:activity-compose:1.3.0-beta02") - implementation("androidx.activity:activity-ktx:1.3.0-beta02") - implementation("androidx.appcompat:appcompat:1.3.0") + implementation("androidx.activity:activity-compose:1.4.0") + implementation("androidx.appcompat:appcompat:1.3.1") implementation("androidx.compose.ui:ui:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") - implementation("androidx.core:core-ktx:1.5.0") - implementation("androidx.datastore:datastore-preferences:1.0.0-alpha01") + implementation("androidx.core:core-ktx:1.7.0") + implementation("androidx.datastore:datastore-preferences:1.0.0") implementation("androidx.hilt:hilt-navigation-compose:1.0.0-alpha03") implementation("com.google.dagger:hilt-android:$hiltVersion") implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") - implementation("androidx.lifecycle:lifecycle-runtime:2.3.1") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1") - implementation("androidx.lifecycle:lifecycle-viewmodel:2.3.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1") - implementation("androidx.navigation:navigation-compose:2.4.0-alpha03") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0") + implementation("androidx.navigation:navigation-compose:2.4.0-alpha10") implementation("androidx.palette:palette:1.0.0") implementation("androidx.room:room-ktx:$roomVersion") implementation("androidx.room:room-runtime:$roomVersion") - implementation("com.google.accompanist:accompanist-coil:0.11.1") - implementation("com.google.accompanist:accompanist-insets-ui:0.11.1") - implementation("com.google.accompanist:accompanist-swiperefresh:0.11.1") - implementation("com.google.accompanist:accompanist-systemuicontroller:0.11.1") - implementation("com.google.android.material:material:1.3.0") + implementation("com.google.accompanist:accompanist-insets-ui:$accompanistVersion") + implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion") + implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") + implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") + implementation("com.google.android.material:material:1.4.0") implementation("com.jakewharton:process-phoenix:2.0.0") implementation("com.jakewharton.timber:timber:4.7.1") - implementation("io.coil-kt:coil:1.2.2") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") + implementation("com.squareup.okhttp3:okhttp:4.9.2") + implementation("io.coil-kt:coil-compose:1.4.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion") debugImplementation("com.facebook.flipper:flipper:$flipperVersion") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7a0e4c8..99b9297 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,7 +22,7 @@ android:supportsRtl="true" android:theme="@style/Theme.AppDialer" tools:ignore="GoogleAppIndexingWarning"> - + diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/app/AppModule.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/app/AppModule.kt index 6ddcdc9..52538a7 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/app/AppModule.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/app/AppModule.kt @@ -14,9 +14,11 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import io.github.jbarr21.appdialer.data.UserPreferencesRepo import io.github.jbarr21.appdialer.data.db.AppDatabase import io.github.jbarr21.appdialer.util.ActivityLauncher import io.github.jbarr21.appdialer.util.AppIconFetcher +import javax.inject.Singleton @InstallIn(SingletonComponent::class) @Module @@ -60,4 +62,8 @@ object AppModule { @Provides fun userManager(application: Application) = application.getSystemService()!! + + @Singleton + @Provides + fun userPreferencesRepo(application: Application) = UserPreferencesRepo(application) } \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/data/UserPreferencesRepo.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/data/UserPreferencesRepo.kt index a1c2e4d..0732bbf 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/data/UserPreferencesRepo.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/data/UserPreferencesRepo.kt @@ -1,28 +1,28 @@ package io.github.jbarr21.appdialer.data import android.app.Application -import androidx.datastore.preferences.Preferences -import androidx.datastore.preferences.createDataStore -import androidx.datastore.preferences.edit -import androidx.datastore.preferences.emptyPreferences -import androidx.datastore.preferences.preferencesKey +import android.content.Context +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.emptyPreferences +import androidx.datastore.preferences.preferencesDataStore import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import timber.log.Timber import java.io.IOException -import javax.inject.Inject -class UserPreferencesRepo @Inject constructor(private val application: Application) { +class UserPreferencesRepo(private val application: Application) { - private val dataStore = application.createDataStore(name = "user") + private val Context.dataStore by preferencesDataStore(name = "user") private object Keys { - val USE_HAPTIC_FEEDBACK = preferencesKey("use_haptic_feedback") - val USE_PERSISTENT_SERVICE = preferencesKey("use_persistent_service") + val USE_HAPTIC_FEEDBACK = booleanPreferencesKey("use_haptic_feedback") + val USE_PERSISTENT_SERVICE = booleanPreferencesKey("use_persistent_service") } - val userPreferencesFlow = dataStore.data + val userPreferencesFlow = application.dataStore.data .catch { exception -> if (exception is IOException) { Timber.e(exception, "Error reading preferences") @@ -47,13 +47,13 @@ class UserPreferencesRepo @Inject constructor(private val application: Applicati suspend fun usePersistentService() = getValue(Keys.USE_PERSISTENT_SERVICE, false) private suspend fun updatePreference(key: Preferences.Key, value: T) { - dataStore.edit { preferences -> + application.dataStore.edit { preferences -> preferences[key] = value } } private suspend fun getValue(key: Preferences.Key, defaultValue: T? = null): T { - return this.dataStore.data + return application.dataStore.data .map { preferences -> preferences[key] ?: defaultValue } .first()!! } diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/AppDialerApp.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/AppDialerApp.kt index b93fb24..1a7751a 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/AppDialerApp.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/AppDialerApp.kt @@ -1,20 +1,25 @@ package io.github.jbarr21.appdialer.ui +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.runtime.Composable import androidx.hilt.navigation.compose.hiltViewModel -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController +import com.google.accompanist.navigation.animation.AnimatedNavHost +import com.google.accompanist.navigation.animation.composable +import com.google.accompanist.navigation.animation.rememberAnimatedNavController import io.github.jbarr21.appdialer.ui.info.InfoScreen import io.github.jbarr21.appdialer.ui.main.MainScreen import io.github.jbarr21.appdialer.ui.settings.SettingsScreen +@OptIn(ExperimentalAnimationApi::class) @Composable fun AppDialerApp() { - val navController = rememberNavController() - NavHost(navController = navController, startDestination = Screen.Main.toString()) { + val navController = rememberAnimatedNavController() + AnimatedNavHost( + navController = navController, + startDestination = Screen.Main.toString(), + ) { composable(Screen.Main.toString()) { MainScreen(hiltViewModel(), navController) } composable(Screen.Settings.toString()) { SettingsScreen(hiltViewModel(), navController) } composable(Screen.Info.toString()) { InfoScreen(hiltViewModel(), navController) } } -} +} \ No newline at end of file diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainAppBottomSheet.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainAppBottomSheet.kt index a1ff115..60ea522 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainAppBottomSheet.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainAppBottomSheet.kt @@ -5,7 +5,6 @@ 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.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight @@ -35,7 +34,8 @@ fun MainAppBottomSheet( Surface( color = Color.Black.copy(alpha = 0.5f), modifier = Modifier - .fillMaxSize() + .fillMaxWidth() + .wrapContentHeight() .clickable(onClick = onDismiss) // indication = null, interactionState = InteractionState() ) { Surface( diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainScreen.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainScreen.kt index d0db915..6ffb26c 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainScreen.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainScreen.kt @@ -1,17 +1,23 @@ package io.github.jbarr21.appdialer.ui.main import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.BottomSheetScaffold +import androidx.compose.material.BottomSheetValue import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.MaterialTheme -import androidx.compose.material.SnackbarHost -import androidx.compose.material.SnackbarHostState +import androidx.compose.material.ModalBottomSheetLayout +import androidx.compose.material.ModalBottomSheetState +import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.Surface +import androidx.compose.material.rememberBottomSheetScaffoldState +import androidx.compose.material.rememberBottomSheetState import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -21,6 +27,7 @@ import androidx.navigation.NavController import io.github.jbarr21.appdialer.ui.AppTheme import io.github.jbarr21.appdialer.ui.main.apps.AppGrid import io.github.jbarr21.appdialer.ui.main.dialer.DialerGrid +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterialApi::class) @Composable @@ -28,40 +35,53 @@ fun MainScreen( viewModel: MainViewModel = viewModel(), navController: NavController ) { - val snackbarHostState = remember { SnackbarHostState() } val context = LocalContext.current - Surface(color = MaterialTheme.colors.background, modifier = Modifier.fillMaxSize()) { - Box { - AppGrid( - apps = viewModel.filteredApps, - query = viewModel.queryText, - isRefreshing = viewModel.isRefreshing, - onClick = { viewModel.onAppClicked(context, it) }, - onLongClick = viewModel.onAppLongClicked, - onRefresh = { viewModel.loadApps(false) } - ) - Box(modifier = Modifier.align(alignment = Alignment.BottomCenter)) { - DialerGrid( - buttons = viewModel.dialerLabels, - buttonColors = viewModel.buttonColors, - onClick = viewModel.onDialerClicked, - onLongClick = { viewModel.onDialerLongClickedDecorated(it, navController, snackbarHostState) } - ) + val scope = rememberCoroutineScope() + val sheetState = ModalBottomSheetState(ModalBottomSheetValue.Hidden) + ModalBottomSheetLayout( + scrimColor = Color.Black.copy(alpha = 0.5f), + sheetState = sheetState, + sheetContent = { + if (viewModel.selectedApp.value != null) { + MainAppBottomSheet( + viewModel.selectedApp.value!!, + viewModel.appLongClickActions, + onActionClick = { viewModel.selectedApp.value = null }, + onDismiss = { viewModel.onAppLongClicked(null, sheetState) } + ) + } else { + Box(modifier = Modifier.defaultMinSize(minHeight = 1.dp)) + } } - SnackbarHost( - hostState = snackbarHostState, - modifier = Modifier - .fillMaxSize() - .padding(8.dp) - .align(alignment = Alignment.TopCenter) + ) { + val scaffoldState = rememberBottomSheetScaffoldState( + bottomSheetState = rememberBottomSheetState(BottomSheetValue.Expanded) ) - viewModel.selectedApp.value?.let { - MainAppBottomSheet( - it, - viewModel.appLongClickActions, - onActionClick = { viewModel.selectedApp.value = null }, - onDismiss = { viewModel.onAppLongClicked(null) } + BottomSheetScaffold( + scaffoldState = scaffoldState, + sheetShape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp), + sheetPeekHeight = 96.dp, + sheetContent = { + DialerGrid( + buttons = viewModel.dialerLabels, + buttonColors = viewModel.buttonColors, + onClick = viewModel.onDialerClicked, + onLongClick = { viewModel.onDialerLongClickedDecorated(it, navController) }) + } + ) { + AppGrid( + apps = viewModel.filteredApps, + query = viewModel.queryText, + isRefreshing = viewModel.isRefreshing, + onClick = { viewModel.onAppClicked(context, it) }, + onLongClick = { + val app = viewModel.onAppLongClicked(it, sheetState) + app?.let { + scope.launch { sheetState.show() } + } + }, + onRefresh = { viewModel.loadApps(false) } ) } } diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainViewModel.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainViewModel.kt index f973208..f43ee51 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainViewModel.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/MainViewModel.kt @@ -2,7 +2,8 @@ package io.github.jbarr21.appdialer.ui.main import android.app.Activity import android.content.Context -import androidx.compose.material.SnackbarHostState +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ModalBottomSheetState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue @@ -82,9 +83,11 @@ class MainViewModel @Inject constructor( (context as Activity).finishAndRemoveTask() } - val onAppLongClicked: (App?) -> Unit = { + @ExperimentalMaterialApi + fun onAppLongClicked(app: App?, sheetState: ModalBottomSheetState): App? { vibrator.vibrate() - selectedApp.value = it + selectedApp.value = app + return app } val onDialerClicked: (DialerButton) -> Unit = { @@ -103,7 +106,7 @@ class MainViewModel @Inject constructor( } } - fun onDialerLongClickedDecorated(button: DialerButton, navController: NavController, snackbarHostState: SnackbarHostState) { + fun onDialerLongClickedDecorated(button: DialerButton, navController: NavController) { onDialerLongClicked(button, navController) if (button.isInfoButton) { navController.navigate(Screen.Info.toString()) diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppGrid.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppGrid.kt index c968d3f..74c9a16 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppGrid.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppGrid.kt @@ -2,6 +2,7 @@ package io.github.jbarr21.appdialer.ui.main.apps import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.GridCells @@ -13,11 +14,12 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.google.accompanist.insets.LocalWindowInsets -import com.google.accompanist.insets.toPaddingValues +import com.google.accompanist.insets.rememberInsetsPaddingValues import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import io.github.jbarr21.appdialer.data.App @@ -35,6 +37,7 @@ fun AppGrid( onRefresh: () -> Unit = {} ) { val insets = LocalWindowInsets.current + val statusTop = with(LocalDensity.current) { insets.statusBars.top.toDp() } val isEmpty = apps.isEmpty() && query.isNotEmpty() val isLoading = apps.isEmpty() && query.isEmpty() when { @@ -56,11 +59,12 @@ fun AppGrid( apps.isNotEmpty() -> { SwipeRefresh( state = rememberSwipeRefreshState(isRefreshing), + indicatorPadding = PaddingValues(top = statusTop), onRefresh = onRefresh ) { LazyVerticalGrid( cells = GridCells.Fixed(numColumns), - contentPadding = insets.statusBars.toPaddingValues(), + contentPadding = rememberInsetsPaddingValues(insets = insets.statusBars, additionalBottom = 96.dp * 3), content = { itemsIndexed(apps) { _, app -> AppItem(app, query, onClick, onLongClick) diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppItem.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppItem.kt index d4e4a4c..4c6c94e 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppItem.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/apps/AppItem.kt @@ -10,21 +10,17 @@ import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp -import com.google.accompanist.coil.rememberCoilPainter -import com.google.accompanist.imageloading.ImageLoadState +import coil.compose.rememberImagePainter import io.github.jbarr21.appdialer.data.App import io.github.jbarr21.appdialer.ui.AppTheme import io.github.jbarr21.appdialer.ui.main.PreviewData.previewApp @@ -50,22 +46,17 @@ fun AppItem( .fillMaxWidth() .aspectRatio(1f)) { - val painter = rememberCoilPainter(request = app.iconUri.toString()) - when (painter.loadState) { - is ImageLoadState.Success -> { - Image( - painter = painter, - contentDescription = null, - modifier = Modifier.fillMaxSize() - ) - } - else -> { - Box(modifier = Modifier - .fillMaxSize() - .clip(CircleShape) - .background(Color.DarkGray)) - } - } + val painter = + Image( + painter = rememberImagePainter( + data = app.iconUri, + builder = { + crossfade(true) + } + ), + contentDescription = null, + modifier = Modifier.fillMaxSize() + ) } Text( text = app.annotatedLabel(query), @@ -85,8 +76,8 @@ private class AppProvider : PreviewParameterProvider { @Preview(widthDp = 150) @Composable -fun AppItemPreview(@PreviewParameter(AppProvider::class) app: App) { +fun AppItemPreview() { AppTheme(darkTheme = true) { - AppItem(app) + AppItem(previewApp) } } diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/ColorButtons.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/ColorButtons.kt new file mode 100644 index 0000000..2d95618 --- /dev/null +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/ColorButtons.kt @@ -0,0 +1,57 @@ +package io.github.jbarr21.appdialer.ui.main.dialer + +import android.widget.Toast +import androidx.compose.foundation.clickable +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.layout.size +import androidx.compose.material.FloatingActionButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.google.accompanist.insets.navigationBarsPadding +import io.github.jbarr21.appdialer.ui.AppTheme +import io.github.jbarr21.appdialer.ui.main.PreviewData + +@Composable +fun ColorButtons( + buttonColors: List = emptyList() +) { + val context = LocalContext.current + val onColorClicked: (Color) -> Unit = { + Toast.makeText(context, "Clicked $it", Toast.LENGTH_SHORT).show() + } + + Row( + modifier = Modifier.fillMaxWidth().navigationBarsPadding(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + buttonColors.forEach { color -> + FloatingActionButton( + backgroundColor = color, + onClick = { onColorClicked(color) }, + modifier = Modifier + .size(48.dp) + .clickable( + onClick = { onColorClicked(color) } +// , indication = rememberRipple(bounded = false), +// interactionState = InteractionState() + ) + .padding(all = 16.dp) + ) { } + } + } +} + +@Preview +@Composable +fun ColorButtonsPreview() { + AppTheme(darkTheme = true) { + ColorButtons(buttonColors = PreviewData.buttonColors) + } +} diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/DialerGrid.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/DialerGrid.kt index 459b701..6370435 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/DialerGrid.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/main/dialer/DialerGrid.kt @@ -1,28 +1,18 @@ package io.github.jbarr21.appdialer.ui.main.dialer -import android.widget.Toast import androidx.compose.foundation.ExperimentalFoundationApi -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.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.GridCells import androidx.compose.foundation.lazy.LazyVerticalGrid import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material.FloatingActionButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.google.accompanist.insets.navigationBarsPadding import io.github.jbarr21.appdialer.data.DialerButton import io.github.jbarr21.appdialer.ui.AppTheme import io.github.jbarr21.appdialer.ui.main.PreviewData.buttonColors @@ -37,11 +27,6 @@ fun DialerGrid( onClick: (DialerButton) -> Unit = {}, onLongClick: (DialerButton) -> Unit = {} ) { - val context = LocalContext.current - val onColorClicked: (Color) -> Unit = { - Toast.makeText(context, "Clicked $it", Toast.LENGTH_SHORT).show() - } - Surface( color = MaterialTheme.colors.surface, elevation = 2.dp, @@ -53,25 +38,7 @@ fun DialerGrid( DialerItem(button, onClick, onLongClick) } }) - Row( - modifier = Modifier.fillMaxWidth().navigationBarsPadding(), - horizontalArrangement = Arrangement.SpaceEvenly - ) { - buttonColors.forEach { color -> - FloatingActionButton( - backgroundColor = color, - onClick = { onColorClicked(color) }, - modifier = Modifier - .size(48.dp) - .clickable( - onClick = { onColorClicked(color) } -// , indication = rememberRipple(bounded = false), -// interactionState = InteractionState() - ) - .padding(all = 16.dp) - ) { } - } - } + ColorButtons(buttonColors) } } } diff --git a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/settings/SettingsViewModel.kt b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/settings/SettingsViewModel.kt index cf5ddb2..850823b 100644 --- a/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/settings/SettingsViewModel.kt +++ b/app/src/main/kotlin/io/github/jbarr21/appdialer/ui/settings/SettingsViewModel.kt @@ -4,7 +4,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import io.github.jbarr21.appdialer.data.SimpleListItem @@ -39,11 +38,4 @@ class SettingsViewModel @Inject constructor( fun updateUsePersistentService(enable: Boolean) = viewModelScope.launch { userPreferencesRepo.updateUsePersistentService(enable) } - - class Factory @Inject constructor( - private val userPreferencesRepo: UserPreferencesRepo, - private val settingsData: List> - ) : ViewModelProvider.Factory { - override fun create(modelClass: Class) = SettingsViewModel(userPreferencesRepo, settingsData) as T - } } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 0990d53..a4a3e1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,12 +1,12 @@ buildscript { - val kotlinVersion = "1.5.10" + val kotlinVersion = "1.5.31" val hiltVersion = "2.36" repositories { google() jcenter() } dependencies { - classpath("com.android.tools.build:gradle:7.0.0") + classpath("com.android.tools.build:gradle:7.0.3") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") classpath("com.google.dagger:hilt-android-gradle-plugin:$hiltVersion") }