From 1195df3a1a24b6808a1022121172e41808996ec9 Mon Sep 17 00:00:00 2001 From: Hamza417 Date: Mon, 9 Sep 2024 11:18:45 +0530 Subject: [PATCH 01/47] Bump version id to 200 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c8342450..cbe8b107 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { applicationId "app.simple.peri" minSdk 24 targetSdk 34 - versionCode 154 - versionName "1.54_beta" + versionCode 200 + versionName "2.00_beta" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" From 193b32f6735eac866a38945da20ff9254b8964b2 Mon Sep 17 00:00:00 2001 From: Hamza417 Date: Mon, 9 Sep 2024 14:26:22 +0530 Subject: [PATCH 02/47] Compose home screen rev01 --- app/build.gradle | 4 + .../simple/peri/activities/MainActivity.kt | 228 ++---------------- .../app/simple/peri/compose/nav/Navigation.kt | 31 +++ .../app/simple/peri/compose/nav/Routes.kt | 8 + .../simple/peri/compose/screens/HomeScreen.kt | 207 ++++++++++++++++ .../simple/peri/compose/screens/ListScreen.kt | 1 + .../peri/compose/screens/SettingsScreen.kt | 1 + .../peri/compose/screens/WallpaperScreen.kt | 1 + .../app/simple/peri/compose/theme/Color.kt | 11 + .../app/simple/peri/compose/theme/Theme.kt | 87 +++++++ .../simple/peri/compose/theme/Typography.kt | 25 ++ .../peri/ui/{MainScreen.kt => HomeScreen.kt} | 21 +- .../app/simple/peri/ui/WallpaperScreen.kt | 4 - .../peri/viewmodels/HomeScreenViewModel.kt | 87 +++++++ .../peri/viewmodels/WallpaperViewModel.kt | 69 ------ 15 files changed, 481 insertions(+), 304 deletions(-) create mode 100644 app/src/main/java/app/simple/peri/compose/nav/Navigation.kt create mode 100644 app/src/main/java/app/simple/peri/compose/nav/Routes.kt create mode 100644 app/src/main/java/app/simple/peri/compose/screens/HomeScreen.kt create mode 100644 app/src/main/java/app/simple/peri/compose/screens/ListScreen.kt create mode 100644 app/src/main/java/app/simple/peri/compose/screens/SettingsScreen.kt create mode 100644 app/src/main/java/app/simple/peri/compose/screens/WallpaperScreen.kt create mode 100644 app/src/main/java/app/simple/peri/compose/theme/Color.kt create mode 100644 app/src/main/java/app/simple/peri/compose/theme/Theme.kt create mode 100644 app/src/main/java/app/simple/peri/compose/theme/Typography.kt rename app/src/main/java/app/simple/peri/ui/{MainScreen.kt => HomeScreen.kt} (97%) create mode 100644 app/src/main/java/app/simple/peri/viewmodels/HomeScreenViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index cbe8b107..31d59117 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,6 +83,7 @@ android { dependencies { + implementation 'androidx.navigation:navigation-compose:2.8.0' def composeBom = platform('androidx.compose:compose-bom:2024.09.00') implementation composeBom androidTestImplementation composeBom @@ -93,6 +94,8 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5' implementation 'androidx.compose.runtime:runtime-livedata' implementation 'androidx.compose.foundation:foundation:1.7.0' + implementation 'androidx.compose.ui:ui-tooling-preview-android:1.7.0' + debugImplementation 'androidx.compose.ui:ui-tooling:1.7.0' implementation 'androidx.window:window:1.3.0' implementation 'androidx.core:core-ktx:1.13.1' @@ -113,6 +116,7 @@ dependencies { // Glide implementation 'com.github.bumptech.glide:glide:4.16.0' implementation 'com.github.bumptech.glide:okhttp3-integration:4.15.1' + implementation "com.github.bumptech.glide:compose:1.0.0-beta01" //noinspection KaptUsageInsteadOfKsp kapt 'com.github.bumptech.glide:compiler:4.15.1' diff --git a/app/src/main/java/app/simple/peri/activities/MainActivity.kt b/app/src/main/java/app/simple/peri/activities/MainActivity.kt index 92d5e469..40cc40b1 100644 --- a/app/src/main/java/app/simple/peri/activities/MainActivity.kt +++ b/app/src/main/java/app/simple/peri/activities/MainActivity.kt @@ -1,224 +1,26 @@ package app.simple.peri.activities -import android.app.AlarmManager -import android.app.PendingIntent -import android.content.Intent -import android.graphics.Color -import android.os.Build import android.os.Bundle -import android.util.Log -import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AppCompatActivity -import androidx.biometric.BiometricPrompt -import androidx.core.content.ContextCompat -import androidx.core.view.WindowCompat -import app.simple.peri.R -import app.simple.peri.constants.Misc -import app.simple.peri.crash.CrashReport -import app.simple.peri.databinding.ActivityMainBinding -import app.simple.peri.preferences.MainPreferences -import app.simple.peri.preferences.SharedPreferences -import app.simple.peri.services.AutoWallpaperService -import app.simple.peri.ui.MainScreen -import app.simple.peri.utils.ConditionUtils.isNull -import app.simple.peri.utils.ScreenUtils -import com.google.android.material.dialog.MaterialAlertDialogBuilder +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Surface +import androidx.compose.ui.Modifier +import app.simple.peri.compose.nav.PeristyleNavigation +import app.simple.peri.compose.theme.PeristyleTheme -class MainActivity : AppCompatActivity(), android.content.SharedPreferences.OnSharedPreferenceChangeListener { - - private var binding: ActivityMainBinding? = null - private var biometricPrompt: BiometricPrompt? = null - private var biometricPromptInfo: BiometricPrompt.PromptInfo? = null - private var savedState: Bundle? = null - - private val modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION - - private val storageResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - val uri = result.data?.data - if (uri != null) { - contentResolver.takePersistableUriPermission(uri, modeFlags) - MainPreferences.setStorageUri(uri.toString()) - Log.d("MainActivity", "Storage Uri: $uri") - - binding?.mainContainer?.id?.let { - supportFragmentManager.beginTransaction() - .replace(it, MainScreen.newInstance()) - .commit() - } - } - } +class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - savedState = savedInstanceState - - initSharedPreferences() - initBinding() - makeAppFullScreen() - setDisplaySize() - checkUriPermissions() - initBiometricPromptInfo() - handleStorageUri() - initCrashHandler() - } - - private fun initSharedPreferences() { - SharedPreferences.init(this) - SharedPreferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this) - } - - private fun initBinding() { - binding = ActivityMainBinding.inflate(layoutInflater) - setContentView(binding?.root) - } - - private fun checkUriPermissions() { - if (contentResolver.persistedUriPermissions.isNotEmpty()) { - setAutoWallpaperAlarm() - } - } - - private fun initBiometricPromptInfo() { - biometricPromptInfo = BiometricPrompt.PromptInfo.Builder() - .setTitle(getString(R.string.app_name)) - .setDescription(getString(R.string.biometric_desc)) - .setNegativeButtonText(getString(R.string.close)) - .build() - } - - private fun handleStorageUri() { - if (MainPreferences.getStorageUri() == null) { - Log.d("MainActivity", "Storage Uri: no permission") - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - storageResult.launch(intent) - } else { - Log.d("MainActivity", "Storage Uri: ${MainPreferences.getStorageUri()}") - if (contentResolver.persistedUriPermissions.isNotEmpty()) { - handleBiometricAuthentication() - } else { - Log.d("MainActivity", "Storage Uri: no permission") - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - storageResult.launch(intent) - } - } - } - - private fun initCrashHandler() { - CrashReport(this).initialize() // Can leak? - } - - private fun handleBiometricAuthentication() { - if (savedState.isNull()) { - if (MainPreferences.isBiometric()) { - authenticateWithBiometrics() - } else { - loadMainScreen() - } - } - } - - private fun authenticateWithBiometrics() { - biometricPrompt = BiometricPrompt(this, ContextCompat.getMainExecutor(this), object : BiometricPrompt.AuthenticationCallback() { - override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { - super.onAuthenticationError(errorCode, errString) - handleAuthenticationError(errorCode, errString) - } - - override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { - super.onAuthenticationSucceeded(result) - Log.d("MainActivity", "Biometric: success") - loadMainScreen() - } - - override fun onAuthenticationFailed() { - super.onAuthenticationFailed() - Log.d("MainActivity", "Biometric: failed") - } - }) - - biometricPrompt?.authenticate(biometricPromptInfo!!) - } - - private fun handleAuthenticationError(errorCode: Int, errString: CharSequence) { - when (errorCode) { - BiometricPrompt.ERROR_NEGATIVE_BUTTON -> { - finish() - } - - BiometricPrompt.ERROR_NO_BIOMETRICS, - BiometricPrompt.ERROR_NO_DEVICE_CREDENTIAL -> { - loadMainScreen() - } - - else -> { - MaterialAlertDialogBuilder(this@MainActivity) - .setTitle(getString(R.string.app_name)) - .setMessage(errString) - .setPositiveButton(getString(R.string.close)) { _, _ -> - finish() - } - .show() - } - } - } - - private fun loadMainScreen() { - binding?.mainContainer?.id?.let { - supportFragmentManager.beginTransaction() - .replace(it, MainScreen.newInstance()) - .commit() - } - } - - private fun makeAppFullScreen() { - WindowCompat.setDecorFitsSystemWindows(window, false) - window.statusBarColor = Color.TRANSPARENT - window.navigationBarColor = Color.TRANSPARENT - - // Disable navigation bar contrast - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - window.isNavigationBarContrastEnforced = false - window.isStatusBarContrastEnforced = false - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - window.navigationBarDividerColor = Color.TRANSPARENT - } - } - - private fun setAutoWallpaperAlarm() { - val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager - val intent = Intent(applicationContext, AutoWallpaperService::class.java) - val pendingIntent = PendingIntent.getService(applicationContext, 0, intent, PendingIntent.FLAG_IMMUTABLE) - - // Cancel any existing alarms - alarmManager.cancel(pendingIntent) - - if (MainPreferences.getAutoWallpaperInterval().toInt() > 0) { - val interval = MainPreferences.getAutoWallpaperInterval().toInt() - alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval.toLong(), pendingIntent) - Log.d("MainActivity", "Auto wallpaper alarm set for every ${MainPreferences.getAutoWallpaperInterval()} ms") - } else { - Log.d("MainActivity", "Auto wallpaper alarm cancelled") - } - } - - private fun setDisplaySize() { - with(ScreenUtils.getScreenSize(baseContext)) { - Misc.setDisplaySize(this.width, this.height) - } - } - - override fun onSharedPreferenceChanged(sharedPreferences: android.content.SharedPreferences?, key: String?) { - when (key) { - MainPreferences.AUTO_WALLPAPER_INTERVAL -> { - setAutoWallpaperAlarm() + setContent { + PeristyleTheme { + Surface( + modifier = Modifier.fillMaxSize() + ) { + PeristyleNavigation(this) + } } } } - - override fun onDestroy() { - super.onDestroy() - SharedPreferences.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this) - } } diff --git a/app/src/main/java/app/simple/peri/compose/nav/Navigation.kt b/app/src/main/java/app/simple/peri/compose/nav/Navigation.kt new file mode 100644 index 00000000..b41f859a --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/nav/Navigation.kt @@ -0,0 +1,31 @@ +package app.simple.peri.compose.nav + +import android.content.Context +import androidx.compose.runtime.Composable +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import app.simple.peri.compose.screens.HomeScreen + +@Composable +fun PeristyleNavigation(context: Context) { + val navController = rememberNavController() + + NavHost(navController = navController, startDestination = Routes.HOME) { + composable(Routes.HOME) { + HomeScreen(context, navController) + } + + composable(Routes.LIST) { + // ListScreen() + } + + composable(Routes.WALLPAPER) { + // WallpaperScreen() + } + + composable(Routes.SETTINGS) { + // SettingsScreen() + } + } +} diff --git a/app/src/main/java/app/simple/peri/compose/nav/Routes.kt b/app/src/main/java/app/simple/peri/compose/nav/Routes.kt new file mode 100644 index 00000000..84a605fb --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/nav/Routes.kt @@ -0,0 +1,8 @@ +package app.simple.peri.compose.nav + +object Routes { + const val HOME = "home" + const val LIST = "list" + const val WALLPAPER = "wallpaper" + const val SETTINGS = "settings" +} diff --git a/app/src/main/java/app/simple/peri/compose/screens/HomeScreen.kt b/app/src/main/java/app/simple/peri/compose/screens/HomeScreen.kt new file mode 100644 index 00000000..3f99ddd0 --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/screens/HomeScreen.kt @@ -0,0 +1,207 @@ +package app.simple.peri.compose.screens + +import android.content.Context +import android.graphics.drawable.Drawable +import androidx.compose.foundation.background +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.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerDefaults +import androidx.compose.foundation.pager.PagerSnapDistance +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.util.lerp +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.NavController +import app.simple.peri.R +import app.simple.peri.models.Wallpaper +import app.simple.peri.utils.FileUtils.toUri +import app.simple.peri.viewmodels.HomeScreenViewModel +import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi +import com.bumptech.glide.integration.compose.GlideImage +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.target.Target +import kotlin.math.absoluteValue + +@Composable +fun HomeScreen(context: Context, navController: NavController? = null) { + val pagerState = rememberPagerState(pageCount = { + 2 + }) + + val fling = PagerDefaults.flingBehavior( + state = pagerState, + pagerSnapDistance = PagerSnapDistance.atMost(10) + ) + + val homeScreenViewModel: HomeScreenViewModel = viewModel() + val systemWallpapers: ArrayList + by homeScreenViewModel.getSystemWallpaper().observeAsState(initial = arrayListOf()) + + Surface( + modifier = Modifier.fillMaxSize(), + color = Color.Transparent + ) { + Column { + Header( + title = context.getString(R.string.app_name), + modifier = Modifier.padding(24.dp), + navController = navController + ) + + HorizontalPager( + state = pagerState, + contentPadding = PaddingValues(horizontal = 32.dp), + flingBehavior = fling, + modifier = Modifier + .fillMaxSize() + ) { page -> + val wallpaper = systemWallpapers.getOrNull(page) + + CardItem( + title = if (page == 0) context.getString(R.string.lock_screen) else context.getString(R.string.home_screen), + onClick = { + if (page == 0) { + navController?.navigate("wallpaper") + } else { + navController?.navigate("settings") + } + }, + modifier = Modifier + .weight(1f) + .graphicsLayer { + // Calculate the absolute offset for the current page from the + // scroll position. We use the absolute value which allows us to mirror + // any effects for both directions + val pageOffset = ( + (pagerState.currentPage - page) + pagerState + .currentPageOffsetFraction + ).absoluteValue + + // We animate the alpha, between 50% and 100% + alpha = lerp( + start = 0.5f, + stop = 1f, + fraction = 1f - pageOffset.coerceIn(0f, 1f) + ) + } + .padding(8.dp), // Add padding to create space between the cards + wallpaper = wallpaper + + ) + } + } + } +} + +@OptIn(ExperimentalGlideComposeApi::class) +@Composable +fun CardItem(title: String, onClick: () -> Unit, modifier: Modifier = Modifier, wallpaper: Wallpaper?) { + val currentScale = remember { + mutableStateOf(ContentScale.Crop) + } + + ElevatedCard( + elevation = CardDefaults.cardElevation( + defaultElevation = 6.dp + ), + modifier = modifier + .fillMaxHeight() + .padding(8.dp), // margin + onClick = onClick, + shape = RoundedCornerShape(32.dp) + ) { + Box(modifier = Modifier.fillMaxSize()) { + GlideImage( + model = wallpaper?.uri?.toUri(), + contentDescription = null, + modifier = Modifier.fillMaxSize(), + alignment = Alignment.Center, + contentScale = currentScale.value, + ) { + it.addListener(object : RequestListener { + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target, isFirstResource: Boolean): Boolean { + return false + } + + override fun onResourceReady(resource: Drawable, model: Any, target: Target?, dataSource: DataSource, isFirstResource: Boolean): Boolean { + return false + } + }) + .transition(withCrossFade()) + .disallowHardwareConfig() + .fitCenter() + } + + Text( + text = title, + modifier = Modifier + .align(Alignment.Center) // Align the text to the center of the Box + .padding(16.dp) + .background(Color(0x80000000)), + textAlign = TextAlign.Center, + ) + } + } +} + +@Composable +fun Header(title: String, modifier: Modifier = Modifier, navController: NavController? = null) { + Row( + modifier = modifier + .fillMaxWidth() + .wrapContentHeight(), + verticalAlignment = androidx.compose.ui.Alignment.CenterVertically + ) { + Text( + text = title, + textAlign = TextAlign.Start, + fontSize = 32.sp, // Set the font size + modifier = Modifier.weight(1f), // Set the weight + fontWeight = FontWeight.Bold, // Make the text bold + ) + + IconButton( + onClick = { + navController?.navigate("settings") + }, + ) { + Icon( + imageVector = Icons.Filled.Settings, + contentDescription = null + ) + } + } +} diff --git a/app/src/main/java/app/simple/peri/compose/screens/ListScreen.kt b/app/src/main/java/app/simple/peri/compose/screens/ListScreen.kt new file mode 100644 index 00000000..ac7d72c5 --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/screens/ListScreen.kt @@ -0,0 +1 @@ +package app.simple.peri.compose.screens diff --git a/app/src/main/java/app/simple/peri/compose/screens/SettingsScreen.kt b/app/src/main/java/app/simple/peri/compose/screens/SettingsScreen.kt new file mode 100644 index 00000000..ac7d72c5 --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/screens/SettingsScreen.kt @@ -0,0 +1 @@ +package app.simple.peri.compose.screens diff --git a/app/src/main/java/app/simple/peri/compose/screens/WallpaperScreen.kt b/app/src/main/java/app/simple/peri/compose/screens/WallpaperScreen.kt new file mode 100644 index 00000000..ac7d72c5 --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/screens/WallpaperScreen.kt @@ -0,0 +1 @@ +package app.simple.peri.compose.screens diff --git a/app/src/main/java/app/simple/peri/compose/theme/Color.kt b/app/src/main/java/app/simple/peri/compose/theme/Color.kt new file mode 100644 index 00000000..6670f9a8 --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/theme/Color.kt @@ -0,0 +1,11 @@ +package app.simple.peri.compose.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) diff --git a/app/src/main/java/app/simple/peri/compose/theme/Theme.kt b/app/src/main/java/app/simple/peri/compose/theme/Theme.kt new file mode 100644 index 00000000..23e7acbc --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/theme/Theme.kt @@ -0,0 +1,87 @@ +package app.simple.peri.compose.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.core.view.WindowCompat + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun PeristyleTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} + +@Preview +@Composable +fun PeristyleThemePreview( + @PreviewParameter(BooleanPreviewParameterProvider::class) darkTheme: Boolean +) { + PeristyleTheme(darkTheme = darkTheme) { + // Your Composable content here + } +} + +class BooleanPreviewParameterProvider : PreviewParameterProvider { + override val values: Sequence = sequenceOf(true, false) +} diff --git a/app/src/main/java/app/simple/peri/compose/theme/Typography.kt b/app/src/main/java/app/simple/peri/compose/theme/Typography.kt new file mode 100644 index 00000000..acf15361 --- /dev/null +++ b/app/src/main/java/app/simple/peri/compose/theme/Typography.kt @@ -0,0 +1,25 @@ +package app.simple.peri.compose.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ), + bodySmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.25.sp + ), +) diff --git a/app/src/main/java/app/simple/peri/ui/MainScreen.kt b/app/src/main/java/app/simple/peri/ui/HomeScreen.kt similarity index 97% rename from app/src/main/java/app/simple/peri/ui/MainScreen.kt rename to app/src/main/java/app/simple/peri/ui/HomeScreen.kt index b0ebf02c..22344c9c 100644 --- a/app/src/main/java/app/simple/peri/ui/MainScreen.kt +++ b/app/src/main/java/app/simple/peri/ui/HomeScreen.kt @@ -66,7 +66,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.util.concurrent.Executor -class MainScreen : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener { +class HomeScreen : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener { private val wallpaperViewModel: WallpaperViewModel by viewModels({ requireActivity() }) private var adapterWallpaper: AdapterWallpaper? = null @@ -516,21 +516,6 @@ class MainScreen : Fragment(), SharedPreferences.OnSharedPreferenceChangeListene } } - wallpaperViewModel.getSystemWallpaper().observe(viewLifecycleOwner) { systemWallpapers -> - systemWallpaperAdapter = AdapterSystemWallpaper(systemWallpapers, -1) - systemWallpaperAdapter?.setWallpaperCallbacks(object : WallpaperCallbacks { - override fun onWallpaperClicked(wallpaper: Wallpaper?, position: Int, constraintLayout: ConstraintLayout?) { - openWallpaperScreen(wallpaper!!, constraintLayout!!) - } - - override fun onWallpaperLongClicked(wallpaper: Wallpaper, position: Int, view: View) { - showWallpaperOptions(wallpaper, position, true) - } - }) - - setBothAdapter() - } - binding?.fab?.setOnClickListener { kotlin.runCatching { // Pick a random wallpaper from the list @@ -906,9 +891,9 @@ class MainScreen : Fragment(), SharedPreferences.OnSharedPreferenceChangeListene } companion object { - fun newInstance(): MainScreen { + fun newInstance(): HomeScreen { val args = Bundle() - val fragment = MainScreen() + val fragment = HomeScreen() fragment.arguments = args return fragment } diff --git a/app/src/main/java/app/simple/peri/ui/WallpaperScreen.kt b/app/src/main/java/app/simple/peri/ui/WallpaperScreen.kt index fe5e2c30..3ceb974f 100644 --- a/app/src/main/java/app/simple/peri/ui/WallpaperScreen.kt +++ b/app/src/main/java/app/simple/peri/ui/WallpaperScreen.kt @@ -431,10 +431,6 @@ class WallpaperScreen : Fragment() { } } - if (mode != EXPORT) { - wallpaperViewModel?.postCurrentSystemWallpaper() - } - loader.dismiss() }.onFailure { loader.dismiss() diff --git a/app/src/main/java/app/simple/peri/viewmodels/HomeScreenViewModel.kt b/app/src/main/java/app/simple/peri/viewmodels/HomeScreenViewModel.kt new file mode 100644 index 00000000..1154b393 --- /dev/null +++ b/app/src/main/java/app/simple/peri/viewmodels/HomeScreenViewModel.kt @@ -0,0 +1,87 @@ +package app.simple.peri.viewmodels + +import android.app.Application +import android.app.WallpaperManager +import android.graphics.Bitmap +import android.net.Uri +import android.os.Build +import androidx.core.content.FileProvider +import androidx.core.graphics.drawable.toBitmap +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import app.simple.peri.models.Wallpaper +import app.simple.peri.utils.PermissionUtils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.io.File + +class HomeScreenViewModel(application: Application) : AndroidViewModel(application) { + + private val systemWallpaperData: MutableLiveData> by lazy { + MutableLiveData>().also { + postCurrentSystemWallpaper() + } + } + + fun getSystemWallpaper(): MutableLiveData> { + return systemWallpaperData + } + + private fun postCurrentSystemWallpaper() { + viewModelScope.launch(Dispatchers.IO) { + if (PermissionUtils.checkStoragePermission(getApplication())) { + systemWallpaperData.postValue(getCurrentSystemWallpaper()) + } else { + throw SecurityException("Storage permission not granted") + } + } + } + + private fun getCurrentSystemWallpaper(): ArrayList { + val wallpaperManager = WallpaperManager.getInstance(getApplication()) + val systemBitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + wallpaperManager.getDrawable(WallpaperManager.FLAG_SYSTEM)?.toBitmap() + } else { + wallpaperManager.drawable?.toBitmap() + } + + val lockBitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + wallpaperManager.getDrawable(WallpaperManager.FLAG_LOCK)?.toBitmap() + } else { + wallpaperManager.drawable?.toBitmap() + } + + val systemFile = createTempFile(SYSTEM_WALLPAPER) + val lockFile = createTempFile(LOCK_WALLPAPER) + + systemFile.outputStream().use { systemBitmap?.compress(Bitmap.CompressFormat.PNG, 100, it) } + lockFile.outputStream().use { lockBitmap?.compress(Bitmap.CompressFormat.PNG, 100, it) } + + val systemUri = getFileUri(systemFile) + val lockUri = getFileUri(lockFile) + + return arrayListOf( + Wallpaper().createFromUri(systemUri.toString(), getApplication()), + Wallpaper().createFromUri(lockUri.toString(), getApplication()) + ) + } + + private fun createTempFile(fileName: String): File { + val file = File(getApplication().filesDir, + fileName.replace("$", System.currentTimeMillis().div(1000).toString())) + if (file.exists()) file.delete() + return file + } + + private fun getFileUri(file: File): Uri { + return FileProvider.getUriForFile( + getApplication(), "${getApplication().packageName}.provider", file + ) + } + + companion object { + private const val SYSTEM_WALLPAPER = "system_wallpaper_$.png" + private const val LOCK_WALLPAPER = "lock_wallpaper_$.png" + } +} diff --git a/app/src/main/java/app/simple/peri/viewmodels/WallpaperViewModel.kt b/app/src/main/java/app/simple/peri/viewmodels/WallpaperViewModel.kt index 02a85156..725fc68a 100644 --- a/app/src/main/java/app/simple/peri/viewmodels/WallpaperViewModel.kt +++ b/app/src/main/java/app/simple/peri/viewmodels/WallpaperViewModel.kt @@ -1,18 +1,13 @@ package app.simple.peri.viewmodels import android.app.Application -import android.app.WallpaperManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri -import android.os.Build import android.util.Log -import androidx.core.content.FileProvider -import androidx.core.graphics.drawable.toBitmap import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.MutableLiveData @@ -27,12 +22,10 @@ import app.simple.peri.utils.FileUtils.filterDotFiles import app.simple.peri.utils.FileUtils.listCompleteFiles import app.simple.peri.utils.FileUtils.listOnlyFirstLevelFiles import app.simple.peri.utils.FileUtils.toUri -import app.simple.peri.utils.PermissionUtils import app.simple.peri.utils.WallpaperSort.getSortedList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.io.File class WallpaperViewModel(application: Application) : AndroidViewModel(application) { @@ -78,12 +71,6 @@ class WallpaperViewModel(application: Application) : AndroidViewModel(applicatio MutableLiveData() } - private val systemWallpaperData: MutableLiveData> by lazy { - MutableLiveData>().also { - postCurrentSystemWallpaper() - } - } - private val loadingStatus: MutableLiveData by lazy { MutableLiveData() } @@ -134,10 +121,6 @@ class WallpaperViewModel(application: Application) : AndroidViewModel(applicatio return isDatabaseLoaded } - fun getSystemWallpaper(): MutableLiveData> { - return systemWallpaperData - } - private fun loadWallpaperDatabase() { viewModelScope.launch(Dispatchers.IO) { val wallpaperDatabase = WallpaperDatabase.getInstance(getApplication()) @@ -272,56 +255,6 @@ class WallpaperViewModel(application: Application) : AndroidViewModel(applicatio return hashMap } - private fun getCurrentSystemWallpaper(): ArrayList { - val wallpaperManager = WallpaperManager.getInstance(getApplication()) - val systemBitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - wallpaperManager.getDrawable(WallpaperManager.FLAG_SYSTEM)?.toBitmap() - } else { - wallpaperManager.drawable?.toBitmap() - } - - val lockBitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - wallpaperManager.getDrawable(WallpaperManager.FLAG_LOCK)?.toBitmap() - } else { - wallpaperManager.drawable?.toBitmap() - } - - val systemFile = createTempFile(SYSTEM_WALLPAPER) - val lockFile = createTempFile(LOCK_WALLPAPER) - - systemFile.outputStream().use { systemBitmap?.compress(Bitmap.CompressFormat.PNG, 100, it) } - lockFile.outputStream().use { lockBitmap?.compress(Bitmap.CompressFormat.PNG, 100, it) } - - val systemUri = getFileUri(systemFile) - val lockUri = getFileUri(lockFile) - - return arrayListOf( - Wallpaper().createFromUri(systemUri.toString(), getApplication()), - Wallpaper().createFromUri(lockUri.toString(), getApplication()) - ) - } - - private fun createTempFile(fileName: String): File { - val file = File(getApplication().filesDir, - fileName.replace("$", System.currentTimeMillis().div(1000).toString())) - if (file.exists()) file.delete() - return file - } - - private fun getFileUri(file: File): Uri { - return FileProvider.getUriForFile( - getApplication(), "${getApplication().packageName}.provider", file - ) - } - - fun postCurrentSystemWallpaper() { - viewModelScope.launch(Dispatchers.IO) { - if (PermissionUtils.checkStoragePermission(getApplication())) { - systemWallpaperData.postValue(getCurrentSystemWallpaper()) - } - } - } - fun sortWallpapers() { if (isDatabaseLoaded.value == true) { wallpapers = wallpapersData.value ?: ArrayList() @@ -430,7 +363,5 @@ class WallpaperViewModel(application: Application) : AndroidViewModel(applicatio companion object { private const val TAG = "WallpaperViewModel" - private const val SYSTEM_WALLPAPER = "system_wallpaper_$.png" - private const val LOCK_WALLPAPER = "lock_wallpaper_$.png" } } From 9d57073eb4c9aa8814037bb449cbd61057c2ca82 Mon Sep 17 00:00:00 2001 From: Hamza417 Date: Mon, 9 Sep 2024 15:20:50 +0530 Subject: [PATCH 03/47] Compose home screen rev02 // Added haze background --- .idea/deploymentTargetSelector.xml | 8 ++++ .idea/inspectionProfiles/Project_Default.xml | 9 ++++ app/build.gradle | 4 ++ .../simple/peri/compose/screens/HomeScreen.kt | 42 ++++++++++++++----- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef36..295662e6 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 1f57b99e..e8786ab8 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -3,15 +3,19 @@