feat: start migrating to compose

This commit is contained in:
FunkyMuse 2023-09-19 15:31:32 +02:00
parent abb5f4b0c6
commit 811808c00f
8 changed files with 220 additions and 39 deletions

View File

@ -43,6 +43,22 @@ android {
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
buildConfig = true buildConfig = true
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
kotlinOptions.freeCompilerArgs = listOf(
"-opt-in=kotlin.RequiresOptIn",
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
"-Xcontext-receivers"
)
} }
buildTypes { buildTypes {
@ -91,5 +107,10 @@ android {
} }
dependencies { dependencies {
implementation(libs.kotlin.immutable.collections)
implementation(libs.simple.tools.commons) implementation(libs.simple.tools.commons)
implementation(libs.bundles.lifecycle)
implementation(libs.bundles.compose)
debugImplementation(libs.bundles.compose.preview)
} }

View File

@ -2,51 +2,38 @@ package com.simplemobiletools.thankyou.activities
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import com.simplemobiletools.commons.extensions.* import androidx.activity.compose.setContent
import com.simplemobiletools.commons.compose.extensions.enableEdgeToEdgeSimple
import com.simplemobiletools.commons.compose.extensions.onEventValue
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
import com.simplemobiletools.commons.extensions.appLaunched
import com.simplemobiletools.commons.extensions.checkWhatsNew
import com.simplemobiletools.commons.extensions.hideKeyboard
import com.simplemobiletools.commons.extensions.launchMoreAppsFromUsIntent
import com.simplemobiletools.commons.models.FAQItem import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.commons.models.Release import com.simplemobiletools.commons.models.Release
import com.simplemobiletools.thankyou.BuildConfig import com.simplemobiletools.thankyou.BuildConfig
import com.simplemobiletools.thankyou.R import com.simplemobiletools.thankyou.R
import com.simplemobiletools.thankyou.databinding.ActivityMainBinding import com.simplemobiletools.thankyou.screens.MainScreen
class MainActivity : SimpleActivity() { class MainActivity : SimpleActivity() {
private val binding by lazy(LazyThreadSafetyMode.NONE) { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(binding.root) enableEdgeToEdgeSimple()
setContent {
AppThemeSurface {
val showMoreApps = onEventValue { !resources.getBoolean(R.bool.hide_google_relations) }
MainScreen(
showMoreApps = showMoreApps,
openSettings = ::launchSettings,
openAbout = ::launchAbout,
moreAppsFromUs = ::launchMoreAppsFromUsIntent
)
}
}
appLaunched(BuildConfig.APPLICATION_ID) appLaunched(BuildConfig.APPLICATION_ID)
refreshMenuItems()
setupOptionsMenu()
checkWhatsNewDialog() checkWhatsNewDialog()
updateMaterialActivityViews(binding.mainCoordinator, binding.activityMain, useTransparentNavigation = true, useTopSearchMenu = false)
} }
override fun onResume() {
super.onResume()
updateTextColors(binding.activityMain)
setupToolbar(binding.mainToolbar, statusBarColor = getProperBackgroundColor())
}
private fun refreshMenuItems() {
binding.mainToolbar.menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
}
}
private fun setupOptionsMenu() {
binding.mainToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.settings -> launchSettings()
R.id.about -> launchAbout()
else -> return@setOnMenuItemClickListener false
}
return@setOnMenuItemClickListener true
}
}
private fun launchSettings() { private fun launchSettings() {
hideKeyboard() hideKeyboard()
startActivity(Intent(this, SettingsActivity::class.java)) startActivity(Intent(this, SettingsActivity::class.java))

View File

@ -10,6 +10,7 @@ import com.simplemobiletools.thankyou.R
import com.simplemobiletools.thankyou.databinding.ActivitySettingsBinding import com.simplemobiletools.thankyou.databinding.ActivitySettingsBinding
import com.simplemobiletools.thankyou.extensions.config import com.simplemobiletools.thankyou.extensions.config
import java.util.Locale import java.util.Locale
import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() { class SettingsActivity : SimpleActivity() {
private val binding by lazy(LazyThreadSafetyMode.NONE) { ActivitySettingsBinding.inflate(layoutInflater) } private val binding by lazy(LazyThreadSafetyMode.NONE) { ActivitySettingsBinding.inflate(layoutInflater) }
@ -55,7 +56,7 @@ class SettingsActivity : SimpleActivity() {
settingsUseEnglishHolder.setOnClickListener { settingsUseEnglishHolder.setOnClickListener {
settingsUseEnglish.toggle() settingsUseEnglish.toggle()
config.useEnglish = settingsUseEnglish.isChecked config.useEnglish = settingsUseEnglish.isChecked
System.exit(0) exitProcess(0)
} }
} }
} }

View File

@ -1,4 +1,4 @@
package com.simplemobiletools.thankyou.helpers package com.simplemobiletools.thankyou.helpers
// Shared Preferences // Shared Preferences
val HIDE_LAUNCHER_ICON = "hide_launcher_icon" const val HIDE_LAUNCHER_ICON = "hide_launcher_icon"

View File

@ -0,0 +1,101 @@
@file:OptIn(ExperimentalMaterial3Api::class)
package com.simplemobiletools.thankyou.screens
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.*
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.unit.sp
import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.compose.extensions.MyDevices
import com.simplemobiletools.commons.compose.menus.ActionItem
import com.simplemobiletools.commons.compose.menus.ActionMenu
import com.simplemobiletools.commons.compose.menus.OverflowMode
import com.simplemobiletools.commons.compose.screens.LinkifyText
import com.simplemobiletools.commons.compose.screens.stringFromHTML
import com.simplemobiletools.commons.compose.settings.scaffold.*
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable
internal fun MainScreen(
showMoreApps: Boolean,
openSettings: () -> Unit,
openAbout: () -> Unit,
moreAppsFromUs: () -> Unit,
) {
SettingsLazyScaffold(customTopBar = { scrolledColor: Color, _: MutableInteractionSource, scrollBehavior: TopAppBarScrollBehavior, statusBarColor: Int, colorTransitionFraction: Float, contrastColor: Color ->
TopAppBar(
title = {},
actions = {
val actionMenus = remember {
val list = listOf(
ActionItem(R.string.settings, icon = Icons.Outlined.Settings, doAction = openSettings, overflowMode = OverflowMode.NEVER_OVERFLOW),
ActionItem(R.string.about, icon = Icons.Outlined.Info, doAction = openAbout, overflowMode = OverflowMode.NEVER_OVERFLOW),
)
if (showMoreApps) {
list + ActionItem(R.string.more_apps_from_us, doAction = moreAppsFromUs, overflowMode = OverflowMode.ALWAYS_OVERFLOW)
}
list.toImmutableList()
}
var isMenuVisible by remember { mutableStateOf(false) }
ActionMenu(items = actionMenus, numIcons = 2, isMenuVisible = isMenuVisible, onMenuToggle = { isMenuVisible = it }, iconsColor = scrolledColor)
},
scrollBehavior = scrollBehavior,
colors = topAppBarColors(statusBarColor, colorTransitionFraction, contrastColor),
modifier = Modifier.topAppBarPaddings(),
windowInsets = topAppBarInsets()
)
}) {
val source = stringResource(id = com.simplemobiletools.thankyou.R.string.main_text)
LinkifyText(modifier = Modifier.padding(40.dp), fontSize = 16.sp) {
stringFromHTML(source)
}
}
}
@Composable
fun topAppBarColors(
statusBarColor: Int,
colorTransitionFraction: Float,
contrastColor: Color
) = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = Color(statusBarColor),
containerColor = if (colorTransitionFraction == 1f) contrastColor else MaterialTheme.colorScheme.surface,
navigationIconContentColor = if (colorTransitionFraction == 1f) contrastColor else MaterialTheme.colorScheme.surface
)
@Composable
private fun ActionMenuMainScreen(
) {
var isMenuVisible by remember { mutableStateOf(false) }
val actionMenus: ImmutableList<ActionItem> = remember {
listOf(
ActionItem(nameRes = R.string.settings, icon = Icons.Default.Settings, overflowMode = OverflowMode.NEVER_OVERFLOW, doAction = {}),
ActionItem(nameRes = R.string.about, icon = Icons.Default.Info, overflowMode = OverflowMode.NEVER_OVERFLOW, doAction = {}),
ActionItem(nameRes = R.string.more_apps_from_us, icon = null, overflowMode = OverflowMode.ALWAYS_OVERFLOW, doAction = {}),
).toImmutableList()
}
ActionMenu(items = actionMenus, numIcons = 2, isMenuVisible = isMenuVisible, onMenuToggle = { isMenuVisible = !isMenuVisible })
}
@Composable
@MyDevices
private fun MainScreenPreview() {
AppThemeSurface {
MainScreen(showMoreApps = true, openSettings = {}, openAbout = {}, moreAppsFromUs = {})
}
}

