wip: migrate settings to compose

This commit is contained in:
FunkyMuse 2023-06-26 19:22:56 +02:00
parent a92627c475
commit 73c87aca56
24 changed files with 918 additions and 256 deletions

View File

@ -1,73 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.simplemobiletools.calculator"
minSdkVersion 23
targetSdkVersion 33
versionCode 60
versionName "5.11.3"
setProperty("archivesBaseName", "calculator")
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
}
}
}
flavorDimensions "variants"
productFlavors {
core {}
fdroid {}
prepaid {}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:4c83ec8740'
implementation 'me.grantland:autofittextview:0.2.1'
implementation 'net.objecthunter:exp4j:0.4.8'
kapt 'androidx.room:room-compiler:2.5.1'
implementation 'androidx.room:room-runtime:2.5.1'
annotationProcessor 'androidx.room:room-compiler:2.5.1'
}

110
app/build.gradle.kts Normal file
View File

@ -0,0 +1,110 @@
import java.io.FileInputStream
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.konan.properties.Properties
plugins {
alias(libs.plugins.android)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp)
}
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt()
defaultConfig {
minSdk = project.libs.versions.app.build.minimumSDK.get().toInt()
targetSdk = project.libs.versions.app.build.targetSDK.get().toInt()
versionName = project.libs.versions.app.version.versionName.get()
versionCode = project.libs.versions.app.version.versionCode.get().toInt()
setProperty("archivesBaseName", "calculator")
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
register("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
storeFile = file(keystoreProperties.getProperty("storeFile"))
storePassword = keystoreProperties.getProperty("storePassword")
}
}
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
}
}
buildFeatures {
viewBinding = true
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
}
flavorDimensions.add("variants")
productFlavors {
register("core")
register("fdroid")
register("prepaid")
}
compileOptions {
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
sourceCompatibility = currentJavaVersionFromLibs
targetCompatibility = currentJavaVersionFromLibs
}
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"
)
}
sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
}
lint {
checkReleaseBuilds = false
abortOnError = false
}
}
dependencies {
implementation(libs.simple.tools.commons)
implementation(libs.auto.fit.text.view)
implementation(libs.exp4j)
implementation(libs.bundles.compose)
implementation(libs.bundles.accompanist)
implementation(libs.bundles.compose.preview)
implementation(libs.bundles.room)
ksp(libs.androidx.room.compiler)
}

View File

@ -9,6 +9,7 @@ import androidx.core.content.res.ResourcesCompat
import com.simplemobiletools.calculator.BuildConfig import com.simplemobiletools.calculator.BuildConfig
import com.simplemobiletools.calculator.R import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.databases.CalculatorDatabase import com.simplemobiletools.calculator.databases.CalculatorDatabase
import com.simplemobiletools.calculator.databinding.ActivityMainBinding
import com.simplemobiletools.calculator.dialogs.HistoryDialog import com.simplemobiletools.calculator.dialogs.HistoryDialog
import com.simplemobiletools.calculator.extensions.config import com.simplemobiletools.calculator.extensions.config
import com.simplemobiletools.calculator.extensions.updateViewColors import com.simplemobiletools.calculator.extensions.updateViewColors
@ -20,7 +21,6 @@ import com.simplemobiletools.commons.helpers.LOWER_ALPHA_INT
import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA_INT import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA_INT
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 kotlinx.android.synthetic.main.activity_main.*
import me.grantland.widget.AutofitHelper import me.grantland.widget.AutofitHelper
class MainActivity : SimpleActivity(), Calculator { class MainActivity : SimpleActivity(), Calculator {
@ -32,48 +32,50 @@ class MainActivity : SimpleActivity(), Calculator {
private var saveCalculatorState: String = "" private var saveCalculatorState: String = ""
private lateinit var calc: CalculatorImpl private lateinit var calc: CalculatorImpl
private val binding by lazy(LazyThreadSafetyMode.NONE) { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(binding.root)
appLaunched(BuildConfig.APPLICATION_ID) appLaunched(BuildConfig.APPLICATION_ID)
setupOptionsMenu() setupOptionsMenu()
refreshMenuItems() refreshMenuItems()
updateMaterialActivityViews(main_coordinator, null, useTransparentNavigation = false, useTopSearchMenu = false) updateMaterialActivityViews(binding.mainCoordinator, null, useTransparentNavigation = false, useTopSearchMenu = false)
setupMaterialScrollListener(main_nested_scrollview, main_toolbar) setupMaterialScrollListener(binding.mainNestedScrollview, binding.mainToolbar)
if (savedInstanceState != null) { if (savedInstanceState != null) {
saveCalculatorState = savedInstanceState.getCharSequence(CALCULATOR_STATE) as String saveCalculatorState = savedInstanceState.getCharSequence(CALCULATOR_STATE) as String
} }
calc = CalculatorImpl(this, applicationContext, decimalSeparator, groupingSeparator, saveCalculatorState) calc = CalculatorImpl(this, applicationContext, decimalSeparator, groupingSeparator, saveCalculatorState)
btn_plus.setOnClickOperation(PLUS) binding.btnPlus?.setOnClickOperation(PLUS)
btn_minus.setOnClickOperation(MINUS) binding.btnMinus?.setOnClickOperation(MINUS)
btn_multiply.setOnClickOperation(MULTIPLY) binding.btnMultiply?.setOnClickOperation(MULTIPLY)
btn_divide.setOnClickOperation(DIVIDE) binding.btnDivide?.setOnClickOperation(DIVIDE)
btn_percent.setOnClickOperation(PERCENT) binding.btnPercent?.setOnClickOperation(PERCENT)
btn_power.setOnClickOperation(POWER) binding.btnPower?.setOnClickOperation(POWER)
btn_root.setOnClickOperation(ROOT) binding.btnRoot?.setOnClickOperation(ROOT)
btn_minus.setOnLongClickListener { calc.turnToNegative() } binding.btnMinus?.setOnLongClickListener { calc.turnToNegative() }
btn_clear.setVibratingOnClickListener { calc.handleClear() } binding.btnClear?.setVibratingOnClickListener { calc.handleClear() }
btn_clear.setOnLongClickListener { binding.btnClear?.setOnLongClickListener {
calc.handleReset() calc.handleReset()
true true
} }
getButtonIds().forEach { getButtonIds().forEach {
it.setVibratingOnClickListener { view -> it?.setVibratingOnClickListener { view ->
calc.numpadClicked(view.id) calc.numpadClicked(view.id)
} }
} }
btn_equals.setVibratingOnClickListener { calc.handleEquals() } binding.btnEquals?.setVibratingOnClickListener { calc.handleEquals() }
formula.setOnLongClickListener { copyToClipboard(false) } binding.formula?.setOnLongClickListener { copyToClipboard(false) }
result.setOnLongClickListener { copyToClipboard(true) } binding.result?.setOnLongClickListener { copyToClipboard(true) }
AutofitHelper.create(result) AutofitHelper.create(binding.result)
AutofitHelper.create(formula) AutofitHelper.create(binding.formula)
storeStateVariables() storeStateVariables()
updateViewColors(calculator_holder, getProperTextColor()) binding.calculatorHolder?.let { updateViewColors(it, getProperTextColor()) }
setupDecimalSeparator() setupDecimalSeparator()
checkWhatsNewDialog() checkWhatsNewDialog()
checkAppOnSDCard() checkAppOnSDCard()
@ -81,9 +83,9 @@ class MainActivity : SimpleActivity(), Calculator {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(main_toolbar) setupToolbar(binding.mainToolbar)
if (storedTextColor != config.textColor) { if (storedTextColor != config.textColor) {
updateViewColors(calculator_holder, getProperTextColor()) binding.calculatorHolder?.let { updateViewColors(it, getProperTextColor()) }
} }
if (config.preventPhoneFromSleeping) { if (config.preventPhoneFromSleeping) {
@ -97,14 +99,16 @@ class MainActivity : SimpleActivity(), Calculator {
vibrateOnButtonPress = config.vibrateOnButtonPress vibrateOnButtonPress = config.vibrateOnButtonPress
arrayOf(btn_percent, btn_power, btn_root, btn_clear, btn_reset, btn_divide, btn_multiply, btn_plus, btn_minus, btn_equals, btn_decimal).forEach { binding.apply {
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme) arrayOf(btnPercent, btnPower, btnRoot, btnClear, btnReset, btnDivide, btnMultiply, btnPlus, btnMinus, btnEquals, btnDecimal).forEach {
it.background?.alpha = MEDIUM_ALPHA_INT it?.background = ResourcesCompat.getDrawable(resources, com.simplemobiletools.commons.R.drawable.pill_background, theme)
it?.background?.alpha = MEDIUM_ALPHA_INT
} }
arrayOf(btn_0, btn_1, btn_2, btn_3, btn_4, btn_5, btn_6, btn_7, btn_8, btn_9).forEach { arrayOf(btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9).forEach {
it.background = ResourcesCompat.getDrawable(resources, R.drawable.pill_background, theme) it?.background = ResourcesCompat.getDrawable(resources, com.simplemobiletools.commons.R.drawable.pill_background, theme)
it.background?.alpha = LOWER_ALPHA_INT it?.background?.alpha = LOWER_ALPHA_INT
}
} }
} }
@ -129,7 +133,7 @@ class MainActivity : SimpleActivity(), Calculator {
} }
private fun setupOptionsMenu() { private fun setupOptionsMenu() {
main_toolbar.setOnMenuItemClickListener { menuItem -> binding.mainToolbar.setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.history -> showHistory() R.id.history -> showHistory()
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent() R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
@ -142,8 +146,8 @@ class MainActivity : SimpleActivity(), Calculator {
} }
private fun refreshMenuItems() { private fun refreshMenuItems() {
main_toolbar.menu.apply { binding.mainToolbar.menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations) findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)
} }
} }
@ -163,7 +167,7 @@ class MainActivity : SimpleActivity(), Calculator {
private fun showHistory() { private fun showHistory() {
HistoryHelper(this).getHistory { HistoryHelper(this).getHistory {
if (it.isEmpty()) { if (it.isEmpty()) {
toast(R.string.history_empty) toast(com.simplemobiletools.calculator.R.string.history_empty)
} else { } else {
HistoryDialog(this, it, calc) HistoryDialog(this, it, calc)
} }
@ -180,27 +184,29 @@ class MainActivity : SimpleActivity(), Calculator {
val faqItems = arrayListOf( val faqItems = arrayListOf(
FAQItem(R.string.faq_1_title, R.string.faq_1_text), FAQItem(R.string.faq_1_title, R.string.faq_1_text),
FAQItem(R.string.faq_1_title_commons, R.string.faq_1_text_commons), FAQItem(com.simplemobiletools.commons.R.string.faq_1_title_commons, com.simplemobiletools.commons.R.string.faq_1_text_commons),
FAQItem(R.string.faq_4_title_commons, R.string.faq_4_text_commons) FAQItem(com.simplemobiletools.commons.R.string.faq_4_title_commons, com.simplemobiletools.commons.R.string.faq_4_text_commons)
) )
if (!resources.getBoolean(R.bool.hide_google_relations)) { if (!resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)) {
faqItems.add(FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons)) faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_2_title_commons, com.simplemobiletools.commons.R.string.faq_2_text_commons))
faqItems.add(FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons)) faqItems.add(FAQItem(com.simplemobiletools.commons.R.string.faq_6_title_commons, com.simplemobiletools.commons.R.string.faq_6_text_commons))
} }
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true) startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
} }
private fun getButtonIds() = arrayOf(btn_decimal, btn_0, btn_1, btn_2, btn_3, btn_4, btn_5, btn_6, btn_7, btn_8, btn_9) private fun getButtonIds() = binding.run {
arrayOf(btnDecimal, btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9)
private fun copyToClipboard(copyResult: Boolean): Boolean {
var value = formula.value
if (copyResult) {
value = result.value
} }
return if (value.isEmpty()) { private fun copyToClipboard(copyResult: Boolean): Boolean {
var value = binding.formula?.value
if (copyResult) {
value = binding.result?.value
}
return if (value.isNullOrEmpty()) {
false false
} else { } else {
copyToClipboard(value) copyToClipboard(value)
@ -209,19 +215,19 @@ class MainActivity : SimpleActivity(), Calculator {
} }
override fun showNewResult(value: String, context: Context) { override fun showNewResult(value: String, context: Context) {
result.text = value binding.result?.text = value
} }
private fun checkWhatsNewDialog() { private fun checkWhatsNewDialog() {
arrayListOf<Release>().apply { arrayListOf<Release>().apply {
add(Release(18, R.string.release_18)) add(Release(18, com.simplemobiletools.calculator.R.string.release_18))
add(Release(28, R.string.release_28)) add(Release(28, com.simplemobiletools.calculator.R.string.release_28))
checkWhatsNew(this, BuildConfig.VERSION_CODE) checkWhatsNew(this, BuildConfig.VERSION_CODE)
} }
} }
override fun showNewFormula(value: String, context: Context) { override fun showNewFormula(value: String, context: Context) {
formula.text = value binding.formula?.text = value
} }
private fun setupDecimalSeparator() { private fun setupDecimalSeparator() {
@ -234,7 +240,7 @@ class MainActivity : SimpleActivity(), Calculator {
groupingSeparator = COMMA groupingSeparator = COMMA
} }
calc.updateSeparators(decimalSeparator, groupingSeparator) calc.updateSeparators(decimalSeparator, groupingSeparator)
btn_decimal.text = decimalSeparator binding.btnDecimal?.text = decimalSeparator
} }
private fun View.setVibratingOnClickListener(callback: (view: View) -> Unit) { private fun View.setVibratingOnClickListener(callback: (view: View) -> Unit) {

View File

@ -1,33 +1,82 @@
package com.simplemobiletools.calculator.activities package com.simplemobiletools.calculator.activities
import android.app.ActivityManager
import android.content.Intent import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import com.simplemobiletools.calculator.R import android.view.View
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import com.simplemobiletools.calculator.compose.screens.SettingsScreen
import com.simplemobiletools.calculator.compose.theme.AppThemeSurface
import com.simplemobiletools.calculator.compose.theme.Theme
import com.simplemobiletools.calculator.databinding.ActivitySettingsBinding
import com.simplemobiletools.calculator.extensions.calculatorDB import com.simplemobiletools.calculator.extensions.calculatorDB
import com.simplemobiletools.calculator.extensions.config import com.simplemobiletools.calculator.extensions.config
import com.simplemobiletools.calculator.extensions.updateWidgets import com.simplemobiletools.calculator.extensions.updateWidgets
import com.simplemobiletools.calculator.extensions.viewBinding
import com.simplemobiletools.commons.activities.CustomizationActivity
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.helpers.NavigationIcon import java.util.Locale
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isTiramisuPlus
import kotlinx.android.synthetic.main.activity_settings.*
import java.util.*
import kotlin.system.exitProcess import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() { class SettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false) private val binding by viewBinding(ActivitySettingsBinding::inflate)
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar) private val preferences by lazy { config }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppThemeSurface {
SettingsScreen(
customizeColors = ::handleCustomizeColorsClick, goBack = ::finish,
backgroundColor = getProperBackgroundColor()
)
}
}
val backgroundColor = getProperBackgroundColor()
updateStatusbarColor(backgroundColor)
updateActionbarColor(backgroundColor)
//updateMaterialActivityViews(binding.settingsCoordinator, binding.settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
//setupMaterialScrollListener(binding.settingsNestedScrollview, binding.settingsToolbar)
}
fun updateStatusbarColor(color: Int) {
window.statusBarColor = color
if (color.getContrastColor() == DARK_GREY) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility.addBit(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
} else {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility.removeBit(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
}
}
fun updateActionbarColor(color: Int = getProperStatusBarColor()) {
updateStatusbarColor(color)
setTaskDescription(ActivityManager.TaskDescription(null, null, color))
}
fun updateNavigationBarColor(color: Int) {
window.navigationBarColor = color
updateNavigationBarButtons(color)
}
fun updateNavigationBarButtons(color: Int) {
if (isOreoPlus()) {
if (color.getContrastColor() == DARK_GREY) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility.addBit(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
} else {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility.removeBit(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR)
}
}
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
setupToolbar(settings_toolbar, NavigationIcon.Arrow) /*setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou() setupPurchaseThankYou()
setupCustomizeColors() setupCustomizeColors()
@ -37,66 +86,76 @@ class SettingsActivity : SimpleActivity() {
setupPreventPhoneFromSleeping() setupPreventPhoneFromSleeping()
setupUseCommaAsDecimalMark() setupUseCommaAsDecimalMark()
setupCustomizeWidgetColors() setupCustomizeWidgetColors()
updateTextColors(settings_nested_scrollview) updateTextColors(binding.settingsNestedScrollview)
arrayOf(settings_color_customization_section_label, settings_general_settings_label).forEach { arrayOf(binding.settingsColorCustomizationSectionLabel, binding.settingsGeneralSettingsLabel).forEach {
it.setTextColor(getProperPrimaryColor()) it.setTextColor(getProperPrimaryColor())
} }*/
} }
private fun setupPurchaseThankYou() { private fun setupPurchaseThankYou() {
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled()) binding.settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
settings_purchase_thank_you_holder.setOnClickListener { binding.settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent() launchPurchaseThankYouIntent()
} }
} }
private fun setupCustomizeColors() { private fun setupCustomizeColors() {
settings_color_customization_label.text = getCustomizeColorsString() binding.settingsWidgetColorCustomizationLabel.text = getCustomizeColorsString()
settings_color_customization_holder.setOnClickListener { binding.settingsWidgetColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick() handleCustomizeColorsClick()
} }
} }
private fun handleCustomizeColorsClick() {
Intent(applicationContext, CustomizationActivity::class.java).apply {
/*putExtra(APP_ICON_IDS, getAppIconIDs())
putExtra(APP_LAUNCHER_NAME, getAppLauncherName())*/
startActivity(this)
}
}
private fun setupUseEnglish() { private fun setupUseEnglish() {
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus()) binding.settingsUseEnglishHolder.beVisibleIf((preferences.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settings_use_english.isChecked = config.useEnglish binding.settingsUseEnglish.isChecked = preferences.useEnglish
settings_use_english_holder.setOnClickListener { binding.settingsUseEnglishHolder.setOnClickListener {
settings_use_english.toggle() binding.settingsUseEnglish.toggle()
config.useEnglish = settings_use_english.isChecked preferences.useEnglish = binding.settingsUseEnglish.isChecked
exitProcess(0) exitProcess(0)
} }
} }
private fun setupLanguage() { private fun setupLanguage() {
settings_language.text = Locale.getDefault().displayLanguage binding.settingsLanguage.text = Locale.getDefault().displayLanguage
settings_language_holder.beVisibleIf(isTiramisuPlus()) binding.settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
settings_language_holder.setOnClickListener { binding.settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// launchChangeAppLanguageIntent()
}
} }
} }
private fun setupVibrate() { private fun setupVibrate() {
settings_vibrate.isChecked = config.vibrateOnButtonPress binding.settingsVibrate.isChecked = preferences.vibrateOnButtonPress
settings_vibrate_holder.setOnClickListener { binding.settingsVibrateHolder.setOnClickListener {
settings_vibrate.toggle() binding.settingsVibrate.toggle()
config.vibrateOnButtonPress = settings_vibrate.isChecked preferences.vibrateOnButtonPress = binding.settingsVibrate.isChecked
} }
} }
private fun setupPreventPhoneFromSleeping() { private fun setupPreventPhoneFromSleeping() {
settings_prevent_phone_from_sleeping.isChecked = config.preventPhoneFromSleeping binding.settingsPreventPhoneFromSleeping.isChecked = preferences.preventPhoneFromSleeping
settings_prevent_phone_from_sleeping_holder.setOnClickListener { binding.settingsPreventPhoneFromSleepingHolder.setOnClickListener {
settings_prevent_phone_from_sleeping.toggle() binding.settingsPreventPhoneFromSleeping.toggle()
config.preventPhoneFromSleeping = settings_prevent_phone_from_sleeping.isChecked preferences.preventPhoneFromSleeping = binding.settingsPreventPhoneFromSleeping.isChecked
} }
} }
private fun setupUseCommaAsDecimalMark() { private fun setupUseCommaAsDecimalMark() {
settings_use_comma_as_decimal_mark.isChecked = config.useCommaAsDecimalMark binding.settingsUseCommaAsDecimalMark.isChecked = preferences.useCommaAsDecimalMark
settings_use_comma_as_decimal_mark_holder.setOnClickListener { binding.settingsUseCommaAsDecimalMark.setOnClickListener {
settings_use_comma_as_decimal_mark.toggle() binding.settingsUseCommaAsDecimalMark.toggle()
config.useCommaAsDecimalMark = settings_use_comma_as_decimal_mark.isChecked preferences.useCommaAsDecimalMark = binding.settingsUseCommaAsDecimalMark.isChecked
updateWidgets() updateWidgets()
ensureBackgroundThread { ensureBackgroundThread {
applicationContext.calculatorDB.deleteHistory() applicationContext.calculatorDB.deleteHistory()
@ -105,7 +164,7 @@ class SettingsActivity : SimpleActivity() {
} }
private fun setupCustomizeWidgetColors() { private fun setupCustomizeWidgetColors() {
settings_widget_color_customization_holder.setOnClickListener { binding.settingsWidgetColorCustomizationHolder.setOnClickListener {
Intent(this, WidgetConfigureActivity::class.java).apply { Intent(this, WidgetConfigureActivity::class.java).apply {
putExtra(IS_CUSTOMIZING_COLORS, true) putExtra(IS_CUSTOMIZING_COLORS, true)
startActivity(this) startActivity(this)

View File

@ -10,14 +10,14 @@ import android.widget.RemoteViews
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import com.simplemobiletools.calculator.R import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.databinding.WidgetConfigBinding
import com.simplemobiletools.calculator.extensions.config import com.simplemobiletools.calculator.extensions.config
import com.simplemobiletools.calculator.extensions.viewBinding
import com.simplemobiletools.calculator.helpers.MyWidgetProvider import com.simplemobiletools.calculator.helpers.MyWidgetProvider
import com.simplemobiletools.commons.dialogs.ColorPickerDialog import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.widget_config.*
class WidgetConfigureActivity : SimpleActivity() { class WidgetConfigureActivity : SimpleActivity() {
private var mBgAlpha = 0f private var mBgAlpha = 0f
@ -27,11 +27,13 @@ class WidgetConfigureActivity : SimpleActivity() {
private var mBgColorWithoutTransparency = 0 private var mBgColorWithoutTransparency = 0
private var mFeatureLockedDialog: FeatureLockedDialog? = null private var mFeatureLockedDialog: FeatureLockedDialog? = null
private val binding by viewBinding(WidgetConfigBinding::inflate)
public override fun onCreate(savedInstanceState: Bundle?) { public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false useDynamicTheme = false
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED) setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_config) setContentView(binding.root)
initVariables() initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
@ -41,12 +43,12 @@ class WidgetConfigureActivity : SimpleActivity() {
finish() finish()
} }
config_save.setOnClickListener { saveConfig() } binding.configSave.setOnClickListener { saveConfig() }
config_bg_color.setOnClickListener { pickBackgroundColor() } binding.configBgColor.setOnClickListener { pickBackgroundColor() }
config_text_color.setOnClickListener { pickTextColor() } binding.configTextColor.setOnClickListener { pickTextColor() }
val primaryColor = getProperPrimaryColor() val primaryColor = getProperPrimaryColor()
config_bg_seekbar.setColors(mTextColor, primaryColor, primaryColor) binding.configBgSeekbar.setColors(mTextColor, primaryColor, primaryColor)
if (!isCustomizingColors && !isOrWasThankYouInstalled()) { if (!isCustomizingColors && !isOrWasThankYouInstalled()) {
mFeatureLockedDialog = FeatureLockedDialog(this) { mFeatureLockedDialog = FeatureLockedDialog(this) {
@ -70,27 +72,27 @@ class WidgetConfigureActivity : SimpleActivity() {
mBgColor = config.widgetBgColor mBgColor = config.widgetBgColor
mBgAlpha = Color.alpha(mBgColor) / 255.toFloat() mBgAlpha = Color.alpha(mBgColor) / 255.toFloat()
btn_reset.beVisible() binding.configCalc.btnReset.beVisible()
mBgColorWithoutTransparency = Color.rgb(Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor)) mBgColorWithoutTransparency = Color.rgb(Color.red(mBgColor), Color.green(mBgColor), Color.blue(mBgColor))
config_bg_seekbar.setOnSeekBarChangeListener(seekbarChangeListener) binding.configBgSeekbar.setOnSeekBarChangeListener(seekbarChangeListener)
config_bg_seekbar.progress = (mBgAlpha * 100).toInt() binding.configBgSeekbar.progress = (mBgAlpha * 100).toInt()
updateBackgroundColor() updateBackgroundColor()
mTextColor = config.widgetTextColor mTextColor = config.widgetTextColor
if (mTextColor == resources.getColor(R.color.default_widget_text_color) && config.isUsingSystemTheme) { if (mTextColor == resources.getColor(com.simplemobiletools.commons.R.color.default_widget_text_color, theme) && config.isUsingSystemTheme) {
mTextColor = resources.getColor(R.color.you_primary_color, theme) mTextColor = resources.getColor(com.simplemobiletools.commons.R.color.you_primary_color, theme)
} }
updateTextColor() updateTextColor()
formula.text = "15,937*5" binding.configCalc.formula.text = "15,937*5"
result.text = "79,685" binding.configCalc.result.text = "79,685"
} }
private fun saveConfig() { private fun saveConfig() {
val appWidgetManager = AppWidgetManager.getInstance(this) ?: return val appWidgetManager = AppWidgetManager.getInstance(this) ?: return
val views = RemoteViews(packageName, R.layout.widget).apply { val views = RemoteViews(packageName, R.layout.widget).apply {
applyColorFilter(R.id.widget_background, mBgColor) applyColorFilter(binding.widgetBackground.id, mBgColor)
} }
appWidgetManager.updateAppWidget(mWidgetId, views) appWidgetManager.updateAppWidget(mWidgetId, views)
@ -121,13 +123,13 @@ class WidgetConfigureActivity : SimpleActivity() {
private fun updateBackgroundColor() { private fun updateBackgroundColor() {
mBgColor = mBgColorWithoutTransparency.adjustAlpha(mBgAlpha) mBgColor = mBgColorWithoutTransparency.adjustAlpha(mBgAlpha)
widget_background.applyColorFilter(mBgColor) binding.widgetBackground.applyColorFilter(mBgColor)
config_bg_color.setFillWithStroke(mBgColor, mBgColor) binding.configBgColor.setFillWithStroke(mBgColor, mBgColor)
config_save.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor()) binding.configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
} }
private fun updateTextColor() { private fun updateTextColor() {
config_text_color.setFillWithStroke(mTextColor, mTextColor) binding.configTextColor.setFillWithStroke(mTextColor, mTextColor)
val viewIds = intArrayOf( val viewIds = intArrayOf(
R.id.btn_0, R.id.btn_1, R.id.btn_2, R.id.btn_3, R.id.btn_4, R.id.btn_5, R.id.btn_6, R.id.btn_7, R.id.btn_8, R.id.btn_0, R.id.btn_1, R.id.btn_2, R.id.btn_3, R.id.btn_4, R.id.btn_5, R.id.btn_6, R.id.btn_7, R.id.btn_8,
@ -135,9 +137,10 @@ class WidgetConfigureActivity : SimpleActivity() {
R.id.btn_minus, R.id.btn_plus, R.id.btn_decimal, R.id.btn_equals R.id.btn_minus, R.id.btn_plus, R.id.btn_decimal, R.id.btn_equals
) )
result.setTextColor(mTextColor)
formula.setTextColor(mTextColor) binding.configCalc.result.setTextColor(mTextColor)
config_save.setTextColor(getProperPrimaryColor().getContrastColor()) binding.configCalc.formula.setTextColor(mTextColor)
binding.configSave.setTextColor(getProperPrimaryColor().getContrastColor())
viewIds.forEach { viewIds.forEach {
(findViewById<TextView>(it)).setTextColor(mTextColor) (findViewById<TextView>(it)).setTextColor(mTextColor)

View File

@ -3,23 +3,21 @@ package com.simplemobiletools.calculator.adapters
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.activities.SimpleActivity import com.simplemobiletools.calculator.activities.SimpleActivity
import com.simplemobiletools.calculator.databinding.HistoryViewBinding
import com.simplemobiletools.calculator.helpers.CalculatorImpl import com.simplemobiletools.calculator.helpers.CalculatorImpl
import com.simplemobiletools.calculator.models.History import com.simplemobiletools.calculator.models.History
import com.simplemobiletools.commons.extensions.copyToClipboard import com.simplemobiletools.commons.extensions.copyToClipboard
import com.simplemobiletools.commons.extensions.getProperTextColor import com.simplemobiletools.commons.extensions.getProperTextColor
import kotlinx.android.synthetic.main.history_view.view.*
class HistoryAdapter(val activity: SimpleActivity, val items: List<History>, val calc: CalculatorImpl, val itemClick: () -> Unit) : class HistoryAdapter(val activity: SimpleActivity, val items: List<History>, val calc: CalculatorImpl, val itemClick: () -> Unit) :
RecyclerView.Adapter<HistoryAdapter.ViewHolder>() { RecyclerView.Adapter<HistoryAdapter.ViewHolder>() {
private var textColor = activity.getProperTextColor() private var textColor = activity.getProperTextColor()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
val view = activity.layoutInflater.inflate(R.layout.history_view, parent, false) ViewHolder(HistoryViewBinding.inflate(activity.layoutInflater, parent, false))
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position] val item = items[position]
@ -28,13 +26,13 @@ class HistoryAdapter(val activity: SimpleActivity, val items: List<History>, val
override fun getItemCount() = items.size override fun getItemCount() = items.size
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { inner class ViewHolder(private val binding: HistoryViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bindView(item: History): View { fun bindView(item: History): View {
itemView.apply { itemView.apply {
item_formula.text = item.formula binding.itemFormula.text = item.formula
item_result.text = item.result binding.itemResult.text = item.result
item_formula.setTextColor(textColor) binding.itemFormula.setTextColor(textColor)
item_result.setTextColor(textColor) binding.itemResult.setTextColor(textColor)
setOnClickListener { setOnClickListener {
calc.addNumberToFormula(item.result) calc.addNumberToFormula(item.result)

View File

@ -0,0 +1,8 @@
package com.simplemobiletools.calculator.compose.extensions
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
class BooleanPreviewParameterProvider : PreviewParameterProvider<Boolean> {
override val values: Sequence<Boolean>
get() = sequenceOf(false, true)
}

View File

@ -0,0 +1,28 @@
package com.simplemobiletools.calculator.compose.extensions
import android.content.res.Configuration
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
const val LIGHT = "Light"
const val DARK = "Dark"
@MyDevicesDarkOnly
@MyDevicesLightOnly
annotation class MyDevices
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_4_XL, name = "6.3 inches dark", group = DARK)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_2, name = "5.0 inches dark", group = DARK)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_2_XL, name = "6.0 inches dark", group = DARK)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_4_XL, name = "5.5 inches dark", group = DARK)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_4, name = "5.7 inches dark", group = DARK)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.TABLET, name = "Tablet", group = DARK)
annotation class MyDevicesDarkOnly
@Preview(showBackground = true, device = Devices.PIXEL_4_XL, name = "6.3 inches light", group = LIGHT)
@Preview(showBackground = true, device = Devices.PIXEL_2, name = "5.0 inches light", group = LIGHT)
@Preview(showBackground = true, device = Devices.PIXEL_2_XL, name = "6.0 inches light", group = LIGHT)
@Preview(showBackground = true, device = Devices.PIXEL_XL, name = "5.5 inches light", group = LIGHT)
@Preview(showBackground = true, device = Devices.PIXEL_4, name = "5.7 inches light", group = LIGHT)
@Preview(showBackground = true, device = Devices.TABLET, name = "Tablet", group = DARK)
annotation class MyDevicesLightOnly

View File

@ -0,0 +1,88 @@
package com.simplemobiletools.calculator.compose.screens
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.graphics.toColor
import com.simplemobiletools.calculator.compose.extensions.MyDevices
import com.simplemobiletools.calculator.compose.settings.SettingsCheckBoxComponent
import com.simplemobiletools.calculator.compose.settings.SettingsGroup
import com.simplemobiletools.calculator.compose.settings.SettingsPreferenceComponent
import com.simplemobiletools.calculator.compose.settings.SettingsTitleTextComponent
import com.simplemobiletools.calculator.compose.theme.AppThemeSurface
import com.simplemobiletools.commons.R
@Composable
fun SettingsScreen(
goBack: () -> Unit,
customizeColors: () -> Unit,
backgroundColor: Int
) {
Scaffold(
modifier = Modifier
.fillMaxSize()
.background(Color(backgroundColor)),
topBar = {
TopAppBar(
title = {
Text(
text = stringResource(id = R.string.settings),
modifier = Modifier
.padding(start = 16.dp)
.fillMaxWidth()
)
},
navigationIcon = {
Icon(
imageVector = Icons.Filled.ArrowBack, contentDescription = stringResource(id = R.string.back),
modifier = Modifier
.clickable { goBack() }
.padding(start = 8.dp)
)
}
)
}
) { paddingValues ->
Column(
Modifier
.padding(paddingValues)
.verticalScroll(rememberScrollState())
) {
SettingsGroup(title = {
SettingsTitleTextComponent(text = stringResource(id = R.string.color_customization))
}) {
SettingsPreferenceComponent(preferenceTitle = stringResource(id = R.string.customize_colors), doOnPreferenceClick = customizeColors)
SettingsPreferenceComponent(preferenceTitle = stringResource(id = R.string.customize_widget_colors))
Spacer(modifier = Modifier.padding(bottom = 16.dp))
}
Divider()
SettingsGroup(title = {
SettingsTitleTextComponent(text = stringResource(id = R.string.general_settings))
}) {
SettingsPreferenceComponent(preferenceTitle = stringResource(id = R.string.purchase_simple_thank_you))
SettingsCheckBoxComponent(title = stringResource(id = R.string.use_english_language))
SettingsPreferenceComponent(preferenceTitle = stringResource(id = R.string.language), preferenceSummary = "English")
SettingsCheckBoxComponent(title = stringResource(id = R.string.vibrate_on_button_press))
SettingsCheckBoxComponent(title = stringResource(id = R.string.prevent_phone_from_sleeping))
SettingsCheckBoxComponent(title = stringResource(id = com.simplemobiletools.calculator.R.string.use_comma_as_decimal_mark))
}
}
}
}
@MyDevices
@Composable
private fun SettingsScreenPreview() {
AppThemeSurface { SettingsScreen(goBack = {}, customizeColors = {}, backgroundColor = MaterialTheme.colorScheme.background.toArgb()) }
}

View File

@ -0,0 +1,75 @@
package com.simplemobiletools.calculator.compose.settings
import androidx.compose.animation.AnimatedVisibility
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.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.simplemobiletools.calculator.compose.extensions.MyDevices
import com.simplemobiletools.calculator.compose.theme.AppThemeSurface
import com.simplemobiletools.calculator.compose.theme.preferenceSummaryColor
import com.simplemobiletools.calculator.compose.theme.preferenceTitleColor
@Composable
fun SettingsCheckBoxComponent(
modifier: Modifier = Modifier,
title: String,
summary: String? = null,
initialValue: Boolean = false,
isPreferenceEnabled: Boolean = true,
onChange: ((Boolean) -> Unit)? = null,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.padding(vertical = 14.dp, horizontal = 16.dp),
) {
Column(
modifier = Modifier.weight(1f),
) {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(end = 16.dp),
text = title,
fontSize = 16.sp,
color = preferenceTitleColor(isEnabled = isPreferenceEnabled),
)
AnimatedVisibility(visible = !summary.isNullOrBlank()) {
Text(
text = summary.toString(),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
.padding(end = 16.dp),
fontSize = 14.sp,
color = preferenceSummaryColor(isEnabled = isPreferenceEnabled),
)
}
}
Checkbox(
checked = initialValue,
onCheckedChange = { onChange?.invoke(it) },
enabled = isPreferenceEnabled,
)
}
}
@MyDevices
@Composable
private fun SettingsCheckBoxComponentPreview() {
AppThemeSurface {
SettingsCheckBoxComponent(
title = "Some title",
summary = "Some summary",
)
}
}

View File

@ -0,0 +1,64 @@
package com.simplemobiletools.calculator.compose.settings
import androidx.compose.foundation.layout.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.simplemobiletools.calculator.compose.extensions.MyDevices
@Composable
fun SettingsGroup(
modifier: Modifier = Modifier,
title: @Composable (() -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit,
) {
Surface {
Column(
modifier = modifier.fillMaxWidth(),
) {
if (title != null) {
SettingsGroupTitle(title)
}
content()
}
}
}
@Composable
internal fun SettingsGroupTitle(title: @Composable () -> Unit) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(64.dp)
.padding(horizontal = 16.dp),
contentAlignment = Alignment.CenterStart
) {
val primary = MaterialTheme.colorScheme.primary
val titleStyle = MaterialTheme.typography.headlineMedium.copy(color = primary)
ProvideTextStyle(value = titleStyle) { title() }
}
}
@MyDevices
@Composable
private fun SettingsGroupPreview() {
MaterialTheme {
SettingsGroup(
title = { Text(text = "Title") }
) {
Box(
modifier = Modifier
.height(64.dp)
.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
Text(text = "Settings group")
}
}
}
}

View File

@ -0,0 +1,68 @@
package com.simplemobiletools.calculator.compose.settings
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.simplemobiletools.calculator.compose.extensions.MyDevices
import com.simplemobiletools.calculator.compose.theme.AppThemeSurface
import com.simplemobiletools.calculator.compose.theme.preferenceSummaryColor
import com.simplemobiletools.calculator.compose.theme.preferenceTitleColor
import com.simplemobiletools.commons.R
@Composable
fun SettingsPreferenceComponent(
modifier: Modifier = Modifier,
preferenceTitle: String,
preferenceSummary: String? = null,
isPreferenceEnabled: Boolean = true,
doOnPreferenceLongClick: (() -> Unit)? = null,
doOnPreferenceClick: (() -> Unit)? = null,
) {
Column(
modifier = modifier
.fillMaxWidth()
.combinedClickable(
enabled = isPreferenceEnabled,
onClick = { doOnPreferenceClick?.invoke() },
onLongClick = { doOnPreferenceLongClick?.invoke() },
)
.padding(vertical = 14.dp, horizontal = 16.dp),
) {
Text(
text = preferenceTitle,
modifier = Modifier.fillMaxWidth(),
fontSize = 16.sp,
color = preferenceTitleColor(isEnabled = isPreferenceEnabled),
)
AnimatedVisibility(visible = !preferenceSummary.isNullOrBlank()) {
Text(
text = preferenceSummary.toString(),
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
fontSize = 14.sp,
color = preferenceSummaryColor(isEnabled = isPreferenceEnabled),
)
}
}
}
@MyDevices
@Composable
private fun SettingsPreferencePreview() {
AppThemeSurface {
SettingsPreferenceComponent(
preferenceTitle = stringResource(id = R.string.language),
preferenceSummary = stringResource(id = R.string.translation_english),
isPreferenceEnabled = true,
)
}
}

View File

@ -0,0 +1,38 @@
package com.simplemobiletools.calculator.compose.settings
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.simplemobiletools.calculator.compose.extensions.MyDevices
import com.simplemobiletools.calculator.compose.theme.AppThemeSurface
@Composable
fun SettingsTitleTextComponent(
modifier: Modifier = Modifier,
text: String,
) {
Box(modifier = Modifier.padding(top = 24.dp, bottom = 8.dp)) {
Text(
text = text.uppercase(),
modifier = modifier,
fontWeight = FontWeight(300),
color = MaterialTheme.colorScheme.primary,
fontSize = with(LocalDensity.current) {
dimensionResource(id = com.simplemobiletools.commons.R.dimen.normal_text_size).toSp()
},
)
}
}
@MyDevices
@Composable
private fun SettingsTitleTextComponentPreview() = AppThemeSurface {
SettingsTitleTextComponent(text = "Color customization")
}

View File

@ -0,0 +1,103 @@
package com.simplemobiletools.calculator.compose.theme
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.HIGHER_ALPHA
val primaryColor = Color(0xFFF57C00)
val secondaryColor = Color(0xFFD76D00)
val tertiaryColor = primaryColor
private val DarkColorScheme = darkColorScheme(
primary = primaryColor,
secondary = secondaryColor,
tertiary = tertiaryColor,
)
private val LightColorScheme = lightColorScheme(
primary = primaryColor,
secondary = secondaryColor,
tertiary = tertiaryColor,
)
@get:ReadOnlyComposable
val disabledTextColor @Composable get() = if (isSystemInDarkTheme()) Color.DarkGray else Color.LightGray
@get:ReadOnlyComposable
val textSubTitleColor
@Composable get() = if (isSystemInDarkTheme()) {
Color.White.copy(0.5f)
} else {
Color.Black.copy(
0.5f,
)
}
@Composable
fun preferenceSummaryColor(isEnabled: Boolean) =
if (isEnabled) textSubTitleColor else disabledTextColor
@Composable
fun preferenceTitleColor(isEnabled: Boolean) = if (isEnabled) Color.Unspecified else disabledTextColor
@Composable
fun Theme(
useTransparentNavigation: Boolean = true,
properBackgroundColor: Int,
content: @Composable () -> Unit,
statusBarColor: Int,
) {
//todo
val context = LocalContext.current
val systemUiController = rememberSystemUiController()
LaunchedEffect(Unit) {
if (context.navigationBarHeight > 0 || context.isUsingGestureNavigation() && useTransparentNavigation) {
systemUiController.isNavigationBarVisible = false
}
systemUiController.setStatusBarColor(
color = Color(statusBarColor)
)
systemUiController.setNavigationBarColor(Color(properBackgroundColor.adjustAlpha(HIGHER_ALPHA)))
}
MaterialTheme(
colorScheme = DarkColorScheme,
content = content,
)
}
@Composable
fun AppThemeSurface(
modifier: Modifier = Modifier,
properBackgroundColor: Int = LocalContext.current.getProperBackgroundColor(),
backgroundColor: Int = MaterialTheme.colorScheme.background.toArgb(),
statusBarColor: Int = LocalContext.current.getProperStatusBarColor(),
content: @Composable () -> Unit,
) {
Theme(properBackgroundColor = properBackgroundColor, content = {
Surface(
modifier = modifier
.fillMaxSize()
.background(Color(backgroundColor))
) {
content()
}
}, statusBarColor = statusBarColor)
}

View File

@ -4,6 +4,7 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.calculator.R import com.simplemobiletools.calculator.R
import com.simplemobiletools.calculator.activities.SimpleActivity import com.simplemobiletools.calculator.activities.SimpleActivity
import com.simplemobiletools.calculator.adapters.HistoryAdapter import com.simplemobiletools.calculator.adapters.HistoryAdapter
import com.simplemobiletools.calculator.databinding.DialogHistoryBinding
import com.simplemobiletools.calculator.extensions.calculatorDB import com.simplemobiletools.calculator.extensions.calculatorDB
import com.simplemobiletools.calculator.helpers.CalculatorImpl import com.simplemobiletools.calculator.helpers.CalculatorImpl
import com.simplemobiletools.calculator.models.History import com.simplemobiletools.calculator.models.History
@ -11,28 +12,28 @@ import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import kotlinx.android.synthetic.main.dialog_history.view.*
class HistoryDialog(activity: SimpleActivity, items: List<History>, calculator: CalculatorImpl) { class HistoryDialog(activity: SimpleActivity, items: List<History>, calculator: CalculatorImpl) {
var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
init { init {
val view = activity.layoutInflater.inflate(R.layout.dialog_history, null)
val view = DialogHistoryBinding.inflate(activity.layoutInflater, null, false)
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null) .setPositiveButton(com.simplemobiletools.commons.R.string.ok, null)
.setNeutralButton(R.string.clear_history) { _, _ -> .setNeutralButton(R.string.clear_history) { _, _ ->
ensureBackgroundThread { ensureBackgroundThread {
activity.applicationContext.calculatorDB.deleteHistory() activity.applicationContext.calculatorDB.deleteHistory()
activity.toast(R.string.history_cleared) activity.toast(R.string.history_cleared)
} }
}.apply { }.apply {
activity.setupDialogStuff(view, this, R.string.history) { alertDialog -> activity.setupDialogStuff(view.root, this, R.string.history) { alertDialog ->
dialog = alertDialog dialog = alertDialog
} }
} }
view.history_list.adapter = HistoryAdapter(activity, items, calculator) { view.historyList.adapter = HistoryAdapter(activity, items, calculator) {
dialog?.dismiss() dialog?.dismiss()
} }
} }

View File

@ -0,0 +1,10 @@
package com.simplemobiletools.calculator.extensions
import android.app.Activity
import android.view.LayoutInflater
import androidx.viewbinding.ViewBinding
inline fun <T : ViewBinding> Activity.viewBinding(crossinline bindingInflater: (LayoutInflater) -> T) =
lazy(LazyThreadSafetyMode.NONE) {
bindingInflater.invoke(layoutInflater)
}

View File

@ -281,7 +281,7 @@ class CalculatorImpl(
} }
if (result.isInfinite() || result.isNaN()) { if (result.isInfinite() || result.isNaN()) {
context.toast(R.string.unknown_error_occurred) context.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
return return
} }
@ -295,7 +295,7 @@ class CalculatorImpl(
inputDisplayedFormula = result.format() inputDisplayedFormula = result.format()
baseValue = result baseValue = result
} catch (e: Exception) { } catch (e: Exception) {
context.toast(R.string.unknown_error_occurred) context.toast(com.simplemobiletools.commons.R.string.unknown_error_occurred)
} }
} }
} }

View File

@ -1,29 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

5
build.gradle.kts Normal file
View File

@ -0,0 +1,5 @@
plugins {
alias(libs.plugins.android).apply(false)
alias(libs.plugins.kotlinAndroid).apply(false)
alias(libs.plugins.ksp).apply(false)
}

View File

@ -1,20 +1,12 @@
# Project-wide Gradle settings. org.gradle.jvmargs=-Xmx4g -XX:+UseGCOverheadLimit -XX:GCTimeLimit=10 -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.workers.max=8
# IDE (e.g. Android Studio) users: kotlin.code.style=official
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.enableJetifier=true
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.vfs.watch=true
org.gradle.configureondemand=true
org.gradle.unsafe.configuration-cache=true
org.gradle.unsafe.configuration-cache-problems=warn
android.nonTransitiveRClass=true

93
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,93 @@
[versions]
#jetbrains
kotlin = "1.8.21"
#KSP
ksp = "1.8.21-1.0.11"
#Androidx
androidx-customView = "1.2.0-alpha02"
androidx-customViewPooling = "1.0.0"
#Compose
composeActivity = "1.8.0-alpha06"
compose = "1.6.0-alpha01"
composeCompiler = "1.4.7"
composeMaterial3 = "1.2.0-alpha03"
accompanist = "0.31.4-beta"
#AutoFitTextView
autofittextview = "0.2.1"
#exp4j
exp4j = "0.4.8"
#Room
room = "2.5.2"
#Simple tools
simple-commons = "4c83ec8740"
#Gradle
gradlePlugins-agp = "7.3.1"
#build
app-build-compileSDKVersion = "34"
app-build-targetSDK = "33"
app-build-minimumSDK = "23"
app-build-javaVersion = "VERSION_17"
app-build-kotlinJVMTarget = "17"
#versioning
app-version-appId = "com.simplemobiletools.calculator"
app-version-versionCode = "60"
app-version-versionName = "5.11.3"
[libraries]
#Android X
androidx-customView = { module = "androidx.customview:customview", version.ref = "androidx-customView" }
androidx-customViewPooling = { module = "androidx.customview:customview-poolingcontainer", version.ref = "androidx-customViewPooling" }
#Room
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
#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" }
#UI
auto-fit-text-view = { module = "me.grantland:autofittextview", version.ref = "autofittextview" }
#Simple Mobile Tools
simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" }
#Exp4j
exp4j = { module = "net.objecthunter:exp4j", version.ref = "exp4j" }
#Accompanist
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }
[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",
]
room = [
"androidx-room-ktx",
"androidx-room-runtime",
]
accompanist = [
"accompanist-systemuicontroller",
]
[plugins]
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
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-7.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip

View File

@ -1 +0,0 @@
include ':app'

16
settings.gradle.kts Normal file
View File

@ -0,0 +1,16 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { setUrl("https://jitpack.io") }
}
}
include(":app")