View File

@ -0,0 +1,17 @@
package com.simplemobiletools.thankyou.screens
import androidx.compose.runtime.Composable
import com.simplemobiletools.commons.compose.extensions.MyDevices
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
@Composable
internal fun SettingsScreen() {
}
@Composable
@MyDevices
private fun SettingsScreenPreview() {
AppThemeSurface { SettingsScreen() }
}

View File

@ -1,8 +1,18 @@
[versions] [versions]
#jetbrains #jetbrains
kotlin = "1.9.0" kotlin = "1.9.10"
kotlin-immutable-collections = "0.3.5" #todo remove
#Simple tools #Simple tools
simple-commons = "de113ad025" simple-commons = "eceb48949e"
#Compose
composeActivity = "1.8.0-beta01"
compose = "1.6.0-alpha05"
composeCompiler = "1.5.3"
composeMaterial3 = "1.2.0-alpha07"
#Androidx
androidx-customView = "1.2.0-alpha02"
androidx-customViewPooling = "1.0.0"
androidx-lifecycle = "2.7.0-alpha02"
#Gradle #Gradle
gradlePlugins-agp = "8.1.1" gradlePlugins-agp = "8.1.1"
app-build-compileSDKVersion = "34" app-build-compileSDKVersion = "34"
@ -15,8 +25,52 @@ app-version-appId = "com.simplemobiletools.thankyou"
app-version-versionCode = "31" app-version-versionCode = "31"
app-version-versionName = "5.7.3" app-version-versionName = "5.7.3"
[libraries] [libraries]
#Android X
androidx-customView = { module = "androidx.customview:customview", version.ref = "androidx-customView" }
androidx-customViewPooling = { module = "androidx.customview:customview-poolingcontainer", version.ref = "androidx-customViewPooling" }
#Simple Mobile Tools #Simple Mobile Tools
simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" } simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" }
#Android X lifecycle
androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" }
androidx-lifecycle-viewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
androidx-lifecycle-viewModel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
androidx-lifecycle-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
#Compose
compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "composeCompiler" }
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "composeMaterial3" }
compose-material2 = { module = "androidx.compose.material:material", version.ref = "compose" }
compose-material-icons = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose" }
compose-animation = { module = "androidx.compose.animation:animation", version.ref = "compose" }
compose-activity = { module = "androidx.activity:activity-compose", version.ref = "composeActivity" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "compose" }
compose-uiTooling-debug = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
compose-uiTooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }
kotlin-immutable-collections = {module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlin-immutable-collections"} #todo remove
[bundles]
compose = [
"compose-activity",
"compose-animation",
"compose-compiler",
"compose-foundation",
"compose-material-icons",
"compose-material3",
"compose-runtime",
"compose-ui",
"compose-uiTooling-preview",
]
compose-preview = [
"androidx-customView",
"androidx-customViewPooling",
"compose-uiTooling-debug",
]
lifecycle = [
"androidx-lifecycle-compose",
"androidx-lifecycle-runtime",
"androidx-lifecycle-viewModel",
"androidx-lifecycle-viewModel-compose",
]
[plugins] [plugins]
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" } android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip