diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..7be3f878 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +# https://editorconfig.org/ +# This configuration is used by ktlint when spotless invokes it + +[*.{kt,kts}] +ij_kotlin_allow_trailing_comma=true +ij_kotlin_allow_trailing_comma_on_call_site=true +ktlint_function_naming_ignore_when_annotated_with=Composable, Test diff --git a/.github/actions/prepare-keystore/action.yml b/.github/actions/prepare-keystore/action.yml new file mode 100644 index 00000000..228dc62e --- /dev/null +++ b/.github/actions/prepare-keystore/action.yml @@ -0,0 +1,34 @@ +name: Prepare KeyStore +description: Write the KeyStore file and properties to disk + +inputs: + signingStorePassword: + description: 'The password for the KeyStore' + required: true + signingKeyPassword: + description: 'The password for the Key' + required: true + signingKeyAlias: + description: 'The alias for the Key' + required: true + keyStoreBase64: + description: 'The KeyStore file encoded as base64' + required: true + +runs: + using: composite + steps: + - name: Write Keystore file 🗄️ + id: android_keystore + uses: timheuer/base64-to-file@v1.0.3 + with: + fileName: key.jks + encodedString: ${{ inputs.keyStoreBase64 }} + + - name: Write Keystore properties 🗝️ + shell: bash + run: | + echo "storeFile=${{ steps.android_keystore.outputs.filePath }}" > key.properties + echo "storePassword=${{ inputs.signingStorePassword }}" >> key.properties + echo "keyPassword=${{ inputs.signingKeyPassword }}" >> key.properties + echo "keyAlias=${{ inputs.signingKeyAlias }}" >> key.properties diff --git a/.github/workflows/build-testing.yaml b/.github/workflows/build-testing.yaml new file mode 100644 index 00000000..4cc6657b --- /dev/null +++ b/.github/workflows/build-testing.yaml @@ -0,0 +1,31 @@ +name: Build and push debug app + +on: + pull_request: + +jobs: + debug-builds: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: gradle/wrapper-validation-action@v2 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: "adopt" + java-version: 21 + cache: "gradle" + + - name: Run tests + run: ./gradlew test + + - name: Compile + run: ./gradlew assembleDebug + + - name: Upload APK + uses: actions/upload-artifact@v4 + with: + name: numberhub-app-debug-apks + path: app/build/outputs/apk/fdroid/debug/app-*-debug.apk \ No newline at end of file diff --git a/.github/workflows/release-app-github.yaml b/.github/workflows/release-app-github.yaml new file mode 100644 index 00000000..0c698bdc --- /dev/null +++ b/.github/workflows/release-app-github.yaml @@ -0,0 +1,52 @@ +name: Build and publish app + +on: + release: + types: [ published ] + +jobs: + release-app-github: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: gradle/wrapper-validation-action@v2 + + - name: Write KeyStore 🗝️ + uses: ./.github/actions/prepare-keystore + with: + signingStorePassword: ${{ secrets.SIGNING_STORE_PASSWORD }} + signingKeyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }} + signingKeyAlias: ${{ secrets.SIGNING_KEY_ALIAS }} + keyStoreBase64: ${{ secrets.KEYSTORE }} + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'adopt' + java-version: 21 + cache: 'gradle' + + - name: Build APKs 📱 + run: ./gradlew assembleRelease + + - name: Build AABs 📱 + run: ./gradlew bundleRelease + + - name: Upload APKs 🚀 + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + files: app/build/outputs/apk/fdroid/release/*.apk + + - name: Upload APKs bundles 🚀 + uses: softprops/action-gh-release@v1 + if: startsWith(github.ref, 'refs/tags/') + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + with: + files: app/build/outputs/bundle/fdroidRelease/*.aab \ No newline at end of file diff --git a/.run/spotlessApply.run.xml b/.run/spotlessApply.run.xml new file mode 100644 index 00000000..6eecd0a8 --- /dev/null +++ b/.run/spotlessApply.run.xml @@ -0,0 +1,42 @@ + + + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/.run/spotlessCheck.run.xml b/.run/spotlessCheck.run.xml new file mode 100644 index 00000000..9894de0a --- /dev/null +++ b/.run/spotlessCheck.run.xml @@ -0,0 +1,42 @@ + + + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/README.md b/README.md index 14c47e92..44e1339b 100644 --- a/README.md +++ b/README.md @@ -7,63 +7,14 @@

-# 📲 Download +## Notice -

- Google Play - F-Droid - GitHub -

+This app was originally created by [sadellie](https://github.com/sadellie). +Unfortunately, it has been archived on March 1st, 2024 (https://github.com/sadellie/unitto) +without any notice or explanation. +Since there has been no activity from sadellie on GitHub since then, I guess +they are not actively working on projects anymore. -Prefer _Google Play_ - -# 💁‍♀️ Contribute -

- -

- -

- Translate - Issues - Discussions -

- -## 👩‍💻 Do NOT contribute code -1. I do **NOT** need any help in code. -2. Hard forks and alterations of Unitto are **NOT** welcomed. Use a _Fork_ button so that commits' author is not lost. - -# ⚠ Security -Read [this](https://github.com/sadellie/unitto/wiki/Security). - -TL;DR: the app is legit, no cap fr fr - -## 🤖 Custom ROM developers -Leave. - -## 🤓 Nerds - -
-Benchmarks and Baseline profile - -``` -Pixel 8 - 14 - -StartupBenchmark_startupPrecompiledWithBaselineProfile -timeToInitialDisplayMs min 183.5, median 219.9, max 247.3 - -StartupBenchmark_startupWithoutPreCompilation -timeToInitialDisplayMs min 223.6, median 328.0, max 663.8 - -StartupBenchmark_startupWithPartialCompilationAndDisabledBaselineProfile -timeToInitialDisplayMs min 264.8, median 308.0, max 376.1 -StartupBenchmark_startupFullyPrecompiled -timeToInitialDisplayMs min 314.4, median 336.9, max 388.3 -``` -
- -## 🔎 Additional -Terms and Conditions: https://sadellie.github.io/unitto/terms - -Privacy Policy: https://sadellie.github.io/unitto/privacy - -FAQ: https://sadellie.github.io/unitto/faq +I will maintain this app, but I do not plan to add new features. +I don't have enough time to do that, but you are welcome to contribute. +I will review and merge your pull requests. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d2467e63..95c55499 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,11 +28,11 @@ plugins { } android { - namespace = "com.sadellie.unitto" + namespace = "app.myzel394.numberhub" compileSdk = 34 defaultConfig { - applicationId = "com.sadellie.unitto" + applicationId = "app.myzel394.numberhub" minSdk = 21 targetSdk = 34 versionCode = libs.versions.versionCode.get().toInt() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 60258a4c..59acccec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -50,7 +50,7 @@ diff --git a/app/src/main/java/com/sadellie/unitto/App.kt b/app/src/main/java/app/myzel394/numberhub/App.kt similarity index 87% rename from app/src/main/java/com/sadellie/unitto/App.kt rename to app/src/main/java/app/myzel394/numberhub/App.kt index c6762e63..6fc505dd 100644 --- a/app/src/main/java/com/sadellie/unitto/App.kt +++ b/app/src/main/java/app/myzel394/numberhub/App.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import androidx.activity.ComponentActivity import androidx.activity.SystemBarStyle @@ -37,14 +37,14 @@ import androidx.compose.ui.platform.LocalContext import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import com.sadellie.unitto.core.ui.common.NavigationDrawer -import com.sadellie.unitto.core.ui.common.rememberDrawerState -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.pushDynamicShortcut -import com.sadellie.unitto.core.ui.theme.DarkThemeColors -import com.sadellie.unitto.core.ui.theme.LightThemeColors -import com.sadellie.unitto.core.ui.theme.TypographySystem -import com.sadellie.unitto.data.model.userprefs.AppPreferences +import app.myzel394.numberhub.core.ui.common.NavigationDrawer +import app.myzel394.numberhub.core.ui.common.rememberDrawerState +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.pushDynamicShortcut +import app.myzel394.numberhub.core.ui.theme.DarkThemeColors +import app.myzel394.numberhub.core.ui.theme.LightThemeColors +import app.myzel394.numberhub.core.ui.theme.TypographySystem +import app.myzel394.numberhub.data.model.userprefs.AppPreferences import io.github.sadellie.themmo.Themmo import io.github.sadellie.themmo.ThemmoController import kotlinx.coroutines.launch @@ -76,14 +76,14 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) { dynamicThemeEnabled = prefs.enableDynamicTheme, amoledThemeEnabled = prefs.enableAmoledTheme, customColor = prefs.customColor.toColor(), - monetMode = prefs.monetMode + monetMode = prefs.monetMode, ) } Themmo( themmoController = themmoController, typography = TypographySystem, - animationSpec = tween(250) + animationSpec = tween(250), ) { val backgroundColor = MaterialTheme.colorScheme.background val isDarkThemeEnabled = remember(backgroundColor) { backgroundColor.luminance() < 0.5f } @@ -92,7 +92,8 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) { modifier = Modifier, state = drawerState, gesturesEnabled = gesturesEnabled, - tabs = DrawerItem.main, + mainTabs = DrawerItem.main, + additionalTabs = DrawerItem.additional, currentDestination = navBackStackEntry?.destination?.route, onItemClick = { destination -> drawerScope.launch { drawerState.close() } @@ -112,10 +113,9 @@ internal fun ComponentActivity.App(prefs: AppPreferences?) { navController = navController, themmoController = it, startDestination = prefs.startingScreen, - rpnMode = prefs.rpnMode, - openDrawer = { drawerScope.launch { drawerState.open() } } + openDrawer = { drawerScope.launch { drawerState.open() } }, ) - } + }, ) DisposableEffect(isDarkThemeEnabled) { diff --git a/app/src/main/java/com/sadellie/unitto/MainActivity.kt b/app/src/main/java/app/myzel394/numberhub/MainActivity.kt similarity index 82% rename from app/src/main/java/com/sadellie/unitto/MainActivity.kt rename to app/src/main/java/app/myzel394/numberhub/MainActivity.kt index c810ef4a..4967e317 100644 --- a/app/src/main/java/com/sadellie/unitto/MainActivity.kt +++ b/app/src/main/java/app/myzel394/numberhub/MainActivity.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import android.os.Bundle import androidx.activity.compose.setContent @@ -28,14 +28,14 @@ import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalConfiguration import androidx.core.os.ConfigurationCompat import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.ui.LocalHapticPreference -import com.sadellie.unitto.core.ui.LocalLocale -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.calculateWindowSizeClass -import com.sadellie.unitto.core.ui.theme.LocalNumberTypography -import com.sadellie.unitto.core.ui.theme.NumberTypographySystem -import com.sadellie.unitto.core.ui.theme.NumberTypographyUnitto -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.core.ui.LocalHapticPreference +import app.myzel394.numberhub.core.ui.LocalLocale +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.calculateWindowSizeClass +import app.myzel394.numberhub.core.ui.theme.LocalNumberTypography +import app.myzel394.numberhub.core.ui.theme.NumberTypographySystem +import app.myzel394.numberhub.core.ui.theme.NumberTypographyUnitto +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.AndroidEntryPoint import java.util.Locale import javax.inject.Inject @@ -68,7 +68,7 @@ internal class MainActivity : AppCompatActivity() { LocalLocale provides locale, LocalWindowSize provides calculateWindowSizeClass(this@MainActivity), LocalNumberTypography provides numbersTypography, - LocalHapticPreference provides (prefs?.enableVibrations ?: true) + LocalHapticPreference provides (prefs?.enableVibrations ?: true), ) { App(prefs) } diff --git a/app/src/main/java/com/sadellie/unitto/UnittoApplication.kt b/app/src/main/java/app/myzel394/numberhub/UnittoApplication.kt similarity index 91% rename from app/src/main/java/com/sadellie/unitto/UnittoApplication.kt rename to app/src/main/java/app/myzel394/numberhub/UnittoApplication.kt index 39b84d16..dced9782 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoApplication.kt +++ b/app/src/main/java/app/myzel394/numberhub/UnittoApplication.kt @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import android.app.Application import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp -internal class UnittoApplication: Application() +internal class UnittoApplication : Application() diff --git a/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt b/app/src/main/java/app/myzel394/numberhub/UnittoNavigation.kt similarity index 63% rename from app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt rename to app/src/main/java/app/myzel394/numberhub/UnittoNavigation.kt index a6bae2ec..46a41914 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoNavigation.kt +++ b/app/src/main/java/app/myzel394/numberhub/UnittoNavigation.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -26,14 +26,13 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost -import com.sadellie.unitto.feature.bodymass.navigation.bodyMassGraph -import com.sadellie.unitto.feature.calculator.navigation.calculatorGraph -import com.sadellie.unitto.feature.converter.navigation.converterGraph -import com.sadellie.unitto.feature.datecalculator.navigation.dateCalculatorGraph -import com.sadellie.unitto.feature.settings.navigation.navigateToSettings -import com.sadellie.unitto.feature.settings.navigation.navigateToUnitGroups -import com.sadellie.unitto.feature.settings.navigation.settingGraph -import com.sadellie.unitto.feature.timezone.navigation.timeZoneGraph +import app.myzel394.numberhub.feature.bodymass.navigation.bodyMassGraph +import app.myzel394.numberhub.feature.calculator.navigation.calculatorGraph +import app.myzel394.numberhub.feature.converter.navigation.converterGraph +import app.myzel394.numberhub.feature.datecalculator.navigation.dateCalculatorGraph +import app.myzel394.numberhub.feature.settings.navigation.navigateToUnitGroups +import app.myzel394.numberhub.feature.settings.navigation.settingGraph +import app.myzel394.numberhub.feature.timezone.navigation.timeZoneGraph import io.github.sadellie.themmo.ThemmoController @Composable @@ -42,47 +41,41 @@ internal fun UnittoNavigation( themmoController: ThemmoController, startDestination: String, openDrawer: () -> Unit, - rpnMode: Boolean, ) { NavHost( navController = navController, startDestination = startDestination, modifier = Modifier.background(MaterialTheme.colorScheme.background), enterTransition = { fadeIn() }, - exitTransition = { fadeOut() } + exitTransition = { fadeOut() }, ) { + calculatorGraph( + openDrawer = openDrawer, + ) + converterGraph( openDrawer = openDrawer, navController = navController, - navigateToSettings = navController::navigateToSettings, - navigateToUnitGroups = navController::navigateToUnitGroups - ) - - settingGraph( - themmoController = themmoController, - navController = navController - ) - - calculatorGraph( - openDrawer = openDrawer, - rpnMode = rpnMode, - navigateToSettings = navController::navigateToSettings + navigateToUnitGroups = navController::navigateToUnitGroups, ) dateCalculatorGraph( - navigateToMenu = openDrawer, - navigateToSettings = navController::navigateToSettings + openDrawer = openDrawer, ) timeZoneGraph( - navigateToMenu = openDrawer, - navigateToSettings = navController::navigateToSettings, + openDrawer = openDrawer, navController = navController, ) bodyMassGraph( openDrawer = openDrawer, - navigateToSettings = navController::navigateToSettings, + ) + + settingGraph( + openDrawer = openDrawer, + navController = navController, + themmoController = themmoController, ) } } diff --git a/app/src/main/java/com/sadellie/unitto/UnittoTileService.kt b/app/src/main/java/app/myzel394/numberhub/UnittoTileService.kt similarity index 89% rename from app/src/main/java/com/sadellie/unitto/UnittoTileService.kt rename to app/src/main/java/app/myzel394/numberhub/UnittoTileService.kt index 037b3678..151c92e9 100644 --- a/app/src/main/java/com/sadellie/unitto/UnittoTileService.kt +++ b/app/src/main/java/app/myzel394/numberhub/UnittoTileService.kt @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub +import android.annotation.SuppressLint import android.app.PendingIntent import android.content.Intent import android.os.Build @@ -26,6 +27,7 @@ import androidx.annotation.RequiresApi @RequiresApi(Build.VERSION_CODES.N) class UnittoTileService : TileService() { + @SuppressLint("StartActivityAndCollapseDeprecated") override fun onClick() { super.onClick() @@ -33,7 +35,7 @@ class UnittoTileService : TileService() { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)) + startActivityAndCollapse(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)) } else { @Suppress("DEPRECATION") startActivityAndCollapse(intent) diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts index 2b250614..074d9a7e 100644 --- a/benchmark/build.gradle.kts +++ b/benchmark/build.gradle.kts @@ -23,7 +23,7 @@ plugins { } android { - namespace = "com.sadellie.unitto.benchmark" + namespace = "app.myzel394.numberhub.benchmark" compileSdk = 34 defaultConfig { diff --git a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBaselineProfile.kt b/benchmark/src/main/java/app/myzel394/numberhub/benchmark/StartupBaselineProfile.kt similarity index 90% rename from benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBaselineProfile.kt rename to benchmark/src/main/java/app/myzel394/numberhub/benchmark/StartupBaselineProfile.kt index 0fb5f900..8eb5ae47 100644 --- a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBaselineProfile.kt +++ b/benchmark/src/main/java/app/myzel394/numberhub/benchmark/StartupBaselineProfile.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.benchmark +package app.myzel394.numberhub.benchmark import android.os.Build import androidx.annotation.RequiresApi @@ -30,8 +30,8 @@ class StartupBaselineProfile { @Test fun generate() = baselineProfileRule.collect( - packageName = "com.sadellie.unitto", - includeInStartupProfile = true + packageName = "app.myzel394.numberhub", + includeInStartupProfile = true, ) { startActivityAndWait() device.pressBack() diff --git a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt b/benchmark/src/main/java/app/myzel394/numberhub/benchmark/StartupBenchmark.kt similarity index 94% rename from benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt rename to benchmark/src/main/java/app/myzel394/numberhub/benchmark/StartupBenchmark.kt index cfef733e..fef504fd 100644 --- a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt +++ b/benchmark/src/main/java/app/myzel394/numberhub/benchmark/StartupBenchmark.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.benchmark +package app.myzel394.numberhub.benchmark import androidx.benchmark.macro.BaselineProfileMode import androidx.benchmark.macro.CompilationMode @@ -61,16 +61,16 @@ class StartupBenchmark { fun startupFullyPrecompiled() = startup(CompilationMode.Full()) private fun startup( - compilationMode: CompilationMode + compilationMode: CompilationMode, ) = benchmarkRule.measureRepeated( - packageName = "com.sadellie.unitto", + packageName = "app.myzel394.numberhub", metrics = listOf(StartupTimingMetric()), compilationMode = compilationMode, iterations = 10, startupMode = StartupMode.COLD, setupBlock = { pressHome() - } + }, ) { startActivityAndWait() } diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 6157fa19..238da172 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -20,7 +20,7 @@ plugins { `kotlin-dsl` } -group = "com.sadellie.unitto.buildlogic" +group = "app.myzel394.numberhub.buildlogic" java { sourceCompatibility = JavaVersion.VERSION_17 diff --git a/build-logic/convention/src/main/java/UnittoAndroidApplicationJacocoPlugin.kt b/build-logic/convention/src/main/java/UnittoAndroidApplicationJacocoPlugin.kt index fbcacf77..df2e24b0 100644 --- a/build-logic/convention/src/main/java/UnittoAndroidApplicationJacocoPlugin.kt +++ b/build-logic/convention/src/main/java/UnittoAndroidApplicationJacocoPlugin.kt @@ -17,7 +17,7 @@ */ import com.android.build.api.variant.ApplicationAndroidComponentsExtension -import com.sadellie.unitto.configureJacoco +import app.myzel394.numberhub.configureJacoco import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.getByType diff --git a/build-logic/convention/src/main/java/UnittoAndroidLibraryJacocoPlugin.kt b/build-logic/convention/src/main/java/UnittoAndroidLibraryJacocoPlugin.kt index a47b2850..acd458e3 100644 --- a/build-logic/convention/src/main/java/UnittoAndroidLibraryJacocoPlugin.kt +++ b/build-logic/convention/src/main/java/UnittoAndroidLibraryJacocoPlugin.kt @@ -17,7 +17,7 @@ */ import com.android.build.api.variant.LibraryAndroidComponentsExtension -import com.sadellie.unitto.configureJacoco +import app.myzel394.numberhub.configureJacoco import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.getByType diff --git a/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt b/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt index 6d0b8581..7b38982d 100644 --- a/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt +++ b/build-logic/convention/src/main/java/UnittoAndroidTestConventionPlugin.kt @@ -17,7 +17,7 @@ */ import com.android.build.gradle.TestExtension -import com.sadellie.unitto.configureKotlinAndroid +import app.myzel394.numberhub.configureKotlinAndroid import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.configure diff --git a/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt b/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt index a2daeee3..fe2fb657 100644 --- a/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt +++ b/build-logic/convention/src/main/java/UnittoLibraryComposePlugin.kt @@ -17,7 +17,7 @@ */ import com.android.build.api.dsl.LibraryExtension -import com.sadellie.unitto.configureCompose +import app.myzel394.numberhub.configureCompose import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalogsExtension diff --git a/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt b/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt index 1d76a8c8..2e498762 100644 --- a/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt +++ b/build-logic/convention/src/main/java/UnittoLibraryPlugin.kt @@ -17,7 +17,7 @@ */ import com.android.build.api.dsl.LibraryExtension -import com.sadellie.unitto.configureKotlinAndroid +import app.myzel394.numberhub.configureKotlinAndroid import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalogsExtension diff --git a/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureCompose.kt b/build-logic/convention/src/main/java/app/myzel394/numberhub/ConfigureCompose.kt similarity index 93% rename from build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureCompose.kt rename to build-logic/convention/src/main/java/app/myzel394/numberhub/ConfigureCompose.kt index c001a840..5ebda2b5 100644 --- a/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureCompose.kt +++ b/build-logic/convention/src/main/java/app/myzel394/numberhub/ConfigureCompose.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import com.android.build.api.dsl.CommonExtension import org.gradle.api.Project @@ -24,7 +24,7 @@ import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.kotlin.dsl.getByType internal fun Project.configureCompose( - commonExtension: CommonExtension<*, *, *, *, *>, + commonExtension: CommonExtension<*, *, *, *, *, *> ) { commonExtension.apply { buildFeatures { diff --git a/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt b/build-logic/convention/src/main/java/app/myzel394/numberhub/ConfigureKotlinAndroid.kt similarity index 95% rename from build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt rename to build-logic/convention/src/main/java/app/myzel394/numberhub/ConfigureKotlinAndroid.kt index 9ecda2a6..7d34eb92 100644 --- a/build-logic/convention/src/main/java/com/sadellie/unitto/ConfigureKotlinAndroid.kt +++ b/build-logic/convention/src/main/java/app/myzel394/numberhub/ConfigureKotlinAndroid.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import com.android.build.api.dsl.CommonExtension import org.gradle.api.JavaVersion @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions import org.jetbrains.kotlin.gradle.tasks.KotlinCompile internal fun Project.configureKotlinAndroid( - commonExtension: CommonExtension<*, *, *, *, *>, + commonExtension: CommonExtension<*, *, *, *, *, *>, ) { commonExtension.apply { compileSdk = 34 @@ -100,6 +100,6 @@ internal fun Project.configureKotlinAndroid( } } -fun CommonExtension<*, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { +fun CommonExtension<*, *, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { (this as ExtensionAware).extensions.configure("kotlinOptions", block) } diff --git a/build-logic/convention/src/main/java/com/sadellie/unitto/Jacoco.kt b/build-logic/convention/src/main/java/app/myzel394/numberhub/Jacoco.kt similarity index 98% rename from build-logic/convention/src/main/java/com/sadellie/unitto/Jacoco.kt rename to build-logic/convention/src/main/java/app/myzel394/numberhub/Jacoco.kt index 76194bda..896dbc87 100644 --- a/build-logic/convention/src/main/java/com/sadellie/unitto/Jacoco.kt +++ b/build-logic/convention/src/main/java/app/myzel394/numberhub/Jacoco.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import com.android.build.api.variant.AndroidComponentsExtension import org.gradle.api.Project diff --git a/build-logic/convention/src/main/java/com/sadellie/unitto/ProjectExtensions.kt b/build-logic/convention/src/main/java/app/myzel394/numberhub/ProjectExtensions.kt similarity index 97% rename from build-logic/convention/src/main/java/com/sadellie/unitto/ProjectExtensions.kt rename to build-logic/convention/src/main/java/app/myzel394/numberhub/ProjectExtensions.kt index 7f888f32..3e23de7f 100644 --- a/build-logic/convention/src/main/java/com/sadellie/unitto/ProjectExtensions.kt +++ b/build-logic/convention/src/main/java/app/myzel394/numberhub/ProjectExtensions.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto +package app.myzel394.numberhub import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalog diff --git a/core/base/build.gradle.kts b/core/base/build.gradle.kts index 77c5754b..73ad0b5b 100644 --- a/core/base/build.gradle.kts +++ b/core/base/build.gradle.kts @@ -22,7 +22,7 @@ plugins { } android { - namespace = "com.sadellie.unitto.core.base" + namespace = "app.myzel394.numberhub.core.base" defaultConfig { stringConfigField("VERSION_NAME", libs.versions.versionName.get()) @@ -33,13 +33,13 @@ android { getByName("playStore") { stringConfigField( "STORE_LINK", - "http://play.google.com/store/apps/details?id=com.sadellie.unitto" + "http://play.google.com/store/apps/details?id=app.myzel394.numberhub" ) } getByName("fdroid") { stringConfigField( "STORE_LINK", - "https://github.com/sadellie/unitto" + "https://github.com/Myzel394/NumberHub" ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt b/core/base/src/main/java/app/myzel394/numberhub/core/base/FormatterSymbols.kt similarity index 72% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt rename to core/base/src/main/java/app/myzel394/numberhub/core/base/FormatterSymbols.kt index 7ea14dce..91ba529f 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt +++ b/core/base/src/main/java/app/myzel394/numberhub/core/base/FormatterSymbols.kt @@ -16,3 +16,15 @@ * along with this program. If not, see . */ +package app.myzel394.numberhub.core.base + +/** + * Formatter symbols. Always use [Token]. + * + * @property grouping Symbol fpr thousands separator. + * @property fractional Symbol decimal separator. + */ +data class FormatterSymbols( + val grouping: String, + val fractional: String, +) diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/OutputFormat.kt b/core/base/src/main/java/app/myzel394/numberhub/core/base/OutputFormat.kt similarity index 96% rename from core/base/src/main/java/com/sadellie/unitto/core/base/OutputFormat.kt rename to core/base/src/main/java/app/myzel394/numberhub/core/base/OutputFormat.kt index 120c4a33..57700c52 100644 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/OutputFormat.kt +++ b/core/base/src/main/java/app/myzel394/numberhub/core/base/OutputFormat.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.base +package app.myzel394.numberhub.core.base /** * Output format here means whether or not use engineering notation @@ -24,8 +24,10 @@ package com.sadellie.unitto.core.base object OutputFormat { // Never use engineering notation const val PLAIN = 0 + // Use format that a lower API returns const val ALLOW_ENGINEERING = 1 + // App will try it's best to use engineering notation const val FORCE_ENGINEERING = 2 } diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/Precision.kt b/core/base/src/main/java/app/myzel394/numberhub/core/base/Precision.kt similarity index 95% rename from core/base/src/main/java/com/sadellie/unitto/core/base/Precision.kt rename to core/base/src/main/java/app/myzel394/numberhub/core/base/Precision.kt index f1b2e7a7..fade570e 100644 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/Precision.kt +++ b/core/base/src/main/java/app/myzel394/numberhub/core/base/Precision.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.base +package app.myzel394.numberhub.core.base /** * Current maximum scale that will be used in app. Used in various places in code. diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt b/core/base/src/main/java/app/myzel394/numberhub/core/base/Token.kt similarity index 93% rename from core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt rename to core/base/src/main/java/app/myzel394/numberhub/core/base/Token.kt index fbc9f5d6..1cda3b6d 100644 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt +++ b/core/base/src/main/java/app/myzel394/numberhub/core/base/Token.kt @@ -16,10 +16,16 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.base +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.base @Suppress("ObjectPropertyName") object Token { + const val SPACE = " " + const val PERIOD = "." + const val COMMA = "," + object Digit { const val _1 = "1" const val _2 = "2" @@ -96,14 +102,14 @@ object Token { val all by lazy { listOf( - arsin, arcos, actan, sin, cos, tan, log, exp, ln + arsin, arcos, actan, sin, cos, tan, log, exp, ln, ).sortedByDescending { it.length } } val allWithOpeningBracket by lazy { listOf( arsinBracket, arcosBracket, actanBracket, sinBracket, cosBracket, tanBracket, - logBracket, expBracket, lnBracket + logBracket, expBracket, lnBracket, ) } } @@ -140,7 +146,7 @@ object Token { Operator.multiply to listOf("*", "•"), Func.arsin to listOf("arsin"), Func.arcos to listOf("arcos"), - Func.actan to listOf("actan") + Func.actan to listOf("actan"), ) } } diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt b/core/base/src/main/java/app/myzel394/numberhub/core/base/TopLevelDestinations.kt similarity index 97% rename from core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt rename to core/base/src/main/java/app/myzel394/numberhub/core/base/TopLevelDestinations.kt index d658a51a..f31c8bbe 100644 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/TopLevelDestinations.kt +++ b/core/base/src/main/java/app/myzel394/numberhub/core/base/TopLevelDestinations.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.base +package app.myzel394.numberhub.core.base // Don't touch, users have "..._route" in their settings object TopLevelDestinations { diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/Separator.kt b/core/base/src/main/java/com/sadellie/unitto/core/base/Separator.kt deleted file mode 100644 index b5559383..00000000 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/Separator.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2022-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.base - -/** - * Separators mean symbols that separate fractional part - */ -object Separator { - const val SPACE = 0 - const val PERIOD = 1 - const val COMMA = 2 -} diff --git a/core/base/src/main/res/values/strings.xml b/core/base/src/main/res/values/strings.xml index dc3ef0bb..b6e9246b 100644 --- a/core/base/src/main/res/values/strings.xml +++ b/core/base/src/main/res/values/strings.xml @@ -21,7 +21,7 @@ Add - Unitto + NumberHub Height @@ -220,7 +220,7 @@ Used in this dialog window. Should be short --> https://s3.eu-west-1.amazonaws.com/po-pub/i/1oIHPj16krI0jyLmg4JaP2mk.png --> Selected item - About Unitto + About NumberHub Learn about the app @@ -245,6 +245,7 @@ Alternatively you can use "Export" --> Currency rates are updated daily. There\'s no real-time market monitoring in the app Wrong currency rates? Dark + Decimal separator Disable unit group Display App look and feel @@ -301,6 +302,7 @@ Maybe this can be labeled better? Let me know. It should be something that can d Use system font for texts in app Terms and Conditions Third party licenses + Thousands separator Settings Translate this app Join POEditor project to help @@ -320,6 +322,10 @@ Maybe this can be labeled better? Let me know. It should be something that can d View source code Add time zone + Unitto is now NumberHub! + Unitto has been discontinued. You\'re one of the first users to try NumberHub! Please spread the word and share the app with your friends. Thank you for your support! + NumberHub serves as a drop-in replacement for Unitto. It has the same features and more. NumberHub is still in beta and changes may occur. Please report any issues you find. Thanks for being one of the first to try it out! + Read the article diff --git a/core/base/src/test/java/com/sadellie/unitto/core/base/OutputFormatTest.kt b/core/base/src/test/java/app/myzel394/numberhub/core/base/OutputFormatTest.kt similarity index 96% rename from core/base/src/test/java/com/sadellie/unitto/core/base/OutputFormatTest.kt rename to core/base/src/test/java/app/myzel394/numberhub/core/base/OutputFormatTest.kt index 8768ffe8..7b776970 100644 --- a/core/base/src/test/java/com/sadellie/unitto/core/base/OutputFormatTest.kt +++ b/core/base/src/test/java/app/myzel394/numberhub/core/base/OutputFormatTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.base +package app.myzel394.numberhub.core.base import org.junit.Assert import org.junit.Test @@ -42,4 +42,4 @@ class OutputFormatTest { fun testOutputFormatForceEngineering() { Assert.assertEquals(2, OutputFormat.FORCE_ENGINEERING) } -} \ No newline at end of file +} diff --git a/core/base/src/test/java/com/sadellie/unitto/core/base/TokenTest.kt b/core/base/src/test/java/app/myzel394/numberhub/core/base/TokenTest.kt similarity index 87% rename from core/base/src/test/java/com/sadellie/unitto/core/base/TokenTest.kt rename to core/base/src/test/java/app/myzel394/numberhub/core/base/TokenTest.kt index 376d25d7..a19a15d8 100644 --- a/core/base/src/test/java/com/sadellie/unitto/core/base/TokenTest.kt +++ b/core/base/src/test/java/app/myzel394/numberhub/core/base/TokenTest.kt @@ -16,12 +16,20 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.base +package app.myzel394.numberhub.core.base import org.junit.Assert import org.junit.Test class TokenTest { + + @Test + fun testFormatterSymbols() { + Assert.assertEquals(" ", Token.SPACE) + Assert.assertEquals(".", Token.PERIOD) + Assert.assertEquals(",", Token.COMMA) + } + @Test fun testDigit() { Assert.assertEquals("1234567890", Token.Digit.all.joinToString("")) @@ -126,7 +134,7 @@ class TokenTest { "e", ).joinToString("") - Assert.assertEquals("1234567890.$operator$func$consts", Token.expressionTokens.joinToString("")) + Assert.assertEquals("1234567890.$operator$func${consts}E", Token.expressionTokens.joinToString("")) } @Test @@ -142,9 +150,14 @@ class TokenTest { @Test fun testSexyToUgly() { listOf( - "−", "÷", "×", "sin⁻¹", "cos⁻¹", "tan⁻¹" + "−", + "÷", + "×", + "sin⁻¹", + "cos⁻¹", + "tan⁻¹", ).forEach { assert(it in Token.sexyToUgly.keys) } } -} \ No newline at end of file +} diff --git a/core/base/src/test/java/com/sadellie/unitto/core/base/SeparatorTest.kt b/core/base/src/test/java/com/sadellie/unitto/core/base/SeparatorTest.kt deleted file mode 100644 index cf101bda..00000000 --- a/core/base/src/test/java/com/sadellie/unitto/core/base/SeparatorTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.base - -import org.junit.Assert -import org.junit.Test - -class SeparatorTest { - - @Test - fun testExists() { - Assert.assertNotNull(Separator) - } - - @Test - fun testSeparatorSpace() { - Assert.assertEquals(0, Separator.SPACE) - } - - @Test - fun testSeparatorPeriod() { - Assert.assertEquals(1, Separator.PERIOD) - } - - @Test - fun testSeparatorComma() { - Assert.assertEquals(2, Separator.COMMA) - } -} \ No newline at end of file diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index 2a659b51..b80f1bf8 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -23,7 +23,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.core.ui" +android.namespace = "app.myzel394.numberhub.core.ui" // Workaround from https://github.com/robolectric/robolectric/pull/4736 android.testOptions.unitTests.isIncludeAndroidResources = true diff --git a/core/ui/src/androidTest/java/com/sadellie/unitto/core/ui/ZonedDateTimeUtilsTest.kt b/core/ui/src/androidTest/java/app/myzel394/numberhub/core/ui/ZonedDateTimeUtilsTest.kt similarity index 97% rename from core/ui/src/androidTest/java/com/sadellie/unitto/core/ui/ZonedDateTimeUtilsTest.kt rename to core/ui/src/androidTest/java/app/myzel394/numberhub/core/ui/ZonedDateTimeUtilsTest.kt index 2ee51684..874e6488 100644 --- a/core/ui/src/androidTest/java/com/sadellie/unitto/core/ui/ZonedDateTimeUtilsTest.kt +++ b/core/ui/src/androidTest/java/app/myzel394/numberhub/core/ui/ZonedDateTimeUtilsTest.kt @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.createAndroidComposeRule -import com.sadellie.unitto.core.ui.datetime.formatOffset +import app.myzel394.numberhub.core.ui.datetime.formatOffset import org.junit.Assert.assertEquals import org.junit.Rule import org.junit.Test @@ -28,7 +28,7 @@ import java.time.ZonedDateTime class ZonedDateTimeUtilsTest { - @get: Rule + @get:Rule val composeTestRule = createAndroidComposeRule() @Test diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalHapticPreference.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalHapticPreference.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalHapticPreference.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalHapticPreference.kt index 33ae234c..599c7b9a 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalHapticPreference.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalHapticPreference.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import androidx.compose.runtime.compositionLocalOf diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalLocale.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalLocale.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalLocale.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalLocale.kt index e410c968..30717837 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalLocale.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalLocale.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import androidx.compose.runtime.compositionLocalOf import java.util.Locale diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalWindowSize.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalWindowSize.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalWindowSize.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalWindowSize.kt index 7a7fd006..422876f5 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/LocalWindowSize.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/LocalWindowSize.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import android.app.Activity import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi @@ -36,9 +36,10 @@ import androidx.compose.ui.util.fastForEach import androidx.window.layout.WindowMetricsCalculator val LocalWindowSize: ProvidableCompositionLocal = compositionLocalOf { - WindowSizeClass.calculateFromSize( - size = Size.Zero, - density = defaultDensity + // Phone in portrait mode + WindowSizeClass( + heightSizeClass = WindowHeightSizeClass.Medium, + widthSizeClass = WindowWidthSizeClass.Compact, ) } @@ -80,9 +81,9 @@ fun calculateWindowSizeClass(activity: Activity): WindowSizeClass { * @property heightSizeClass height-based window size class ([WindowHeightSizeClass]) */ @Immutable -class WindowSizeClass private constructor( +class WindowSizeClass( val widthSizeClass: WindowWidthSizeClass, - val heightSizeClass: WindowHeightSizeClass + val heightSizeClass: WindowHeightSizeClass, ) { companion object { /** @@ -117,7 +118,7 @@ class WindowSizeClass private constructor( supportedWidthSizeClasses: Set = WindowWidthSizeClass.DefaultSizeClasses, supportedHeightSizeClasses: Set = - WindowHeightSizeClass.DefaultSizeClasses + WindowHeightSizeClass.DefaultSizeClasses, ): WindowSizeClass { val windowWidthSizeClass = WindowWidthSizeClass.fromWidth(size.width, density, supportedWidthSizeClasses) @@ -224,7 +225,9 @@ value class WindowWidthSizeClass private constructor(private val value: Int) : /** Calculates the [WindowWidthSizeClass] for a given [width] */ internal fun fromWidth(width: Dp): WindowWidthSizeClass { return fromWidth( - with(defaultDensity) { width.toPx() }, defaultDensity, DefaultSizeClasses + with(defaultDensity) { width.toPx() }, + defaultDensity, + DefaultSizeClasses, ) } @@ -235,7 +238,7 @@ value class WindowWidthSizeClass private constructor(private val value: Int) : internal fun fromWidth( width: Float, density: Density, - supportedSizeClasses: Set + supportedSizeClasses: Set, ): WindowWidthSizeClass { require(width >= 0) { "Width must not be negative" } require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" } @@ -322,7 +325,9 @@ value class WindowHeightSizeClass private constructor(private val value: Int) : /** Calculates the [WindowHeightSizeClass] for a given [height] */ internal fun fromHeight(height: Dp): WindowHeightSizeClass { return fromHeight( - with(defaultDensity) { height.toPx() }, defaultDensity, DefaultSizeClasses + with(defaultDensity) { height.toPx() }, + defaultDensity, + DefaultSizeClasses, ) } @@ -333,7 +338,7 @@ value class WindowHeightSizeClass private constructor(private val value: Int) : internal fun fromHeight( height: Float, density: Density, - supportedSizeClasses: Set + supportedSizeClasses: Set, ): WindowHeightSizeClass { require(height >= 0) { "Width must not be negative" } require(supportedSizeClasses.isNotEmpty()) { "Must support at least one size class" } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/NavGraphBuilderExtensions.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/NavGraphBuilderExtensions.kt similarity index 77% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/NavGraphBuilderExtensions.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/NavGraphBuilderExtensions.kt index 93f79337..6ecaefc6 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/NavGraphBuilderExtensions.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/NavGraphBuilderExtensions.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.AnimatedContentTransitionScope @@ -44,16 +44,22 @@ fun NavGraphBuilder.unittoComposable( route: String, arguments: List = emptyList(), deepLinks: List = emptyList(), - enterTransition: (@JvmSuppressWildcards - AnimatedContentTransitionScope.() -> EnterTransition?)? = { unittoFadeIn() }, - exitTransition: (@JvmSuppressWildcards - AnimatedContentTransitionScope.() -> ExitTransition?)? = { unittoFadeOut() }, - popEnterTransition: (@JvmSuppressWildcards - AnimatedContentTransitionScope.() -> EnterTransition?)? = - enterTransition, - popExitTransition: (@JvmSuppressWildcards - AnimatedContentTransitionScope.() -> ExitTransition?)? = - exitTransition, + enterTransition: ( + @JvmSuppressWildcards + AnimatedContentTransitionScope.() -> EnterTransition? + )? = { unittoFadeIn() }, + exitTransition: ( + @JvmSuppressWildcards + AnimatedContentTransitionScope.() -> ExitTransition? + )? = { unittoFadeOut() }, + popEnterTransition: ( + @JvmSuppressWildcards + AnimatedContentTransitionScope.() -> EnterTransition? + )? = enterTransition, + popExitTransition: ( + @JvmSuppressWildcards + AnimatedContentTransitionScope.() -> ExitTransition? + )? = exitTransition, content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit, ): Unit = composable( route = route, @@ -79,22 +85,26 @@ fun NavGraphBuilder.unittoStackedComposable( enterTransition = { slideInHorizontally( animationSpec = unittoEnterTween(), - initialOffsetX = { (it * 0.2f).toInt() }) + unittoFadeIn() + initialOffsetX = { (it * 0.2f).toInt() }, + ) + unittoFadeIn() }, exitTransition = { slideOutHorizontally( animationSpec = unittoExitTween(), - targetOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeOut() + targetOffsetX = { -(it * 0.2f).toInt() }, + ) + unittoFadeOut() }, popEnterTransition = { slideInHorizontally( animationSpec = unittoEnterTween(), - initialOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeIn() + initialOffsetX = { -(it * 0.2f).toInt() }, + ) + unittoFadeIn() }, popExitTransition = { slideOutHorizontally( animationSpec = unittoExitTween(), - targetOffsetX = { (it * 0.2f).toInt() }) + unittoFadeOut() + targetOffsetX = { (it * 0.2f).toInt() }, + ) + unittoFadeOut() }, content = content, ) @@ -113,10 +123,10 @@ fun NavGraphBuilder.unittoNavigation( exitTransition: (AnimatedContentTransitionScope.() -> ExitTransition?)? = null, popEnterTransition: ( - AnimatedContentTransitionScope.() -> EnterTransition? + AnimatedContentTransitionScope.() -> EnterTransition? )? = enterTransition, popExitTransition: ( - AnimatedContentTransitionScope.() -> ExitTransition? + AnimatedContentTransitionScope.() -> ExitTransition? )? = exitTransition, builder: NavGraphBuilder.() -> Unit, ): Unit = navigation( @@ -128,7 +138,7 @@ fun NavGraphBuilder.unittoNavigation( exitTransition = exitTransition, popEnterTransition = popEnterTransition, popExitTransition = popExitTransition, - builder = builder + builder = builder, ) private const val ENTER_DURATION = 350 diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/ShortcutUtils.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/ShortcutUtils.kt similarity index 89% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/ShortcutUtils.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/ShortcutUtils.kt index 27bfe720..423d0e8f 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/ShortcutUtils.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/ShortcutUtils.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import android.app.PendingIntent import android.app.PendingIntent.FLAG_IMMUTABLE @@ -28,8 +28,8 @@ import androidx.annotation.RequiresApi import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.model.Shortcut +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.model.Shortcut import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -48,7 +48,7 @@ suspend fun Context.pushDynamicShortcut( val shortcutCompat = shortcutInfoCompat( context = context, route = drawerItem.graph, - shortcut = shortcut + shortcut = shortcut, ) kotlin.runCatching { @@ -71,7 +71,7 @@ fun Context.addShortcut( val shortcutCompat = shortcutInfoCompat( context = context, route = drawerItem.graph, - shortcut = shortcut + shortcut = shortcut, ) val shortCutIntent = ShortcutManagerCompat.createShortcutResultIntent(context, shortcutCompat) @@ -80,7 +80,7 @@ fun Context.addShortcut( ShortcutManagerCompat.requestPinShortcut( context, shortcutCompat, - PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender + PendingIntent.getBroadcast(context, 0, shortCutIntent, FLAG_IMMUTABLE).intentSender, ) } catch (e: Exception) { showToast(context, e.message ?: "Error") @@ -99,10 +99,10 @@ private fun Context.shortcutInfoCompat( .setIntent( Intent( Intent.ACTION_VIEW, - Uri.parse("app://com.sadellie.unitto/$route"), + Uri.parse("app://app.myzel394.numberhub/$route"), context, - context.javaClass - ) + context.javaClass, + ), ) .build() } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/UIUtils.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/UIUtils.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/UIUtils.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/UIUtils.kt index b7851b7f..e076166b 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/UIUtils.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/UIUtils.kt @@ -16,14 +16,14 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import android.content.ActivityNotFoundException import android.content.Context import android.net.Uri import android.widget.Toast import androidx.browser.customtabs.CustomTabsIntent -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R /** * Open given link in browser diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Button.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Button.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Button.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Button.kt index 81a4f8ae..d7aa479d 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Button.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Button.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.interaction.MutableInteractionSource @@ -50,7 +50,7 @@ fun Button( border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - content: @Composable RowScope.() -> Unit + content: @Composable RowScope.() -> Unit, ) { Surface( modifier = modifier.squashable( @@ -58,7 +58,7 @@ fun Button( onLongClick = onLongClick, interactionSource = interactionSource, cornerRadiusRange = 30..50, - enabled = enabled + enabled = enabled, ), color = containerColor, contentColor = contentColor, @@ -70,12 +70,12 @@ fun Button( Modifier .defaultMinSize( minWidth = ButtonDefaults.MinWidth, - minHeight = ButtonDefaults.MinHeight + minHeight = ButtonDefaults.MinHeight, ) .padding(contentPadding), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, - content = content + content = content, ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Chip.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Chip.kt similarity index 65% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Chip.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Chip.kt index d9ba0520..5626c870 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Chip.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Chip.kt @@ -16,9 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common -import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.animateColor +import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -26,7 +27,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.AssistChipDefaults import androidx.compose.material3.FilterChipDefaults @@ -40,6 +40,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.Preview @@ -48,41 +49,37 @@ import androidx.compose.ui.unit.dp @Composable fun FilterChip( modifier: Modifier = Modifier, - selected: Boolean, + isSelected: Boolean, onClick: () -> Unit, label: String, - imageVector: ImageVector, - contentDescription: String, ) { + val transition = updateTransition(targetState = isSelected, label = "Selected transition") + val backgroundColor = transition.animateColor(label = "Background color") { + if (it) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface + } + val borderColor = transition.animateColor(label = "Border color") { + if (it) Color.Transparent else MaterialTheme.colorScheme.outline + } + Row( modifier = modifier - .background( - color = if (selected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface, - shape = FilterChipDefaults.shape - ) + .padding(vertical = 8.dp) + .clip(FilterChipDefaults.shape) + .clickable { onClick() } + .background(backgroundColor.value) .border( width = 1.dp, - color = if (selected) Color.Transparent else MaterialTheme.colorScheme.outline, - shape = FilterChipDefaults.shape + color = borderColor.value, + shape = FilterChipDefaults.shape, ) .height(FilterChipDefaults.Height) - .clickable { onClick() } - .padding(start = 8.dp, end = 16.dp), - verticalAlignment = Alignment.CenterVertically + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically, ) { - AnimatedVisibility(visible = selected) { - Icon( - modifier = Modifier.height(FilterChipDefaults.IconSize), - imageVector = imageVector, - contentDescription = contentDescription, - tint = MaterialTheme.colorScheme.onPrimaryContainer - ) - } Text( - modifier = Modifier.padding(start = 8.dp), text = label, style = MaterialTheme.typography.labelLarge, - color = if (selected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant + color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -96,25 +93,24 @@ fun AssistChip( ) { Row( modifier = modifier - .background( - color = MaterialTheme.colorScheme.surface, - shape = AssistChipDefaults.shape - ) + .padding(vertical = 8.dp) + .clip(FilterChipDefaults.shape) + .clickable { onClick() } + .background(MaterialTheme.colorScheme.surface) .border( width = 1.dp, color = MaterialTheme.colorScheme.outline, - shape = AssistChipDefaults.shape + shape = AssistChipDefaults.shape, ) .height(32.dp) - .clickable { onClick() } .padding(horizontal = 8.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Icon( modifier = Modifier.height(AssistChipDefaults.IconSize), imageVector = imageVector, contentDescription = contentDescription, - tint = MaterialTheme.colorScheme.onSurfaceVariant + tint = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -125,7 +121,7 @@ fun PreviewAssistChip() { AssistChip( onClick = {}, imageVector = Icons.Default.Settings, - contentDescription = "" + contentDescription = "", ) } @@ -135,10 +131,8 @@ fun PreviewFilterChip() { var isSelected by remember { mutableStateOf(true) } FilterChip( - selected = isSelected, + isSelected = isSelected, onClick = { isSelected = !isSelected }, label = "Label", - imageVector = Icons.Default.Check, - contentDescription = "" ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/MenuButton.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/DrawerButton.kt similarity index 83% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/MenuButton.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/DrawerButton.kt index 1ad07c8e..e046b04c 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/MenuButton.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/DrawerButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Menu @@ -24,19 +24,19 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R /** - * Button that is used in Top bars + * Button that is used in Top bars to open drawer. * * @param onClick Action to be called when button is clicked. */ @Composable -fun MenuButton(onClick: () -> Unit) { +fun DrawerButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( - Icons.Outlined.Menu, - contentDescription = stringResource(R.string.open_menu_description) + imageVector = Icons.Outlined.Menu, + contentDescription = stringResource(R.string.open_menu_description), ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/DrawerItem.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/DrawerItem.kt similarity index 88% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/DrawerItem.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/DrawerItem.kt index da93b329..52dca27e 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/DrawerItem.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/DrawerItem.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.material3.Icon import androidx.compose.material3.NavigationDrawerItem @@ -25,7 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.model.DrawerItem @Composable internal fun DrawerItem( @@ -33,13 +33,13 @@ internal fun DrawerItem( destination: DrawerItem, icon: ImageVector, selected: Boolean, - onClick: (DrawerItem) -> Unit + onClick: (DrawerItem) -> Unit, ) { NavigationDrawerItem( modifier = modifier, label = { Text(stringResource(destination.name)) }, icon = { Icon(icon, stringResource(destination.name)) }, selected = selected, - onClick = { onClick(destination) } + onClick = { onClick(destination) }, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/EmptyScreen.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/EmptyScreen.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/EmptyScreen.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/EmptyScreen.kt index 0e75a287..defed681 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/EmptyScreen.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/EmptyScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Header.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Header.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Header.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Header.kt index 663cc7a5..3fa1e554 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Header.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Header.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.background import androidx.compose.foundation.layout.PaddingValues @@ -43,8 +43,8 @@ fun Header( start = 56.dp, end = 16.dp, top = 24.dp, - bottom = 12.dp - ) + bottom = 12.dp, + ), ) { Text( modifier = modifier @@ -53,6 +53,6 @@ fun Header( .fillMaxWidth(), text = text, style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.primary + color = MaterialTheme.colorScheme.primary, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/KeyboardButton.kt similarity index 80% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/KeyboardButton.kt index e5a8bab5..1bdb5c5f 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeyboardButton.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/KeyboardButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import android.view.HapticFeedbackConstants import androidx.compose.animation.core.tween @@ -36,7 +36,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalView -import com.sadellie.unitto.core.ui.LocalHapticPreference +import app.myzel394.numberhub.core.ui.LocalHapticPreference import kotlinx.coroutines.launch @Composable @@ -64,15 +64,24 @@ fun BasicKeyboardButton( Box( modifier = modifier .squashable( - onClick = { onClick(); vibrate() }, - onLongClick = if (onLongClick != null) { { onLongClick(); vibrate() } } else null, + onClick = { + onClick() + vibrate() + }, + onLongClick = if (onLongClick != null) { + { + onLongClick() + vibrate() + } + } else { + null + }, interactionSource = remember { MutableInteractionSource() }, cornerRadiusRange = 30..50, - animationSpec = tween(200) + animationSpec = tween(200), ) - .background(containerColor) - , - contentAlignment = Alignment.Center + .background(containerColor), + contentAlignment = Alignment.Center, ) { Icon( imageVector = icon, @@ -84,7 +93,7 @@ fun BasicKeyboardButton( scaleX = contentHeight scaleY = contentHeight }, - tint = iconColor + tint = iconColor, ) } } @@ -173,22 +182,25 @@ fun KeyboardButtonTertiary( ) } -/** - * Mostly for main button in portrait mode. Changes icon size inside. - */ -const val KeyboardButtonContentHeightTall = 1.1f +object KeyboardButtonToken { -/** - * Mostly for additional button in portrait mode. Changes icon size inside. - */ -const val KeyboardButtonContentHeightTallAdditional = 1.6f + /** + * Mostly for main button in portrait mode. Changes icon size inside. + */ + const val CONTENT_HEIGHT_TALL = 1.1f -/** - * Mostly for main button in landscape mode. Changes icon size inside. - */ -const val KeyboardButtonContentHeightShort = 1.3f + /** + * Mostly for additional button in portrait mode. Changes icon size inside. + */ + const val CONTENT_HEIGHT_TALL_ADDITIONAL = 1.6f -/** - * Mostly for additional button in landscape mode. Changes icon size inside. - */ -const val KeyboardButtonContentHeightShortAdditional = 1.1f + /** + * Mostly for main button in landscape mode. Changes icon size inside. + */ + const val CONTENT_HEIGHT_SHORT = 1.3f + + /** + * Mostly for additional button in landscape mode. Changes icon size inside. + */ + const val CONTENT_HEIGHT_SHORT_ADDITIONAL = 1.1f +} diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeypadFlow.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/KeypadFlow.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeypadFlow.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/KeypadFlow.kt index f100ccf2..8f749381 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/KeypadFlow.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/KeypadFlow.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.annotation.IntRange import androidx.compose.foundation.layout.Arrangement @@ -49,7 +49,7 @@ fun KeypadFlow( columns: Int, @IntRange(0, 100) horizontalPadding: Int = 10, @IntRange(0, 100) verticalPadding: Int = 10, - content: @Composable FlowRowScope.(width: Float, height: Float) -> Unit + content: @Composable FlowRowScope.(width: Float, height: Float) -> Unit, ) { val height: Float = remember { (1f - verticalPadding / 100f) / rows } val width: Float = remember { (1f - horizontalPadding / 100f) / columns } @@ -58,7 +58,7 @@ fun KeypadFlow( modifier = modifier, maxItemsInEachRow = columns, horizontalArrangement = Arrangement.SpaceAround, - verticalArrangement = Arrangement.SpaceAround + verticalArrangement = Arrangement.SpaceAround, ) { content(width, height) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ListItem.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ListItem.kt similarity index 91% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ListItem.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ListItem.kt index 5045fe61..bfdafb59 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ListItem.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ListItem.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -57,12 +57,12 @@ fun ListItem( .padding(start = 16.dp, end = 24.dp) .heightIn(min = if (supportingContent == null) 56.dp else 72.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { leadingContent?.let { ProvideColor( color = MaterialTheme.colorScheme.onSurfaceVariant, - content = it + content = it, ) } @@ -70,20 +70,20 @@ fun ListItem( ProvideStyle( color = MaterialTheme.colorScheme.onSurface, textStyle = MaterialTheme.typography.bodyLarge, - content = headlineContent + content = headlineContent, ) supportingContent?.let { ProvideStyle( color = MaterialTheme.colorScheme.onSurfaceVariant, textStyle = MaterialTheme.typography.bodyMedium, - content = it + content = it, ) } } trailingContent?.let { ProvideColor( color = MaterialTheme.colorScheme.onSurfaceVariant, - content = it + content = it, ) } } @@ -106,10 +106,10 @@ fun ListItem( imageVector = icon, contentDescription = iconDescription, modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant + tint = MaterialTheme.colorScheme.onSurfaceVariant, ) }, - trailingContent = trailing + trailingContent = trailing, ) @Composable @@ -120,14 +120,14 @@ fun ListItem( iconDescription: String = headlineText, supportingText: String? = null, switchState: Boolean, - onSwitchChange: (Boolean) -> Unit + onSwitchChange: (Boolean) -> Unit, ) = ListItem( modifier = modifier .clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(), onClick = { onSwitchChange(!switchState) }, - role = Role.Switch + role = Role.Switch, ), headlineText = headlineText, supportingText = supportingText, @@ -136,9 +136,9 @@ fun ListItem( trailing = { Switch( checked = switchState, - onCheckedChange = { onSwitchChange(it) } + onCheckedChange = { onSwitchChange(it) }, ) - } + }, ) @Preview @@ -152,7 +152,7 @@ fun PreviewListItem1() { leadingContent = { Icon( imageVector = Icons.Default.Home, - contentDescription = null + contentDescription = null, ) }, ) @@ -171,7 +171,7 @@ fun PreviewListItem1() { supportingText = "Support text support text support text support text", modifier = Modifier, trailing = {}, - iconDescription = "" + iconDescription = "", ) ListItem( diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/LocalProvider.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/LocalProvider.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/LocalProvider.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/LocalProvider.kt index 3df313ec..93e67103 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/LocalProvider.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/LocalProvider.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.material3.LocalContentColor import androidx.compose.material3.ProvideTextStyle diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ModifierExtensions.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ModifierExtensions.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ModifierExtensions.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ModifierExtensions.kt index 01bf1057..dc69ead3 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ModifierExtensions.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ModifierExtensions.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.core.AnimationSpec import androidx.compose.animation.core.animateDpAsState @@ -47,7 +47,7 @@ fun Modifier.squashable( val cornerRadius: Int by animateIntAsState( targetValue = if (isPressed) cornerRadiusRange.first else cornerRadiusRange.last, animationSpec = animationSpec, - label = "Squashed animation" + label = "Squashed animation", ) this @@ -58,7 +58,7 @@ fun Modifier.squashable( interactionSource = interactionSource, indication = rememberRipple(), role = role, - enabled = enabled + enabled = enabled, ) } @@ -75,7 +75,7 @@ fun Modifier.squashable( val cornerRadius: Dp by animateDpAsState( targetValue = if (isPressed) cornerRadiusRange.start else cornerRadiusRange.endInclusive, animationSpec = animationSpec, - label = "Squashed animation" + label = "Squashed animation", ) this @@ -86,6 +86,6 @@ fun Modifier.squashable( interactionSource = interactionSource, indication = rememberRipple(), role = role, - enabled = enabled + enabled = enabled, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/NavigateUpButton.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/NavigateUpButton.kt similarity index 92% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/NavigateUpButton.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/NavigateUpButton.kt index fe95a293..4b03cb8c 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/NavigateUpButton.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/NavigateUpButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack @@ -24,7 +24,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R /** * Button that is used in Top bars @@ -36,7 +36,7 @@ fun NavigateUpButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( Icons.AutoMirrored.Outlined.ArrowBack, - contentDescription = stringResource(R.string.navigate_up_description) + contentDescription = stringResource(R.string.navigate_up_description), ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/NavigationDrawer.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/NavigationDrawer.kt similarity index 85% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/NavigationDrawer.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/NavigationDrawer.kt index 95567aec..e14f2967 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/NavigationDrawer.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/NavigationDrawer.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.core.tween import androidx.compose.foundation.Canvas @@ -58,9 +58,9 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowWidthSizeClass -import com.sadellie.unitto.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowWidthSizeClass +import app.myzel394.numberhub.core.ui.model.DrawerItem import kotlinx.coroutines.launch import kotlin.math.roundToInt @@ -73,7 +73,7 @@ class DrawerState( initialValue = initialValue, positionalThreshold = { distance -> distance * 0.5f }, velocityThreshold = { with(requireNotNull(density)) { 400.dp.toPx() } }, - animationSpec = tween() + animationSpec = tween(), ) val isOpen: Boolean @@ -89,10 +89,10 @@ class DrawerState( suspend fun close() = anchoredDraggableState.animateTo(DrawerValue.Closed) companion object { - internal fun Saver() = + internal fun saver() = Saver( save = { it.currentValue }, - restore = { DrawerState(it) } + restore = { DrawerState(it) }, ) } } @@ -101,7 +101,7 @@ class DrawerState( fun rememberDrawerState( initialValue: DrawerValue = DrawerValue.Closed, ): DrawerState { - return rememberSaveable(saver = DrawerState.Saver()) { + return rememberSaveable(saver = DrawerState.saver()) { DrawerState(initialValue) } } @@ -111,7 +111,8 @@ fun NavigationDrawer( modifier: Modifier, gesturesEnabled: Boolean, state: DrawerState = rememberDrawerState(), - tabs: List, + mainTabs: List, + additionalTabs: List, currentDestination: String?, onItemClick: (DrawerItem) -> Unit, content: @Composable () -> Unit, @@ -123,16 +124,17 @@ fun NavigationDrawer( PermanentDrawerSheet( modifier = Modifier .fillMaxHeight() - .verticalScroll(rememberScrollState()) + .verticalScroll(rememberScrollState()), ) { SheetContent( - tabs = tabs, + mainTabs = mainTabs, + additionalTabs = additionalTabs, currentDestination = currentDestination, - onItemClick = onItemClick + onItemClick = onItemClick, ) } }, - content = content + content = content, ) } else { UnittoModalNavigationDrawer( @@ -141,18 +143,19 @@ fun NavigationDrawer( ModalDrawerSheet( modifier = Modifier .fillMaxHeight() - .verticalScroll(rememberScrollState()) + .verticalScroll(rememberScrollState()), ) { SheetContent( - tabs = tabs, + mainTabs = mainTabs, + additionalTabs = additionalTabs, currentDestination = currentDestination, - onItemClick = onItemClick + onItemClick = onItemClick, ) } }, gesturesEnabled = gesturesEnabled, state = state, - content = content + content = content, ) } } @@ -170,7 +173,7 @@ private fun UnittoModalNavigationDrawer( val drawerScope = rememberCoroutineScope() Box( - modifier = modifier.fillMaxSize() + modifier = modifier.fillMaxSize(), ) { val drawerWidth = 360.dp val drawerWidthPx = with(density) { drawerWidth.toPx() } @@ -183,7 +186,7 @@ private fun UnittoModalNavigationDrawer( DraggableAnchors { DrawerValue.Closed at minValue DrawerValue.Open at maxValue - } + }, ) } @@ -199,7 +202,7 @@ private fun UnittoModalNavigationDrawer( state = state.anchoredDraggableState, orientation = Orientation.Horizontal, enabled = gesturesEnabled or state.isOpen, - ) + ), ) Scrim( @@ -207,7 +210,9 @@ private fun UnittoModalNavigationDrawer( onClose = { if (gesturesEnabled) drawerScope.launch { state.close() } }, fraction = { fraction( - minValue, maxValue, state.anchoredDraggableState.requireOffset() + minValue, + maxValue, + state.anchoredDraggableState.requireOffset(), ) }, ) @@ -221,14 +226,14 @@ private fun UnittoModalNavigationDrawer( .anchoredDraggableState .requireOffset() .roundToInt(), - y = 0 + y = 0, ) } .anchoredDraggable( state = state.anchoredDraggableState, orientation = Orientation.Horizontal, enabled = gesturesEnabled or state.isOpen, - ) + ), ) { drawerContent() } @@ -251,7 +256,7 @@ private fun Scrim( Canvas( Modifier .fillMaxSize() - .then(dismissDrawer) + .then(dismissDrawer), ) { drawRect(color, alpha = fraction()) } @@ -263,12 +268,12 @@ private fun fraction(a: Float, b: Float, pos: Float) = @Preview( backgroundColor = 0xFFC8F7D4, showBackground = true, - device = "spec:width=320dp,height=500dp,dpi=320" + device = "spec:width=320dp,height=500dp,dpi=320", ) @Preview( backgroundColor = 0xFFC8F7D4, showBackground = true, - device = "spec:width=440dp,height=500dp,dpi=440" + device = "spec:width=440dp,height=500dp,dpi=440", ) @Composable private fun PreviewUnittoModalNavigationDrawerClose() { @@ -279,18 +284,19 @@ private fun PreviewUnittoModalNavigationDrawerClose() { modifier = Modifier, state = drawerState, gesturesEnabled = true, - tabs = DrawerItem.main, + mainTabs = DrawerItem.main, + additionalTabs = DrawerItem.additional, currentDestination = DrawerItem.Calculator.start, onItemClick = {}, content = { Column { Text(text = "Content") Button( - onClick = { corScope.launch { drawerState.open() } } + onClick = { corScope.launch { drawerState.open() } }, ) { Text(text = "BUTTON") } } - } + }, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PagedIsland.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/PagedIsland.kt similarity index 82% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PagedIsland.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/PagedIsland.kt index 210253f4..0df6cb00 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PagedIsland.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/PagedIsland.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.animateContentSize import androidx.compose.foundation.Canvas @@ -49,7 +49,7 @@ import kotlinx.coroutines.launch * [HorizontalPager] with a background and a page indicator. * * @param modifier [Modifier] that will be applied to the surround [Column]. - * @param pagerState [PagerState] that will passed [HorizontalPager]. + * @param pageCount Page count for [PagerState] that will passed [HorizontalPager]. * @param backgroundColor [Color] for background. * @param pageIndicatorAlignment [Alignment.Horizontal] for page indicator. * @param onClick Called on all clicks, even if the page didn't change. @@ -58,7 +58,7 @@ import kotlinx.coroutines.launch @Composable fun PagedIsland( modifier: Modifier = Modifier, - pagerState: PagerState, + pageCount: Int, backgroundColor: Color = MaterialTheme.colorScheme.secondaryContainer, pageIndicatorAlignment: Alignment.Horizontal = Alignment.End, onClick: () -> Unit = {}, @@ -67,6 +67,8 @@ fun PagedIsland( val contentColor = MaterialTheme.colorScheme.contentColorFor(backgroundColor) val disabledContentColor = contentColor.copy(alpha = 0.5f) val corScope = rememberCoroutineScope() + // https://stackoverflow.com/a/75469260 + val pagerState = rememberPagerState { pageCount * 1_000 } ProvideColor(color = contentColor) { Column( @@ -74,14 +76,17 @@ fun PagedIsland( .clip(RoundedCornerShape(32.dp)) .clickable { onClick() - if (pagerState.currentPage == (pagerState.pageCount - 1)) return@clickable + val targetPage = pagerState.currentPage + 1 corScope.launch { - pagerState.animateScrollToPage(pagerState.currentPage + 1) + pagerState.animateScrollToPage( + // Animate to first page if target page is out of bounds + if (targetPage >= pagerState.pageCount) 0 else targetPage, + ) } } .background(backgroundColor) - .padding(16.dp) + .padding(16.dp), ) { Row( modifier = Modifier @@ -89,8 +94,8 @@ fun PagedIsland( .padding(vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp, pageIndicatorAlignment), ) { - repeat(pagerState.pageCount) { - PageDot(if (it == pagerState.currentPage) contentColor else disabledContentColor) + repeat(pageCount) { + PageDot(if (it == pagerState.currentPage % pageCount) contentColor else disabledContentColor) } } @@ -99,10 +104,9 @@ fun PagedIsland( .animateContentSize() .fillMaxWidth(), verticalAlignment = Alignment.Top, - state = pagerState - ) { page -> - pageContent(page) - } + state = pagerState, + pageContent = { page -> pageContent(page % pageCount) }, + ) } } } @@ -121,7 +125,7 @@ private fun PageDot( private fun PreviewPagedIsland() { PagedIsland( modifier = Modifier.size(400.dp, 250.dp), - pagerState = rememberPagerState { 5 } + pageCount = 5, ) { currentPage -> Column { Text("Current page: $currentPage") diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PortraitLandscape.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/PortraitLandscape.kt similarity index 84% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PortraitLandscape.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/PortraitLandscape.kt index 6faba5d6..bbd0d80b 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PortraitLandscape.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/PortraitLandscape.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -26,9 +26,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.WindowWidthSizeClass +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowHeightSizeClass +import app.myzel394.numberhub.core.ui.WindowWidthSizeClass /** * When Portrait mode will place [content1] and [content2] in a [Column]. @@ -52,8 +52,11 @@ fun PortraitLandscape( .weight(1f) .fillMaxSize() .padding( - it.maxWidth * 0.015f, 0.dp, - it.maxHeight * 0.03f, it.maxHeight * 0.03f) + it.maxWidth * 0.015f, + 0.dp, + it.maxHeight * 0.03f, + it.maxHeight * 0.03f, + ) content1(contentModifier) content2(contentModifier) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ScaffoldWithLargeTopBar.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ScaffoldWithLargeTopBar.kt similarity index 91% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ScaffoldWithLargeTopBar.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ScaffoldWithLargeTopBar.kt index 773338f0..3a2c3372 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ScaffoldWithLargeTopBar.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ScaffoldWithLargeTopBar.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.RowScope @@ -41,10 +41,10 @@ fun ScaffoldWithLargeTopBar( title: String, navigationIcon: @Composable () -> Unit, actions: @Composable RowScope.() -> Unit = {}, - content: @Composable (PaddingValues) -> Unit + content: @Composable (PaddingValues) -> Unit, ) { val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior( - rememberTopAppBarState() + rememberTopAppBarState(), ) Scaffold( modifier = Modifier @@ -56,9 +56,9 @@ fun ScaffoldWithLargeTopBar( }, navigationIcon = navigationIcon, scrollBehavior = scrollBehavior, - actions = actions + actions = actions, ) }, - content = content + content = content, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ScaffoldWithTopBar.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ScaffoldWithTopBar.kt similarity index 83% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ScaffoldWithTopBar.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ScaffoldWithTopBar.kt index 2283e5ee..1845721e 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/ScaffoldWithTopBar.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/ScaffoldWithTopBar.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn @@ -33,9 +33,9 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.WindowWidthSizeClass +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowHeightSizeClass +import app.myzel394.numberhub.core.ui.WindowWidthSizeClass /** * Template screen. Uses [Scaffold] and [CenterAlignedTopAppBar] @@ -59,7 +59,7 @@ fun ScaffoldWithTopBar( floatingActionButton: @Composable () -> Unit = {}, floatingActionButtonPosition: FabPosition = FabPosition.End, scrollBehavior: TopAppBarScrollBehavior? = null, - content: @Composable (PaddingValues) -> Unit + content: @Composable (PaddingValues) -> Unit, ) { Scaffold( modifier = modifier, @@ -67,11 +67,15 @@ fun ScaffoldWithTopBar( AnimatedVisibility( visible = LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact, enter = slideInVertically() + fadeIn(), - exit = slideOutVertically() + fadeOut() + exit = slideOutVertically() + fadeOut(), ) { CenterAlignedTopAppBar( title = title, - navigationIcon = if (LocalWindowSize.current.widthSizeClass != WindowWidthSizeClass.Expanded) navigationIcon else { {} }, + navigationIcon = { + if (LocalWindowSize.current.widthSizeClass != WindowWidthSizeClass.Expanded) { + navigationIcon() + } + }, actions = actions, colors = colors, scrollBehavior = scrollBehavior, @@ -80,6 +84,6 @@ fun ScaffoldWithTopBar( }, floatingActionButton = floatingActionButton, floatingActionButtonPosition = floatingActionButtonPosition, - content = content + content = content, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SearchBar.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SearchBar.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SearchBar.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SearchBar.kt index fda7a005..12f974e7 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SearchBar.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SearchBar.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedVisibility @@ -72,7 +72,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R import kotlin.math.roundToInt @Composable @@ -109,7 +109,7 @@ fun SearchBar( modifier = modifier .windowInsetsPadding(TopAppBarDefaults.windowInsets) .height(height), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { Row( modifier = Modifier @@ -121,10 +121,9 @@ fun SearchBar( .fillMaxWidth() .padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { ProvideColor(MaterialTheme.colorScheme.onSurface) { - NavigateButton { if (notEmpty) clear() else navigateUp() } SearchTextField( @@ -135,7 +134,7 @@ fun SearchBar( value = query, placeholder = stringResource(R.string.search_text_field_placeholder), onValueChange = onQueryChange, - onSearch = onSearch + onSearch = onSearch, ) ClearButton(notEmpty, ::clear) @@ -152,7 +151,7 @@ private fun SearchTextField( value: TextFieldValue, placeholder: String, onValueChange: (TextFieldValue) -> Unit, - onSearch: KeyboardActionScope.() -> Unit + onSearch: KeyboardActionScope.() -> Unit, ) { BasicTextField( modifier = modifier, @@ -171,33 +170,33 @@ private fun SearchTextField( modifier = Modifier.alpha(0.7f), text = placeholder, style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSurface + color = MaterialTheme.colorScheme.onSurface, ) } - } + }, ) } @Composable private fun SearchButton( - onClick: () -> Unit + onClick: () -> Unit, ) { SearchBarIconButton(onClick) { Icon( imageVector = Icons.Default.Search, - contentDescription = stringResource(R.string.search_button_description) + contentDescription = stringResource(R.string.search_button_description), ) } } @Composable private fun NavigateButton( - onClick: () -> Unit + onClick: () -> Unit, ) { SearchBarIconButton(onClick) { Icon( imageVector = Icons.AutoMirrored.Outlined.ArrowBack, - contentDescription = stringResource(R.string.navigate_up_description) + contentDescription = stringResource(R.string.navigate_up_description), ) } } @@ -205,17 +204,17 @@ private fun NavigateButton( @Composable private fun ClearButton( visible: Boolean, - onClick: () -> Unit + onClick: () -> Unit, ) { AnimatedVisibility( visible = visible, enter = fadeIn(), - exit = fadeOut() + exit = fadeOut(), ) { SearchBarIconButton(onClick) { Icon( imageVector = Icons.Outlined.Clear, - contentDescription = stringResource(R.string.clear_input_description) + contentDescription = stringResource(R.string.clear_input_description), ) } } @@ -224,7 +223,7 @@ private fun ClearButton( @Composable fun SearchBarIconButton( onClick: () -> Unit, - content: @Composable () -> Unit + content: @Composable () -> Unit, ) { Box( modifier = Modifier @@ -236,10 +235,10 @@ fun SearchBarIconButton( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple( bounded = false, - radius = 20.dp - ) + radius = 20.dp, + ), ), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { content() } @@ -259,6 +258,6 @@ fun UnittoSearchBarPreview() { query = TextFieldValue("test"), onQueryChange = {}, navigateUp = {}, - scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() + scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(), ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SearchPlaceholder.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SearchPlaceholder.kt similarity index 87% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SearchPlaceholder.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SearchPlaceholder.kt index c7905dc5..64726a0d 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SearchPlaceholder.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SearchPlaceholder.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -35,35 +35,35 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R @Composable fun SearchPlaceholder( onButtonClick: () -> Unit, supportText: String, - buttonLabel: String + buttonLabel: String, ) { Column( modifier = Modifier .fillMaxWidth() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(16.dp) + verticalArrangement = Arrangement.spacedBy(16.dp), ) { Icon( imageVector = Icons.Default.SearchOff, contentDescription = stringResource(R.string.no_results_description), - modifier = Modifier.size(48.dp) + modifier = Modifier.size(48.dp), ) Text( text = stringResource(R.string.no_results_label), textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodyLarge + style = MaterialTheme.typography.bodyLarge, ) Text( text = supportText, textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodySmall, ) ElevatedButton(onClick = onButtonClick) { Text(text = buttonLabel) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SegmentedButton.kt similarity index 92% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SegmentedButton.kt index 6d5fce41..c9dd3253 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SegmentedButton.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SegmentedButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.Crossfade import androidx.compose.foundation.border @@ -47,14 +47,14 @@ import androidx.compose.ui.unit.dp @Composable fun SegmentedButtonsRow( modifier: Modifier = Modifier, - content: @Composable RowScope.() -> Unit + content: @Composable RowScope.() -> Unit, ) { Row( modifier .width(IntrinsicSize.Max) .height(40.dp) .clip(CircleShape) - .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape) + .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape), ) { content() } @@ -66,7 +66,7 @@ fun RowScope.SegmentedButton( label: String, onClick: () -> Unit, selected: Boolean, - icon: ImageVector? = null + icon: ImageVector? = null, ) { val containerColor = if (selected) MaterialTheme.colorScheme.secondaryContainer else MaterialTheme.colorScheme.surface @@ -77,9 +77,9 @@ fun RowScope.SegmentedButton( shape = RectangleShape, colors = ButtonDefaults.outlinedButtonColors( containerColor = containerColor, - contentColor = contentColorFor(containerColor) + contentColor = contentColorFor(containerColor), ), - contentPadding = PaddingValues(horizontal = 12.dp) + contentPadding = PaddingValues(horizontal = 12.dp), ) { if (icon != null) { Crossfade(selected, label = "Selected state") { diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SheetContent.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SheetContent.kt similarity index 77% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SheetContent.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SheetContent.kt index 8d5d5524..f0193c0e 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SheetContent.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/SheetContent.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.clickable @@ -38,16 +38,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.model.DrawerItem import kotlinx.coroutines.delay @Suppress("UnusedReceiverParameter") @Composable internal fun ColumnScope.SheetContent( - tabs: List, + mainTabs: List, + additionalTabs: List, currentDestination: String?, onItemClick: (DrawerItem) -> Unit, ) { @@ -68,38 +67,38 @@ internal fun ColumnScope.SheetContent( modifier = Modifier.clickable( interactionSource = interactionSource, indication = null, - onClick = { showHello = true } - ) + onClick = { showHello = true }, + ), ) { hello -> Text( text = if (hello) stringResource(R.string.hello_label) else stringResource(R.string.app_name), modifier = Modifier.padding(horizontal = 28.dp, vertical = 24.dp), style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.primary + color = MaterialTheme.colorScheme.primary, ) } - tabs.forEach { drawerItem -> + mainTabs.forEach { drawerItem -> val selected = drawerItem.start == currentDestination DrawerItem( modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding), destination = drawerItem, icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon, selected = selected, - onClick = onItemClick + onClick = onItemClick, ) } - // Top bar (and settings button in it) is not visible for compact height - if (LocalWindowSize.current.heightSizeClass == WindowHeightSizeClass.Compact) { - HorizontalDivider(Modifier.padding(horizontal = 12.dp, vertical = 8.dp)) + HorizontalDivider(Modifier.padding(horizontal = 12.dp, vertical = 8.dp)) + additionalTabs.forEach { drawerItem -> + val selected = drawerItem.start == currentDestination DrawerItem( modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding), - destination = DrawerItem.Settings, - icon = DrawerItem.Settings.defaultIcon, - selected = false, - onClick = onItemClick + destination = drawerItem, + icon = if (selected) drawerItem.selectedIcon else drawerItem.defaultIcon, + selected = selected, + onClick = onItemClick, ) } } @@ -109,13 +108,18 @@ internal fun ColumnScope.SheetContent( private fun PreviewDrawerSheet() { Column { SheetContent( - tabs = listOf( + mainTabs = listOf( + DrawerItem.Calculator, + DrawerItem.Calculator, + DrawerItem.Calculator, + ), + additionalTabs = listOf( DrawerItem.Calculator, DrawerItem.Calculator, DrawerItem.Calculator, ), currentDestination = DrawerItem.Calculator.start, - onItemClick = {} + onItemClick = {}, ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Slider.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Slider.kt similarity index 91% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Slider.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Slider.kt index f184d0e9..e32f1228 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Slider.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Slider.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.annotation.FloatRange import androidx.compose.animation.core.Spring @@ -56,12 +56,12 @@ fun Slider( value: Float, valueRange: ClosedFloatingPointRange, onValueChange: (Float) -> Unit, - onValueChangeFinished: (Float) -> Unit = {} + onValueChangeFinished: (Float) -> Unit = {}, ) { val animated = animateFloatAsState( targetValue = value.roundToInt().toFloat(), animationSpec = spring(), - label = "Thumb animation" + label = "Thumb animation", ) Slider( @@ -81,14 +81,14 @@ private fun SquigglyTrack( @FloatRange(0.0, 1.0) waveHeight: Float = 0.7f, strokeWidth: Float = 15f, filledColor: Color = MaterialTheme.colorScheme.primary, - unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant + unfilledColor: Color = MaterialTheme.colorScheme.surfaceVariant, ) { val coroutineScope = rememberCoroutineScope() - var direct by remember { mutableFloatStateOf(waveHeight * (100f - strokeWidth * 2f ) / 100f ) } + var direct by remember { mutableFloatStateOf(waveHeight * (100f - strokeWidth * 2f) / 100f) } val animatedDirect = animateFloatAsState( targetValue = direct, animationSpec = spring(stiffness = Spring.StiffnessLow), - label = "Track animation" + label = "Track animation", ) LaunchedEffect(sliderState.value) { @@ -101,7 +101,7 @@ private fun SquigglyTrack( Canvas( modifier = Modifier .fillMaxWidth() - .height(20.dp) + .height(20.dp), ) { val width = size.width val height = size.height @@ -114,7 +114,7 @@ private fun SquigglyTrack( val path = Path().apply { moveTo( x = initialOffset, - y = height.times(0.5f) + y = height.times(0.5f), ) val amount = ceil(width.div(eachWaveWidth)) @@ -125,7 +125,7 @@ private fun SquigglyTrack( dx1 = eachWaveWidth * 0.5f, dy1 = height.times(peek), dx2 = eachWaveWidth, - dy2 = 0f + dy2 = 0f, ) } } @@ -135,12 +135,12 @@ private fun SquigglyTrack( left = 0f, right = thumbPosition, bottom = height, - clipOp = ClipOp.Intersect + clipOp = ClipOp.Intersect, ) { drawPath( path = path, color = filledColor, - style = Stroke(strokeWidth, cap = StrokeCap.Round) + style = Stroke(strokeWidth, cap = StrokeCap.Round), ) } @@ -149,7 +149,7 @@ private fun SquigglyTrack( start = Offset(thumbPosition, height.times(0.5f)), end = Offset(width, height.times(0.5f)), strokeWidth = strokeWidth, - cap = StrokeCap.Round + cap = StrokeCap.Round, ) } } @@ -162,9 +162,9 @@ private fun SquigglyTrack( private fun PreviewNewSlider() { var currentValue by remember { mutableFloatStateOf(9f) } - com.sadellie.unitto.core.ui.common.Slider( + app.myzel394.numberhub.core.ui.common.Slider( value = currentValue, valueRange = 0f..16f, - onValueChange = { currentValue = it } + onValueChange = { currentValue = it }, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Switch.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Switch.kt similarity index 92% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Switch.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Switch.kt index 60a03247..d020a67e 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/Switch.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/Switch.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateDpAsState @@ -70,7 +70,7 @@ fun Switch( ) val thumbOffset = animateDpAsState( targetValue = if (checked) ThumbPaddingEnd else ThumbPaddingStart, - label = "Thumb offset" + label = "Thumb offset", ) Box( @@ -81,15 +81,15 @@ fun Switch( enabled = true, onClickLabel = null, role = Role.Switch, - onClick = { onCheckedChange(!checked) } + onClick = { onCheckedChange(!checked) }, ) .background(trackColor.value, CircleShape) .size(TrackWidth, TrackHeight) .border( TrackOutlineWidth, borderColor(enabled, checked, colors), - CircleShape - ) + CircleShape, + ), ) { Box( modifier = Modifier @@ -100,7 +100,7 @@ fun Switch( ) .align(Alignment.CenterStart) .background(thumbColor.value, CircleShape) - .size(thumbSize.value) + .size(thumbSize.value), ) } } @@ -109,7 +109,7 @@ fun Switch( private fun trackColor( enabled: Boolean, checked: Boolean, - colors: SwitchColors + colors: SwitchColors, ): Color = if (enabled) { if (checked) colors.checkedTrackColor else colors.uncheckedTrackColor @@ -121,7 +121,7 @@ private fun trackColor( private fun thumbColor( enabled: Boolean, checked: Boolean, - colors: SwitchColors + colors: SwitchColors, ): Color = if (enabled) { if (checked) colors.checkedThumbColor else colors.uncheckedThumbColor @@ -133,7 +133,7 @@ private fun thumbColor( private fun borderColor( enabled: Boolean, checked: Boolean, - colors: SwitchColors + colors: SwitchColors, ): Color = if (enabled) { if (checked) colors.checkedBorderColor else colors.uncheckedBorderColor @@ -147,7 +147,7 @@ val TrackOutlineWidth = 1.8.dp val SelectedHandleSize = 20.0.dp val UnselectedHandleSize = 20.0.dp -val ThumbPaddingStart = (TrackHeight - UnselectedHandleSize) / 2 +val ThumbPaddingStart = (TrackHeight - UnselectedHandleSize) / 2 val ThumbPaddingEnd = TrackWidth - SelectedHandleSize / 2 - TrackHeight / 2 @Preview @@ -156,6 +156,6 @@ fun PreviewPixelSwitch() { var checked by remember { mutableStateOf(false) } Switch( checked = checked, - onCheckedChange = { checked = !checked } + onCheckedChange = { checked = !checked }, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/WithConstraints.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/WithConstraints.kt similarity index 86% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/WithConstraints.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/WithConstraints.kt index 37602a6f..cf176672 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/WithConstraints.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/WithConstraints.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package app.myzel394.numberhub.core.ui.common import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.BoxWithConstraints @@ -34,11 +34,11 @@ fun ColumnWithConstraints( modifier: Modifier = Modifier, verticalArrangement: Arrangement.Vertical = Arrangement.Top, horizontalAlignment: Alignment.Horizontal = Alignment.Start, - content: @Composable (ColumnScope.(BoxWithConstraintsScope)-> Unit) + content: @Composable (ColumnScope.(BoxWithConstraintsScope) -> Unit), ) = BoxWithConstraints(modifier) { Column( verticalArrangement = verticalArrangement, - horizontalAlignment = horizontalAlignment + horizontalAlignment = horizontalAlignment, ) { content(this@BoxWithConstraints) } } @@ -47,10 +47,10 @@ fun RowWithConstraints( modifier: Modifier = Modifier, horizontalArrangement: Arrangement.Horizontal = Arrangement.Start, verticalAlignment: Alignment.Vertical = Alignment.Top, - content: @Composable (RowScope.(BoxWithConstraintsScope)-> Unit) + content: @Composable (RowScope.(BoxWithConstraintsScope) -> Unit), ) = BoxWithConstraints(modifier) { Row( horizontalArrangement = horizontalArrangement, - verticalAlignment = verticalAlignment + verticalAlignment = verticalAlignment, ) { content(this@BoxWithConstraints) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/autosize/AutoSizeTextStyleBox.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/autosize/AutoSizeTextStyleBox.kt similarity index 82% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/autosize/AutoSizeTextStyleBox.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/autosize/AutoSizeTextStyleBox.kt index 32fee842..966ccc41 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/autosize/AutoSizeTextStyleBox.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/autosize/AutoSizeTextStyleBox.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.autosize +package app.myzel394.numberhub.core.ui.common.autosize import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.BoxWithConstraintsScope @@ -43,54 +43,6 @@ import androidx.compose.ui.unit.TextUnit import kotlin.math.min import kotlin.math.roundToInt -// HUGE performance drop. Don't use for buttons -///** -// * Composable function that automatically adjusts the text size to fit within given constraints using AnnotatedString, considering the ratio of line spacing to text size. -// * -// * Features: -// * Similar to AutoSizeText(String), with support for AnnotatedString. -// * -// * @param inlineContent a map storing composables that replaces certain ranges of the text, used to -// * insert composables into text layout. See [InlineTextContent]. -// * @see AutoSizeText -// */ -//@Composable -//internal fun AutoSizeText( -// text: AnnotatedString, -// modifier: Modifier = Modifier, -// minRatio: Float = 1f, -// maxTextSize: TextUnit = TextUnit.Unspecified, -// alignment: Alignment = Alignment.TopStart, -// overflow: TextOverflow = TextOverflow.Clip, -// softWrap: Boolean = true, -// maxLines: Int = Int.MAX_VALUE, -// minLines: Int = 1, -// inlineContent: Map = mapOf(), -// onTextLayout: (TextLayoutResult) -> Unit = {}, -// style: TextStyle = LocalTextStyle.current, -//) = AutoSizeTextStyleBox( -// modifier = modifier, -// text = text, -// maxTextSize = maxTextSize, -// maxLines = maxLines, -// minLines = minLines, -// softWrap = softWrap, -// style = style, -// minRatio = minRatio, -// alignment = alignment -//) { -// Text( -// text = text, -// overflow = overflow, -// softWrap = softWrap, -// maxLines = maxLines, -// minLines = minLines, -// inlineContent = inlineContent, -// onTextLayout = onTextLayout, -// style = LocalTextStyle.current, -// ) -//} - /** * [BoxWithConstraints] with [autoTextStyle] passed via [LocalTextStyle]. * @@ -122,11 +74,11 @@ internal fun AutoSizeTextStyleBox( style: TextStyle, minRatio: Float, alignment: Alignment, - content: @Composable () -> Unit + content: @Composable () -> Unit, ) { val density = LocalDensity.current CompositionLocalProvider( - LocalDensity provides Density(density = density.density, fontScale = 1F) + LocalDensity provides Density(density = density.density, fontScale = 1F), ) { BoxWithConstraints( modifier = modifier, @@ -141,12 +93,12 @@ internal fun AutoSizeTextStyleBox( style = style, alignment = alignment, density = density, - minRatio = minRatio + minRatio = minRatio, ) CompositionLocalProvider( value = LocalTextStyle.provides(autoTextStyle), - content = content + content = content, ) } } @@ -290,10 +242,11 @@ private fun IntProgression.findElectedValue( var high = last while (low <= high) { val mid = low + (high - low) / 2 - if (shouldMoveBackward(transform(mid))) + if (shouldMoveBackward(transform(mid))) { high = mid - 1 - else + } else { low = mid + 1 + } } transform(high.coerceAtLeast(minimumValue = first)) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/autosize/DensityExt.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/autosize/DensityExt.kt similarity index 85% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/autosize/DensityExt.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/autosize/DensityExt.kt index 4bf23835..f33ea9e6 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/autosize/DensityExt.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/autosize/DensityExt.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.autosize +package app.myzel394.numberhub.core.ui.common.autosize import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.DpSize @@ -27,5 +27,8 @@ import androidx.compose.ui.unit.isSpecified internal fun Density.roundToPx(sp: TextUnit): Int = sp.roundToPx() internal fun Density.toSp(px: Int): TextUnit = px.toSp() internal fun Density.toIntSize(dpSize: DpSize): IntSize = - if (dpSize.isSpecified) IntSize(dpSize.width.roundToPx(), dpSize.height.roundToPx()) - else IntSize.Zero + if (dpSize.isSpecified) { + IntSize(dpSize.width.roundToPx(), dpSize.height.roundToPx()) + } else { + IntSize.Zero + } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/DatePickerDialog.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/datetimepicker/DatePickerDialog.kt similarity index 90% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/DatePickerDialog.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/datetimepicker/DatePickerDialog.kt index 4abee43e..904c7315 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/DatePickerDialog.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/datetimepicker/DatePickerDialog.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.datetimepicker +package app.myzel394.numberhub.core.ui.common.datetimepicker import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -43,7 +43,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R import java.time.Instant import java.time.LocalDateTime import java.time.ZoneId @@ -67,7 +67,7 @@ fun DatePickerDialog( BasicAlertDialog( onDismissRequest = onDismiss, modifier = modifier.wrapContentHeight(), - properties = DialogProperties(usePlatformDefaultWidth = false) + properties = DialogProperties(usePlatformDefaultWidth = false), ) { Surface( modifier = modifier @@ -83,15 +83,14 @@ fun DatePickerDialog( Box( modifier = Modifier .align(Alignment.End) - .padding(_dialogButtonsPadding) + .padding(_dialogButtonsPadding), ) { - AlertDialogFlowRow( mainAxisSpacing = _dialogButtonsMainAxisSpacing, - crossAxisSpacing = _dialogButtonsCrossAxisSpacing + crossAxisSpacing = _dialogButtonsCrossAxisSpacing, ) { TextButton( - onClick = onDismiss + onClick = onDismiss, ) { Text(text = dismissLabel) } @@ -100,16 +99,17 @@ fun DatePickerDialog( val millis = pickerState.selectedDateMillis ?: return@TextButton val date = LocalDateTime.ofInstant( - Instant.ofEpochMilli(millis), ZoneId.systemDefault() + Instant.ofEpochMilli(millis), + ZoneId.systemDefault(), ) onConfirm( localDateTime .withYear(date.year) .withMonth(date.monthValue) - .withDayOfMonth(date.dayOfMonth) + .withDayOfMonth(date.dayOfMonth), ) - } + }, ) { Text(text = confirmLabel) } @@ -125,7 +125,7 @@ fun DatePickerDialog( private fun AlertDialogFlowRow( mainAxisSpacing: Dp, crossAxisSpacing: Dp, - content: @Composable () -> Unit + content: @Composable () -> Unit, ) { Layout(content) { measurables, constraints -> val sequences = mutableListOf>() @@ -142,7 +142,7 @@ private fun AlertDialogFlowRow( // Return whether the placeable can be added to the current sequence. fun canAddToCurrentSequence(placeable: Placeable) = currentSequence.isEmpty() || currentMainAxisSize + mainAxisSpacing.roundToPx() + - placeable.width <= constraints.maxWidth + placeable.width <= constraints.maxWidth // Store current sequence information and start a new sequence. fun startNewSequence() { @@ -187,20 +187,22 @@ private fun AlertDialogFlowRow( sequences.forEachIndexed { i, placeables -> val childrenMainAxisSizes = IntArray(placeables.size) { j -> placeables[j].width + - if (j < placeables.lastIndex) mainAxisSpacing.roundToPx() else 0 + if (j < placeables.lastIndex) mainAxisSpacing.roundToPx() else 0 } val arrangement = Arrangement.End val mainAxisPositions = IntArray(childrenMainAxisSizes.size) { 0 } with(arrangement) { arrange( - mainAxisLayoutSize, childrenMainAxisSizes, - layoutDirection, mainAxisPositions + mainAxisLayoutSize, + childrenMainAxisSizes, + layoutDirection, + mainAxisPositions, ) } placeables.forEachIndexed { j, placeable -> placeable.place( x = mainAxisPositions[j], - y = crossAxisPositions[i] + y = crossAxisPositions[i], ) } } @@ -210,4 +212,4 @@ private fun AlertDialogFlowRow( private val _dialogButtonsPadding by lazy { PaddingValues(bottom = 8.dp, end = 6.dp) } private val _dialogButtonsMainAxisSpacing by lazy { 8.dp } -private val _dialogButtonsCrossAxisSpacing by lazy { 12.dp } \ No newline at end of file +private val _dialogButtonsCrossAxisSpacing by lazy { 12.dp } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/datetimepicker/TimePickerDialog.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/datetimepicker/TimePickerDialog.kt index 0a5c89b2..97e80ae5 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/datetimepicker/TimePickerDialog.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.datetimepicker +package app.myzel394.numberhub.core.ui.common.datetimepicker import android.text.format.DateFormat import androidx.compose.foundation.background @@ -59,7 +59,7 @@ import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.zIndex -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R // https://cs.android.com/androidx/platform/tools/dokka-devsite-plugin/+/master:testData/compose/samples/material3/samples/TimePickerSamples.kt @Composable @@ -73,7 +73,7 @@ fun TimePickerDialog( val pickerState = rememberTimePickerState( initialHour = hour, initialMinute = minute, - is24Hour = DateFormat.is24HourFormat(LocalContext.current) + is24Hour = DateFormat.is24HourFormat(LocalContext.current), ) val configuration = LocalConfiguration.current var showingPicker by rememberSaveable { mutableStateOf(true) } @@ -81,8 +81,8 @@ fun TimePickerDialog( BasicAlertDialog( onDismissRequest = onCancel, properties = DialogProperties( - usePlatformDefaultWidth = false - ) + usePlatformDefaultWidth = false, + ), ) { Surface( shape = MaterialTheme.shapes.extraLarge, @@ -92,7 +92,7 @@ fun TimePickerDialog( .height(IntrinsicSize.Min) .background( shape = MaterialTheme.shapes.extraLarge, - color = MaterialTheme.colorScheme.surface + color = MaterialTheme.colorScheme.surface, ), ) { if (configuration.screenHeightDp > 400) { @@ -103,7 +103,7 @@ fun TimePickerDialog( .fillMaxSize() .semantics { isTraversalGroup = true - } + }, ) { IconButton( modifier = Modifier @@ -114,7 +114,8 @@ fun TimePickerDialog( .size(64.dp, 72.dp) .align(Alignment.BottomStart) .zIndex(5f), - onClick = { showingPicker = !showingPicker }) { + onClick = { showingPicker = !showingPicker }, + ) { val icon = if (showingPicker) { Icons.Outlined.Keyboard } else { @@ -122,21 +123,21 @@ fun TimePickerDialog( } Icon( imageVector = icon, - contentDescription = stringResource(R.string.select_time_label) + contentDescription = stringResource(R.string.select_time_label), ) } } } Column( modifier = Modifier.padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Text( modifier = Modifier .fillMaxWidth() .padding(bottom = 20.dp), text = stringResource(R.string.select_time_label), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) if (showingPicker && configuration.screenHeightDp > 400) { TimePicker(state = pickerState) @@ -146,14 +147,14 @@ fun TimePickerDialog( Row( modifier = Modifier .height(40.dp) - .fillMaxWidth() + .fillMaxWidth(), ) { Spacer(modifier = Modifier.weight(1f)) TextButton( - onClick = onCancel + onClick = onCancel, ) { Text(stringResource(R.string.cancel_label)) } TextButton( - onClick = { onConfirm(pickerState.hour, pickerState.minute) } + onClick = { onConfirm(pickerState.hour, pickerState.minute) }, ) { Text(confirmLabel) } } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/IconPack.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/IconPack.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/IconPack.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/IconPack.kt index f43152ca..19c04669 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/IconPack.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/IconPack.kt @@ -16,6 +16,6 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons +package app.myzel394.numberhub.core.ui.common.icons object IconPack diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArCos.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArCos.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArCos.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArCos.kt index 8939296f..2ca8090c 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArCos.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArCos.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.ArCos: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArSin.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArSin.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArSin.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArSin.kt index e599f6da..f3d2cf20 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArSin.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArSin.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.ArSin: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArTan.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArTan.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArTan.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArTan.kt index d34b78d9..ae6202b1 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/ArTan.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/ArTan.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.AcTan: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Backspace.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Backspace.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Backspace.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Backspace.kt index 06316c39..5874e372 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Backspace.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Backspace.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Backspace: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Brackets.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Brackets.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Brackets.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Brackets.kt index 04fed675..a6050f6a 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Brackets.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Brackets.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Brackets: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Clear.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Clear.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Clear.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Clear.kt index 0ed708d8..31d26e1f 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Clear.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Clear.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Clear: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Comma.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Comma.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Comma.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Comma.kt index a233910e..292ea06a 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Comma.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Comma.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Comma: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Cos.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Cos.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Cos.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Cos.kt index 69bccf7c..0789581d 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Cos.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Cos.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Cos: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Deg.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Deg.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Deg.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Deg.kt index dea1f07d..cdcb35e6 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Deg.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Deg.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Deg: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Divide.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Divide.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Divide.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Divide.kt index 26862199..e023c3bc 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Divide.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Divide.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Divide: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Dot.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Dot.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Dot.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Dot.kt index f38bd6e7..225dd631 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Dot.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Dot.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Dot: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Equal.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Equal.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Equal.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Equal.kt index fa0b216c..d2bf463f 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Equal.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Equal.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Equal: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Euler.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Euler.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Euler.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Euler.kt index 8eacdd48..1883218a 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Euler.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Euler.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Euler: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Ex.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Ex.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Ex.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Ex.kt index 72a33a71..248c586c 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Ex.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Ex.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Ex: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Factorial.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Factorial.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Factorial.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Factorial.kt index b7d708f0..3fd84a43 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Factorial.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Factorial.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Factorial: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Inv.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Inv.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Inv.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Inv.kt index fa2029ed..6b0ebe30 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Inv.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Inv.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Inv: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key0.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key0.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key0.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key0.kt index 90af3061..7f937a32 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key0.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key0.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key0: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key1.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key1.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key1.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key1.kt index 1fd52e39..37630e0c 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key1.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key1.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key1: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key2.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key2.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key2.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key2.kt index 6e915ede..dc9bc721 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key2.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key2.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key2: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key3.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key3.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key3.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key3.kt index 5962764e..9100eb54 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key3.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key3.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key3: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key4.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key4.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key4.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key4.kt index 1ff3ee8f..15036441 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key4.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key4.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key4: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key5.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key5.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key5.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key5.kt index 19fa45ff..db3be59b 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key5.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key5.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key5: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key6.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key6.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key6.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key6.kt index 70eb77ed..db7b517c 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key6.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key6.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key6: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key7.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key7.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key7.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key7.kt index 785801b9..c7fb38e2 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key7.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key7.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key7: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key8.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key8.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key8.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key8.kt index 7bef566b..7affa6a5 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key8.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key8.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key8: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key9.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key9.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key9.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key9.kt index 39d7e717..fd37f01d 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Key9.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Key9.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Key9: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyA.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyA.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyA.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyA.kt index 97e03820..9b36a1a5 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyA.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyA.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.KeyA: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyB.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyB.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyB.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyB.kt index 4cccb0e3..22d3b837 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyB.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyB.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.KeyB: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyC.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyC.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyC.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyC.kt index 6f1cd0e5..1bb4be0b 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyC.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyC.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.KeyC: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyD.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyD.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyD.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyD.kt index 3c40989f..a48377c2 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyD.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyD.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.KeyD: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyE.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyE.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyE.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyE.kt index 3b7bc1d6..65d259d4 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyE.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyE.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.KeyE: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyF.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyF.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyF.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyF.kt index e7c16c90..6e014f24 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/KeyF.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/KeyF.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.KeyF: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/LeftBracket.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/LeftBracket.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/LeftBracket.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/LeftBracket.kt index 10ee2d38..ff64bccc 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/LeftBracket.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/LeftBracket.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.LeftBracket: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Ln.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Ln.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Ln.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Ln.kt index 02e82940..8ddb02db 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Ln.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Ln.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Ln: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Log.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Log.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Log.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Log.kt index 25002cf2..49d7d0e7 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Log.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Log.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Log: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Minus.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Minus.kt similarity index 92% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Minus.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Minus.kt index 46902090..a6278314 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Minus.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Minus.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Minus: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Modulo.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Modulo.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Modulo.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Modulo.kt index 58609d95..83efc8c8 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Modulo.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Modulo.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Modulo: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Multiply.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Multiply.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Multiply.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Multiply.kt index b43aee08..287f60db 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Multiply.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Multiply.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Multiply: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Percent.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Percent.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Percent.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Percent.kt index 6be0bc7b..d2d03fbb 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Percent.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Percent.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Percent: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Pi.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Pi.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Pi.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Pi.kt index 52c37011..73af4728 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Pi.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Pi.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Pi: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Plus.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Plus.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Plus.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Plus.kt index af173873..dd028fb3 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Plus.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Plus.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Plus: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Power.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Power.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Power.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Power.kt index 2200e939..c2d2f55f 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Power.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Power.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Power: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Power10.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Power10.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Power10.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Power10.kt index 987c0f27..f2224ba5 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Power10.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Power10.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Power10: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Rad.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Rad.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Rad.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Rad.kt index 93295d95..d33ea713 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Rad.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Rad.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Rad: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/RightBracket.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/RightBracket.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/RightBracket.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/RightBracket.kt index 621da869..24e9c071 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/RightBracket.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/RightBracket.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.RightBracket: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Root.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Root.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Root.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Root.kt index ff91fb88..e86bded0 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Root.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Root.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Root: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Sin.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Sin.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Sin.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Sin.kt index 702d8118..9aba0af8 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Sin.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Sin.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Sin: ImageVector diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Tan.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Tan.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Tan.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Tan.kt index 9c19cd11..a9431b61 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Tan.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/icons/iconpack/Tan.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.icons.iconpack +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.core.ui.common.icons.iconpack import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathFillType.Companion.NonZero @@ -27,7 +29,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector.Builder import androidx.compose.ui.graphics.vector.path import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.IconPack @Suppress("UnusedReceiverParameter") val IconPack.Tan: ImageVector diff --git a/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/ClipboardManagerExt.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/ClipboardManagerExt.kt new file mode 100644 index 00000000..49d065d1 --- /dev/null +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/ClipboardManagerExt.kt @@ -0,0 +1,64 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.core.ui.common.textfield + +import android.content.ClipData +import androidx.compose.ui.platform.ClipboardManager +import androidx.compose.ui.text.AnnotatedString +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token + +/** + * Unformatted values are expected. Basically what BigDecimal and Expression parser use. + * + * @property formatterSymbols Current [FormatterSymbols]. + * @property clipboardManager [android.content.ClipboardManager] provided by system. + */ +internal class ExpressionClipboardManager( + private val formatterSymbols: FormatterSymbols, + private val clipboardManager: android.content.ClipboardManager, +) : ClipboardManager { + override fun setText(annotatedString: AnnotatedString) = clipboardManager.setPrimaryClip( + ClipData.newPlainText( + PLAIN_TEXT_LABEL, + annotatedString + .text + .replace(Token.Digit.dot, formatterSymbols.fractional), + ), + ) + + override fun getText(): AnnotatedString? = clipboardManager.primaryClip?.let { primaryClip -> + if (primaryClip.itemCount > 0) { + val clipText = primaryClip.getItemAt(0)?.text ?: return@let null + + clipText + .toString() + .toAnnotatedString() + } else { + null + } + } + + override fun hasText() = + clipboardManager.primaryClipDescription?.hasMimeType("text/*") ?: false +} + +internal const val PLAIN_TEXT_LABEL = "plain text" + +private fun CharSequence.toAnnotatedString(): AnnotatedString = AnnotatedString(this.toString()) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/CursorFixer.kt similarity index 86% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/CursorFixer.kt index 5726deed..c1d32414 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/CursorFixer.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/CursorFixer.kt @@ -16,13 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield +package app.myzel394.numberhub.core.ui.common.textfield -import com.sadellie.unitto.core.base.Token +import app.myzel394.numberhub.core.base.Token import kotlin.math.abs fun String.fixCursor(pos: Int, grouping: String): Int { - if (isEmpty()) return pos // Best position if we move cursor left @@ -75,7 +74,7 @@ private fun Int.isAtToken(str: String, token: String): Boolean { return str .substring( startIndex = (this - checkBound).coerceAtLeast(0), - endIndex = (this + checkBound).coerceAtMost(str.length) + endIndex = (this + checkBound).coerceAtMost(str.length), ) .contains(token) } @@ -86,7 +85,6 @@ private fun Int.isAfterToken(str: String, token: String): Boolean { .contains(token) } - // This can also make [TextFieldValue.addTokens] better by checking tokens both ways. Needs more tests fun String.tokenAfter(pos: Int): String { Token.Func.allWithOpeningBracket.forEach { @@ -96,23 +94,6 @@ fun String.tokenAfter(pos: Int): String { return substring(pos, (pos + 1).coerceAtMost(this.length)) } -//private fun String.numberNearby(cursor: Int): String { -// val text = this -// -// var aheadCursor = cursor -// var afterCursor = cursor -// -// while (text.tokenAhead(aheadCursor) in Token.Digit.allWithDot) { -// aheadCursor-- -// } -// -// while (text.tokenAfter(afterCursor) in Token.Digit.allWithDot) { -// afterCursor++ -// } -// -// return text.substring(aheadCursor, afterCursor) -//} - private fun Int.isBeforeToken(str: String, token: String): Boolean { return str .substring(this, (this + token.length).coerceAtMost(str.length)) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/ExpressionTransformer.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/ExpressionTransformer.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/ExpressionTransformer.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/ExpressionTransformer.kt index ea9fa187..fa9e95a7 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/ExpressionTransformer.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/ExpressionTransformer.kt @@ -16,12 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield +package app.myzel394.numberhub.core.ui.common.textfield import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.input.OffsetMapping import androidx.compose.ui.text.input.TransformedText import androidx.compose.ui.text.input.VisualTransformation +import app.myzel394.numberhub.core.base.FormatterSymbols class ExpressionTransformer(private val formatterSymbols: FormatterSymbols) : VisualTransformation { @@ -29,13 +30,13 @@ class ExpressionTransformer(private val formatterSymbols: FormatterSymbols) : Vi val formatted = text.text.formatExpression(formatterSymbols) return TransformedText( text = AnnotatedString(formatted), - offsetMapping = ExpressionMapping(text.text, formatted) + offsetMapping = ExpressionMapping(text.text, formatted), ) } inner class ExpressionMapping( private val original: String, - private val transformed: String + private val transformed: String, ) : OffsetMapping { // Called when entering text (on each text change) // Basically moves cursor to the right position diff --git a/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/FixedInputTextFIeld.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/FixedInputTextFIeld.kt new file mode 100644 index 00000000..ec1209c2 --- /dev/null +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/FixedInputTextFIeld.kt @@ -0,0 +1,88 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.core.ui.common.textfield + +import android.content.ClipData +import android.content.Context +import androidx.compose.foundation.clickable +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.ClipboardManager +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.style.TextAlign +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.ui.theme.LocalNumberTypography + +@Composable +fun FixedExpressionInputTextField( + modifier: Modifier = Modifier, + value: String, + formatterSymbols: FormatterSymbols, + textColor: Color, + onClick: () -> Unit, +) { + val clipboardManager = FormattedExpressionClipboardManager( + formatterSymbols = formatterSymbols, + clipboardManager = LocalContext.current.getSystemService(Context.CLIPBOARD_SERVICE) + as android.content.ClipboardManager, + ) + + CompositionLocalProvider(LocalClipboardManager provides clipboardManager) { + SelectionContainer( + modifier = Modifier + .horizontalScroll(rememberScrollState()) // Must be first + .clickable(onClick = onClick) + .then(modifier), + ) { + Text( + modifier = Modifier.fillMaxWidth(), + text = value.formatExpression(formatterSymbols), + style = LocalNumberTypography.current.displaySmall + .copy(color = textColor, textAlign = TextAlign.End), + ) + } + } +} + +private class FormattedExpressionClipboardManager( + private val formatterSymbols: FormatterSymbols, + private val clipboardManager: android.content.ClipboardManager, +) : ClipboardManager { + override fun getText(): AnnotatedString? = null + + override fun setText(annotatedString: AnnotatedString) { + clipboardManager.setPrimaryClip( + ClipData.newPlainText( + PLAIN_TEXT_LABEL, + annotatedString + .text + .replace(formatterSymbols.grouping, ""), + ), + ) + } +} diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FormatterExtensions.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/FormatterExtensions.kt similarity index 94% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FormatterExtensions.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/FormatterExtensions.kt index 75bd31ef..4b721ea0 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FormatterExtensions.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/FormatterExtensions.kt @@ -16,9 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield +package app.myzel394.numberhub.core.ui.common.textfield -import com.sadellie.unitto.core.base.Token +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token private val numbersRegex by lazy { Regex("[\\d.]+") } @@ -50,7 +51,7 @@ internal fun String.clearAndFilterNumberBase(): String { } fun String.formatExpression( - formatterSymbols: FormatterSymbols + formatterSymbols: FormatterSymbols, ): String { var input = this @@ -83,7 +84,7 @@ fun String.formatExpression( } private fun String.formatNumber( - formatterSymbols: FormatterSymbols + formatterSymbols: FormatterSymbols, ): String { val input = this @@ -113,7 +114,7 @@ private fun String.leaveLegalTokensOnly(legalTokens: List): String { val subs = streamOfTokens .substring( cursor, - (cursor + token.length).coerceAtMost(streamOfTokens.length) + (cursor + token.length).coerceAtMost(streamOfTokens.length), ) if (subs == token) { // Got a digit, see if there are other digits coming after diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/InputTextField.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/InputTextField.kt similarity index 59% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/InputTextField.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/InputTextField.kt index bb7e02e9..559335cc 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/InputTextField.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/InputTextField.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield +package app.myzel394.numberhub.core.ui.common.textfield -import androidx.compose.foundation.clickable +import android.content.Context import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.text.BasicTextField @@ -32,132 +32,106 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Rect import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalTextInputService -import androidx.compose.ui.platform.LocalTextToolbar -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.platform.TextToolbar import androidx.compose.ui.text.TextLayoutResult -import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.TextUnit -import com.sadellie.unitto.core.ui.common.autosize.AutoSizeTextStyleBox -import com.sadellie.unitto.core.ui.common.textfield.texttoolbar.UnittoTextToolbar -import com.sadellie.unitto.core.ui.theme.LocalNumberTypography +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.ui.common.autosize.AutoSizeTextStyleBox +import app.myzel394.numberhub.core.ui.theme.LocalNumberTypography @Composable fun ExpressionTextField( modifier: Modifier, value: TextFieldValue, minRatio: Float = 1f, - cutCallback: () -> Unit = {}, - pasteCallback: (String) -> Unit = {}, - onCursorChange: (TextRange) -> Unit, + onValueChange: (TextFieldValue) -> Unit, textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, formatterSymbols: FormatterSymbols, readOnly: Boolean = false, placeholder: String = "", ) { - val localView = LocalView.current - val clipboardManager = LocalClipboardManager.current - val expressionTransformer = remember(formatterSymbols) { ExpressionTransformer(formatterSymbols) } - - fun copyCallback() { - clipboardManager.copyWithFractional(value, formatterSymbols) - onCursorChange(TextRange(value.selection.end)) + val context = LocalContext.current + val clipboardManager = remember(formatterSymbols) { + ExpressionClipboardManager( + formatterSymbols = formatterSymbols, + clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) + as android.content.ClipboardManager, + ) + } + val expressionTransformer = remember(formatterSymbols) { + ExpressionTransformer(formatterSymbols) } - val textToolbar: UnittoTextToolbar = if (readOnly) { - UnittoTextToolbar( - view = localView, - copyCallback = ::copyCallback, - ) - } else { - UnittoTextToolbar( - view = localView, - copyCallback = ::copyCallback, - pasteCallback = { - pasteCallback(clipboardManager.getText()?.text?.clearAndFilterExpression(formatterSymbols) ?: "") + CompositionLocalProvider( + LocalClipboardManager provides clipboardManager, + ) { + AutoSizeTextField( + modifier = modifier, + value = value, + onValueChange = { + onValueChange(it.copy(text = it.text.clearAndFilterExpression(formatterSymbols))) }, - cutCallback = { - clipboardManager.copyWithFractional(value, formatterSymbols) - cutCallback() - } + placeholder = placeholder, + readOnly = readOnly, + textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), + visualTransformation = expressionTransformer, + cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), + minRatio = minRatio, ) } - - AutoSizeTextField( - modifier = modifier, - value = value, - onValueChange = { onCursorChange(it.selection) }, - placeholder = placeholder, - textToolbar = textToolbar, - readOnly = readOnly, - textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), - visualTransformation = expressionTransformer, - cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), - minRatio = minRatio - ) } @Composable -fun UnformattedTextField( +fun NumberBaseTextField( modifier: Modifier, value: TextFieldValue, minRatio: Float = 1f, - cutCallback: () -> Unit = {}, - pasteCallback: (String) -> Unit = {}, - onCursorChange: (TextRange) -> Unit, + onValueChange: (TextFieldValue) -> Unit, textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, readOnly: Boolean = false, placeholder: String = "", ) { - val localView = LocalView.current - val clipboardManager = LocalClipboardManager.current - fun copyCallback() { - clipboardManager.copy(value) - onCursorChange(TextRange(value.selection.end)) - } - - val textToolbar: UnittoTextToolbar = remember(readOnly) { - if (readOnly) { - UnittoTextToolbar( - view = localView, - copyCallback = ::copyCallback, - ) - } else { - UnittoTextToolbar( - view = localView, - copyCallback = ::copyCallback, - pasteCallback = { - pasteCallback(clipboardManager.getText()?.text?.clearAndFilterNumberBase() ?: "") - }, - cutCallback = { - clipboardManager.copy(value) - cutCallback() - } - ) - } - } - AutoSizeTextField( modifier = modifier, value = value, - onValueChange = { onCursorChange(it.selection) }, + onValueChange = { + onValueChange(it.copy(text = it.text.clearAndFilterNumberBase())) + }, placeholder = placeholder, - textToolbar = textToolbar, readOnly = readOnly, - textStyle = LocalNumberTypography.current.displayLarge.copy(color = textColor), + textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), + cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), + minRatio = minRatio, + ) +} + +@Composable +fun SimpleTextField( + modifier: Modifier, + value: TextFieldValue, + minRatio: Float = 1f, + onValueChange: (TextFieldValue) -> Unit, + textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, + readOnly: Boolean = false, + placeholder: String = "", +) { + AutoSizeTextField( + modifier = modifier, + value = value, + onValueChange = onValueChange, + placeholder = placeholder, + readOnly = readOnly, + textStyle = LocalNumberTypography.current.displayLarge.copy(textColor), + cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant), minRatio = minRatio, ) } @@ -166,7 +140,6 @@ fun UnformattedTextField( * Based on: https://gist.github.com/inidamleader/b594d35362ebcf3cedf81055df519300 * * @param placeholder Placeholder text, shown when [value] is empty. - * @param textToolbar [TextToolbar] with modified actions in menu. * @param alignment The alignment of the text within its container. * @see [BasicTextField] * @see [AutoSizeTextStyleBox] @@ -177,7 +150,6 @@ private fun AutoSizeTextField( value: TextFieldValue, onValueChange: (TextFieldValue) -> Unit, placeholder: String? = null, - textToolbar: TextToolbar = LocalTextToolbar.current, enabled: Boolean = true, readOnly: Boolean = false, textStyle: TextStyle = TextStyle.Default, @@ -202,32 +174,18 @@ private fun AutoSizeTextField( softWrap = false, style = textStyle, minRatio = minRatio, - alignment = alignment + alignment = alignment, ) { CompositionLocalProvider( LocalTextInputService provides null, - LocalTextToolbar provides textToolbar ) { - val currentTextToolbar = LocalTextToolbar.current val style = LocalTextStyle.current - val focusRequester = remember { FocusRequester() } BasicTextField( value = value, onValueChange = onValueChange, modifier = Modifier - .fillMaxWidth() - .focusRequester(focusRequester) - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, - onClick = { - currentTextToolbar.hide() - focusRequester.requestFocus() - onValueChange(value.copy(selection = TextRange.Zero)) - currentTextToolbar.showMenu(Rect(Offset.Zero, 0f)) - } - ), + .fillMaxWidth(), enabled = enabled, readOnly = readOnly, textStyle = style, @@ -246,8 +204,8 @@ private fun AutoSizeTextField( text = placeholder!!, style = style.copy( textAlign = TextAlign.End, - color = MaterialTheme.colorScheme.onSurface.copy(0.5f) - ) + color = MaterialTheme.colorScheme.onSurface.copy(0.5f), + ), ) } innerTextField() diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/OutlinedDecimalTextField.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/OutlinedDecimalTextField.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/OutlinedDecimalTextField.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/OutlinedDecimalTextField.kt index 30c7a4d5..9cb306af 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/OutlinedDecimalTextField.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/OutlinedDecimalTextField.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield +package app.myzel394.numberhub.core.ui.common.textfield import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.scaleIn @@ -62,8 +62,8 @@ fun OutlinedDecimalTextField( visualTransformation = expressionFormatter, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Decimal, - imeAction = imeAction + imeAction = imeAction, ), - colors = colors + colors = colors, ) } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/TextFieldValueExtensions.kt similarity index 93% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/TextFieldValueExtensions.kt index ae5248e6..c0cd0749 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/TextFieldValueExtensions.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/TextFieldValueExtensions.kt @@ -16,12 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield +package app.myzel394.numberhub.core.ui.common.textfield import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.SavedStateHandle -import com.sadellie.unitto.core.base.Token +import app.myzel394.numberhub.core.base.Token fun TextFieldValue.addTokens(tokens: String): TextFieldValue { val ahead by lazy { text.tokenAhead(selection.start) } @@ -30,7 +30,8 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue { Token.Operator.plus, Token.Operator.multiply, Token.Operator.divide, - Token.Operator.power -> { + Token.Operator.power, + -> { if (ahead == Token.Operator.plus) return deleteAheadAndAdd(tokens) if (ahead == Token.Operator.minus) return deleteAheadAndAdd(tokens) if (ahead == Token.Operator.multiply) return deleteAheadAndAdd(tokens) @@ -50,7 +51,7 @@ fun TextFieldValue.addTokens(tokens: String): TextFieldValue { return this.copy( text = text.replaceRange(selection.start, selection.end, tokens), - selection = TextRange(selection.start + tokens.length) + selection = TextRange(selection.start + tokens.length), ) } @@ -93,7 +94,7 @@ fun TextFieldValue.addBracket(): TextFieldValue { Token.Operator.plus, Token.Operator.minus, Token.Operator.power, - Token.Operator.leftBracket + Token.Operator.leftBracket, ) if (text.tokenAhead(selection.start) in operators2) { return addTokens(Token.Operator.leftBracket) @@ -122,10 +123,12 @@ fun TextFieldValue.deleteTokens(): TextFieldValue { return this.copy( text = newText, - selection = TextRange((newText.length - distanceFromEnd).coerceAtLeast(0)) + selection = TextRange((newText.length - distanceFromEnd).coerceAtLeast(0)), ) } +fun TextFieldValue.placeCursorAtTheEnd(): TextFieldValue = copy(selection = TextRange(text.length)) + /** * Tries to get a [TextFieldValue]. Places cursor at the end. * diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/FloatingTextActionModeCallback.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/FloatingTextActionModeCallback.kt similarity index 90% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/FloatingTextActionModeCallback.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/FloatingTextActionModeCallback.kt index 90a5f2e0..c83eb8f0 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/FloatingTextActionModeCallback.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/FloatingTextActionModeCallback.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield.texttoolbar +package app.myzel394.numberhub.core.ui.common.textfield.texttoolbar import android.os.Build import android.view.ActionMode @@ -27,7 +27,7 @@ import androidx.annotation.RequiresApi @RequiresApi(Build.VERSION_CODES.M) internal class FloatingTextActionModeCallback( - private val callback: UnittoActionModeCallback + private val callback: UnittoActionModeCallback, ) : ActionMode.Callback2() { override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return callback.onActionItemClicked(mode, item) @@ -48,14 +48,14 @@ internal class FloatingTextActionModeCallback( override fun onGetContentRect( mode: ActionMode?, view: View?, - outRect: android.graphics.Rect? + outRect: android.graphics.Rect?, ) { val rect = callback.rect outRect?.set( rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), - rect.bottom.toInt() + rect.bottom.toInt(), ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoActionModeCallback.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoActionModeCallback.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoActionModeCallback.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoActionModeCallback.kt index efa4681b..6c8c15e2 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoActionModeCallback.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoActionModeCallback.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield.texttoolbar +package app.myzel394.numberhub.core.ui.common.textfield.texttoolbar import android.view.ActionMode import android.view.Menu @@ -33,7 +33,7 @@ internal class UnittoActionModeCallback( var onCopyRequested: (() -> Unit)? = null, var onPasteRequested: (() -> Unit)? = null, var onCutRequested: (() -> Unit)? = null, - var onSelectAllRequested: (() -> Unit)? = null + var onSelectAllRequested: (() -> Unit)? = null, ) { fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { requireNotNull(menu) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoPrimaryTextActionModeCallback.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoPrimaryTextActionModeCallback.kt similarity index 92% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoPrimaryTextActionModeCallback.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoPrimaryTextActionModeCallback.kt index 6bdd1c31..a969a491 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoPrimaryTextActionModeCallback.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoPrimaryTextActionModeCallback.kt @@ -16,14 +16,14 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield.texttoolbar +package app.myzel394.numberhub.core.ui.common.textfield.texttoolbar import android.view.ActionMode import android.view.Menu import android.view.MenuItem internal class UnittoPrimaryTextActionModeCallback( - private val callback: UnittoActionModeCallback + private val callback: UnittoActionModeCallback, ) : ActionMode.Callback { override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return callback.onActionItemClicked(mode, item) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoTextToolbar.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoTextToolbar.kt similarity index 90% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoTextToolbar.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoTextToolbar.kt index d66fc7b1..9383ef5e 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/texttoolbar/UnittoTextToolbar.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/common/textfield/texttoolbar/UnittoTextToolbar.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common.textfield.texttoolbar +package app.myzel394.numberhub.core.ui.common.textfield.texttoolbar import android.os.Build import android.view.ActionMode @@ -29,7 +29,7 @@ class UnittoTextToolbar( private val view: View, private val copyCallback: () -> Unit, private val pasteCallback: (() -> Unit)? = null, - private val cutCallback: (() -> Unit)? = null + private val cutCallback: (() -> Unit)? = null, ) : TextToolbar { private var actionMode: ActionMode? = null @@ -42,7 +42,7 @@ class UnittoTextToolbar( onCopyRequested: (() -> Unit)?, onPasteRequested: (() -> Unit)?, onCutRequested: (() -> Unit)?, - onSelectAllRequested: (() -> Unit)? + onSelectAllRequested: (() -> Unit)?, ) { textActionModeCallback.rect = rect textActionModeCallback.onCopyRequested = copyCallback @@ -66,17 +66,17 @@ class UnittoTextToolbar( private fun startActionMode( view: View, - textActionModeCallback: UnittoActionModeCallback + textActionModeCallback: UnittoActionModeCallback, ): ActionMode { return if (Build.VERSION.SDK_INT >= 23) { view.startActionMode( FloatingTextActionModeCallback(textActionModeCallback), - ActionMode.TYPE_FLOATING + ActionMode.TYPE_FLOATING, ) } else { // Old devices use toolbar instead of a floating menu view.startActionMode( - UnittoPrimaryTextActionModeCallback(textActionModeCallback) + UnittoPrimaryTextActionModeCallback(textActionModeCallback), ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/datetime/UnittoDateTimeFormatter.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/datetime/UnittoDateTimeFormatter.kt similarity index 97% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/datetime/UnittoDateTimeFormatter.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/datetime/UnittoDateTimeFormatter.kt index fea1e1c1..8003f5d4 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/datetime/UnittoDateTimeFormatter.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/datetime/UnittoDateTimeFormatter.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.datetime +package app.myzel394.numberhub.core.ui.datetime import java.time.format.DateTimeFormatter import java.util.Locale diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/datetime/ZonedDateTimeUtils.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/datetime/ZonedDateTimeUtils.kt similarity index 96% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/datetime/ZonedDateTimeUtils.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/datetime/ZonedDateTimeUtils.kt index 9800dbc2..157ab6f3 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/datetime/ZonedDateTimeUtils.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/datetime/ZonedDateTimeUtils.kt @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.datetime +package app.myzel394.numberhub.core.ui.datetime import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R import java.time.LocalDate import java.time.ZonedDateTime import java.time.temporal.ChronoUnit @@ -83,10 +83,11 @@ fun ZonedDateTime.formatTimeHours( locale: Locale, is24Hour: Boolean, ): String = - if (is24Hour) + if (is24Hour) { format(UnittoDateTimeFormatter.time24Hours(locale)) - else + } else { format(UnittoDateTimeFormatter.time12Hours(locale)) + } /** * @see UnittoDateTimeFormatter.timeMinutes @@ -132,7 +133,7 @@ fun ZonedDateTime.formatDateDayMonthYear( * @see UnittoDateTimeFormatter.dateWeekDayMonthYear */ fun LocalDate.formatDateWeekDayMonthYear( - locale: Locale + locale: Locale, ): String = format(UnittoDateTimeFormatter.dateWeekDayMonthYear(locale)) @@ -155,7 +156,6 @@ fun LocalDate.formatDateWeekDayMonthYear( fun ZonedDateTime.formatOffset( currentTime: ZonedDateTime, ): String? { - val offsetFixed = ChronoUnit.SECONDS.between(currentTime, this) var resultBuffer = "" diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/model/DrawerItem.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/model/DrawerItem.kt similarity index 83% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/model/DrawerItem.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/model/DrawerItem.kt index 831eba37..7decbc2a 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/model/DrawerItem.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/model/DrawerItem.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.model +package app.myzel394.numberhub.core.ui.model import android.os.Build import androidx.annotation.StringRes @@ -34,8 +34,8 @@ import androidx.compose.material.icons.outlined.Schedule import androidx.compose.material.icons.outlined.Settings import androidx.compose.material.icons.outlined.SwapHoriz import androidx.compose.ui.graphics.vector.ImageVector -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.TopLevelDestinations +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.TopLevelDestinations sealed class DrawerItem( val graph: String, @@ -43,7 +43,7 @@ sealed class DrawerItem( @StringRes val name: Int, val shortcut: Shortcut?, val selectedIcon: ImageVector, - val defaultIcon: ImageVector + val defaultIcon: ImageVector, ) { data object Calculator : DrawerItem( graph = TopLevelDestinations.CALCULATOR_GRAPH, @@ -52,10 +52,10 @@ sealed class DrawerItem( shortcut = Shortcut( R.string.calculator_title, R.string.calculator_title, - R.drawable.ic_shortcut_calculator + R.drawable.ic_shortcut_calculator, ), selectedIcon = Icons.Filled.Calculate, - defaultIcon = Icons.Outlined.Calculate + defaultIcon = Icons.Outlined.Calculate, ) data object Converter : DrawerItem( @@ -65,10 +65,10 @@ sealed class DrawerItem( shortcut = Shortcut( R.string.unit_converter_title, R.string.unit_converter_title, - R.drawable.ic_shortcut_unit_converter + R.drawable.ic_shortcut_unit_converter, ), selectedIcon = Icons.Filled.SwapHoriz, - defaultIcon = Icons.Outlined.SwapHoriz + defaultIcon = Icons.Outlined.SwapHoriz, ) data object DateCalculator : DrawerItem( @@ -78,10 +78,10 @@ sealed class DrawerItem( shortcut = Shortcut( R.string.date_calculator_title, R.string.date_calculator_title, - R.drawable.ic_shortcut_date_calculator + R.drawable.ic_shortcut_date_calculator, ), selectedIcon = Icons.Filled.Event, - defaultIcon = Icons.Outlined.Event + defaultIcon = Icons.Outlined.Event, ) data object TimeZones : DrawerItem( @@ -91,10 +91,10 @@ sealed class DrawerItem( shortcut = Shortcut( R.string.time_zone_title, R.string.time_zone_title, - R.drawable.ic_shortcut_time_zone + R.drawable.ic_shortcut_time_zone, ), selectedIcon = Icons.Filled.Schedule, - defaultIcon = Icons.Outlined.Schedule + defaultIcon = Icons.Outlined.Schedule, ) data object BodyMass : DrawerItem( @@ -104,10 +104,10 @@ sealed class DrawerItem( shortcut = Shortcut( R.string.body_mass_title, R.string.body_mass_title, - R.drawable.ic_shortcut_body_mass + R.drawable.ic_shortcut_body_mass, ), selectedIcon = Icons.Filled.AccessibilityNew, - defaultIcon = Icons.Outlined.AccessibilityNew + defaultIcon = Icons.Outlined.AccessibilityNew, ) data object Settings : DrawerItem( @@ -116,7 +116,7 @@ sealed class DrawerItem( name = R.string.settings_title, shortcut = null, selectedIcon = Icons.Filled.Settings, - defaultIcon = Icons.Outlined.Settings + defaultIcon = Icons.Outlined.Settings, ) companion object { @@ -139,7 +139,9 @@ sealed class DrawerItem( all } + val additional = listOf(Settings) + // Only routes, not graphs! - val startRoutes by lazy { main.map { it.start } } + val startRoutes by lazy { (main + additional).map { it.start } } } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/model/Shortcut.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/model/Shortcut.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/model/Shortcut.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/model/Shortcut.kt index db2ef43c..1cd42b88 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/model/Shortcut.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/model/Shortcut.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.model +package app.myzel394.numberhub.core.ui.model import androidx.annotation.DrawableRes import androidx.annotation.StringRes diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/Color.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/Color.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/Color.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/Color.kt index c9a61016..00d1f5d2 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/Color.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/Color.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.theme +package app.myzel394.numberhub.core.ui.theme import androidx.compose.ui.graphics.Color @@ -46,7 +46,6 @@ val md_theme_light_outline = Color(0xFF727970) val md_theme_light_inverseOnSurface = Color(0xFFf0f1eb) val md_theme_light_inverseSurface = Color(0xFF2f312e) - val md_theme_dark_primary = Color(0xFF87d991) val md_theme_dark_onPrimary = Color(0xFF003911) val md_theme_dark_primaryContainer = Color(0xFF00531d) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/ColorSchemes.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/ColorSchemes.kt similarity index 98% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/ColorSchemes.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/ColorSchemes.kt index 27ab8473..0ec81d81 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/ColorSchemes.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/ColorSchemes.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.theme +package app.myzel394.numberhub.core.ui.theme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/Type.kt b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/Type.kt similarity index 95% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/Type.kt rename to core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/Type.kt index 5b881321..b506d7e1 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/theme/Type.kt +++ b/core/ui/src/main/java/app/myzel394/numberhub/core/ui/theme/Type.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.theme +package app.myzel394.numberhub.core.ui.theme import androidx.compose.foundation.background import androidx.compose.foundation.lazy.LazyColumn @@ -34,7 +34,7 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.sp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R @Immutable data class NumberTypography( @@ -83,7 +83,7 @@ val TypographySystem by lazy { Typography() } private val FontFamily.Companion.lato: FontFamily get() = FontFamily( - Font(R.font.lato_regular, weight = FontWeight.Normal) + Font(R.font.lato_regular, weight = FontWeight.Normal), ) @Preview(widthDp = 480) @@ -113,7 +113,7 @@ private fun PreviewSystemTypography() { Text( text = "$label 123", style = style, - color = MaterialTheme.colorScheme.onBackground + color = MaterialTheme.colorScheme.onBackground, ) } } @@ -124,7 +124,7 @@ private fun PreviewSystemTypography() { @Composable private fun PreviewNumberTypography() { CompositionLocalProvider( - LocalNumberTypography provides NumberTypographyUnitto + LocalNumberTypography provides NumberTypographyUnitto, ) { val textStyles = mapOf( "displayLarge" to LocalNumberTypography.current.displayLarge, @@ -138,7 +138,7 @@ private fun PreviewNumberTypography() { Text( text = "$label 123 Error 7 1⁄2", style = style, - color = MaterialTheme.colorScheme.onBackground + color = MaterialTheme.colorScheme.onBackground, ) } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SettingsButton.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SettingsButton.kt deleted file mode 100644 index 16d1aeb3..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/SettingsButton.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common - -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Settings -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.R - -@Composable -fun SettingsButton(onClick: () -> Unit) { - IconButton(onClick) { - Icon(Icons.Outlined.Settings, stringResource(R.string.open_settings_label)) - } -} diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Down.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Down.kt deleted file mode 100644 index 11769bb2..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Down.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.icons.iconpack - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathFillType.Companion.NonZero -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap.Companion.Butt -import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.ImageVector.Builder -import androidx.compose.ui.graphics.vector.path -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack - -@Suppress("UnusedReceiverParameter") -val IconPack.Down: ImageVector - get() { - if (_down != null) { - return _down!! - } - _down = Builder(name = "Down", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, - viewportWidth = 24.0f, viewportHeight = 24.0f).apply { - path(fill = SolidColor(Color(0xFF1C1B1F)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(11.5453f, 8.5322f) - verticalLineTo(14.0663f) - lineTo(8.9999f, 11.5208f) - lineTo(8.3635f, 12.1686f) - lineTo(11.9999f, 15.8049f) - lineTo(15.6363f, 12.1686f) - lineTo(14.9999f, 11.5208f) - lineTo(12.4544f, 14.0663f) - verticalLineTo(8.5322f) - horizontalLineTo(11.5453f) - close() - } - } - .build() - return _down!! - } - -private var _down: ImageVector? = null diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Enter.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Enter.kt deleted file mode 100644 index 5f39492f..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Enter.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.icons.iconpack - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathFillType.Companion.NonZero -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap.Companion.Butt -import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.ImageVector.Builder -import androidx.compose.ui.graphics.vector.path -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack - -@Suppress("UnusedReceiverParameter") -val IconPack.Enter: ImageVector - get() { - if (_enter != null) { - return _enter!! - } - _enter = Builder(name = "Enter", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, - viewportWidth = 24.0f, viewportHeight = 24.0f).apply { - path(fill = SolidColor(Color(0xFF1C1B1F)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(15.2085f, 8.5322f) - lineTo(15.2085f, 13.6659f) - lineTo(10.4277f, 13.6659f) - lineTo(11.9679f, 15.1953f) - lineTo(11.3582f, 15.8049f) - lineTo(8.7914f, 13.2381f) - lineTo(11.3689f, 10.6605f) - lineTo(11.9679f, 11.2702f) - lineTo(10.4277f, 12.8103f) - lineTo(14.3529f, 12.8103f) - lineTo(14.3529f, 8.5322f) - lineTo(15.2085f, 8.5322f) - close() - } - } - .build() - return _enter!! - } - -private var _enter: ImageVector? = null diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Pop.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Pop.kt deleted file mode 100644 index 736139f7..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Pop.kt +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.icons.iconpack - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathFillType.Companion.NonZero -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap.Companion.Butt -import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.ImageVector.Builder -import androidx.compose.ui.graphics.vector.path -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack - -@Suppress("UnusedReceiverParameter") -val IconPack.Pop: ImageVector - get() { - if (_pop != null) { - return _pop!! - } - _pop = Builder(name = "Pop", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, viewportWidth - = 24.0f, viewportHeight = 24.0f).apply { - path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(5.2202f, 12.2187f) - curveTo(5.4969f, 12.2187f, 5.7402f, 12.182f, 5.9502f, 12.1087f) - curveTo(6.1636f, 12.0354f, 6.3419f, 11.9337f, 6.4852f, 11.8037f) - curveTo(6.6319f, 11.6704f, 6.7419f, 11.512f, 6.8152f, 11.3287f) - curveTo(6.8886f, 11.1454f, 6.9252f, 10.9437f, 6.9252f, 10.7237f) - curveTo(6.9252f, 10.267f, 6.7836f, 9.9104f, 6.5002f, 9.6537f) - curveTo(6.2202f, 9.397f, 5.7936f, 9.2687f, 5.2202f, 9.2687f) - horizontalLineTo(4.0702f) - verticalLineTo(12.2187f) - horizontalLineTo(5.2202f) - close() - moveTo(5.2202f, 8.5037f) - curveTo(5.6736f, 8.5037f, 6.0669f, 8.557f, 6.4002f, 8.6637f) - curveTo(6.7369f, 8.767f, 7.0152f, 8.9154f, 7.2352f, 9.1087f) - curveTo(7.4552f, 9.302f, 7.6186f, 9.5354f, 7.7252f, 9.8087f) - curveTo(7.8352f, 10.082f, 7.8902f, 10.387f, 7.8902f, 10.7237f) - curveTo(7.8902f, 11.057f, 7.8319f, 11.362f, 7.7152f, 11.6387f) - curveTo(7.5986f, 11.9154f, 7.4269f, 12.1537f, 7.2002f, 12.3537f) - curveTo(6.9769f, 12.5537f, 6.6986f, 12.7104f, 6.3652f, 12.8237f) - curveTo(6.0352f, 12.9337f, 5.6536f, 12.9887f, 5.2202f, 12.9887f) - horizontalLineTo(4.0702f) - verticalLineTo(15.6687f) - horizontalLineTo(3.1052f) - verticalLineTo(8.5037f) - horizontalLineTo(5.2202f) - close() - moveTo(15.5311f, 12.0887f) - curveTo(15.5311f, 12.6254f, 15.4461f, 13.1187f, 15.2761f, 13.5687f) - curveTo(15.1061f, 14.0154f, 14.8661f, 14.4004f, 14.5561f, 14.7237f) - curveTo(14.2461f, 15.047f, 13.8728f, 15.2987f, 13.4361f, 15.4787f) - curveTo(13.0028f, 15.6554f, 12.5228f, 15.7437f, 11.9961f, 15.7437f) - curveTo(11.4694f, 15.7437f, 10.9894f, 15.6554f, 10.5561f, 15.4787f) - curveTo(10.1228f, 15.2987f, 9.7511f, 15.047f, 9.4411f, 14.7237f) - curveTo(9.1311f, 14.4004f, 8.8911f, 14.0154f, 8.7211f, 13.5687f) - curveTo(8.5511f, 13.1187f, 8.4661f, 12.6254f, 8.4661f, 12.0887f) - curveTo(8.4661f, 11.552f, 8.5511f, 11.0604f, 8.7211f, 10.6137f) - curveTo(8.8911f, 10.1637f, 9.1311f, 9.777f, 9.4411f, 9.4537f) - curveTo(9.7511f, 9.127f, 10.1228f, 8.8737f, 10.5561f, 8.6937f) - curveTo(10.9894f, 8.5137f, 11.4694f, 8.4237f, 11.9961f, 8.4237f) - curveTo(12.5228f, 8.4237f, 13.0028f, 8.5137f, 13.4361f, 8.6937f) - curveTo(13.8728f, 8.8737f, 14.2461f, 9.127f, 14.5561f, 9.4537f) - curveTo(14.8661f, 9.777f, 15.1061f, 10.1637f, 15.2761f, 10.6137f) - curveTo(15.4461f, 11.0604f, 15.5311f, 11.552f, 15.5311f, 12.0887f) - close() - moveTo(14.5361f, 12.0887f) - curveTo(14.5361f, 11.6487f, 14.4761f, 11.2537f, 14.3561f, 10.9037f) - curveTo(14.2361f, 10.5537f, 14.0661f, 10.2587f, 13.8461f, 10.0187f) - curveTo(13.6261f, 9.7754f, 13.3594f, 9.5887f, 13.0461f, 9.4587f) - curveTo(12.7328f, 9.3287f, 12.3828f, 9.2637f, 11.9961f, 9.2637f) - curveTo(11.6128f, 9.2637f, 11.2644f, 9.3287f, 10.9511f, 9.4587f) - curveTo(10.6378f, 9.5887f, 10.3694f, 9.7754f, 10.1461f, 10.0187f) - curveTo(9.9261f, 10.2587f, 9.7561f, 10.5537f, 9.6361f, 10.9037f) - curveTo(9.5161f, 11.2537f, 9.4561f, 11.6487f, 9.4561f, 12.0887f) - curveTo(9.4561f, 12.5287f, 9.5161f, 12.9237f, 9.6361f, 13.2737f) - curveTo(9.7561f, 13.6204f, 9.9261f, 13.9154f, 10.1461f, 14.1587f) - curveTo(10.3694f, 14.3987f, 10.6378f, 14.5837f, 10.9511f, 14.7137f) - curveTo(11.2644f, 14.8404f, 11.6128f, 14.9037f, 11.9961f, 14.9037f) - curveTo(12.3828f, 14.9037f, 12.7328f, 14.8404f, 13.0461f, 14.7137f) - curveTo(13.3594f, 14.5837f, 13.6261f, 14.3987f, 13.8461f, 14.1587f) - curveTo(14.0661f, 13.9154f, 14.2361f, 13.6204f, 14.3561f, 13.2737f) - curveTo(14.4761f, 12.9237f, 14.5361f, 12.5287f, 14.5361f, 12.0887f) - close() - moveTo(18.8339f, 12.2187f) - curveTo(19.1106f, 12.2187f, 19.3539f, 12.182f, 19.5639f, 12.1087f) - curveTo(19.7772f, 12.0354f, 19.9556f, 11.9337f, 20.0989f, 11.8037f) - curveTo(20.2456f, 11.6704f, 20.3556f, 11.512f, 20.4289f, 11.3287f) - curveTo(20.5022f, 11.1454f, 20.5389f, 10.9437f, 20.5389f, 10.7237f) - curveTo(20.5389f, 10.267f, 20.3972f, 9.9104f, 20.1139f, 9.6537f) - curveTo(19.8339f, 9.397f, 19.4072f, 9.2687f, 18.8339f, 9.2687f) - horizontalLineTo(17.6839f) - verticalLineTo(12.2187f) - horizontalLineTo(18.8339f) - close() - moveTo(18.8339f, 8.5037f) - curveTo(19.2872f, 8.5037f, 19.6806f, 8.557f, 20.0139f, 8.6637f) - curveTo(20.3506f, 8.767f, 20.6289f, 8.9154f, 20.8489f, 9.1087f) - curveTo(21.0689f, 9.302f, 21.2322f, 9.5354f, 21.3389f, 9.8087f) - curveTo(21.4489f, 10.082f, 21.5039f, 10.387f, 21.5039f, 10.7237f) - curveTo(21.5039f, 11.057f, 21.4456f, 11.362f, 21.3289f, 11.6387f) - curveTo(21.2122f, 11.9154f, 21.0406f, 12.1537f, 20.8139f, 12.3537f) - curveTo(20.5906f, 12.5537f, 20.3122f, 12.7104f, 19.9789f, 12.8237f) - curveTo(19.6489f, 12.9337f, 19.2672f, 12.9887f, 18.8339f, 12.9887f) - horizontalLineTo(17.6839f) - verticalLineTo(15.6687f) - horizontalLineTo(16.7189f) - verticalLineTo(8.5037f) - horizontalLineTo(18.8339f) - close() - } - } - .build() - return _pop!! - } - -private var _pop: ImageVector? = null diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Swap.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Swap.kt deleted file mode 100644 index ed6b9b9f..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Swap.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.icons.iconpack - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathFillType.Companion.NonZero -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap.Companion.Butt -import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.ImageVector.Builder -import androidx.compose.ui.graphics.vector.path -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack - -@Suppress("UnusedReceiverParameter") -val IconPack.Swap: ImageVector - get() { - if (_swap != null) { - return _swap!! - } - _swap = Builder(name = "Swap", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, - viewportWidth = 24.0f, viewportHeight = 24.0f).apply { - path(fill = SolidColor(Color(0xFF1C1B1F)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(10.5454f, 12.5325f) - verticalLineTo(9.9234f) - lineTo(9.609f, 10.8597f) - lineTo(9.0908f, 10.3507f) - lineTo(10.909f, 8.5325f) - lineTo(12.7272f, 10.3507f) - lineTo(12.209f, 10.8597f) - lineTo(11.2726f, 9.9234f) - verticalLineTo(12.5325f) - horizontalLineTo(10.5454f) - close() - moveTo(13.0908f, 15.8052f) - lineTo(11.2726f, 13.987f) - lineTo(11.7908f, 13.4779f) - lineTo(12.7272f, 14.4143f) - verticalLineTo(11.8052f) - horizontalLineTo(13.4545f) - verticalLineTo(14.4143f) - lineTo(14.3908f, 13.4779f) - lineTo(14.909f, 13.987f) - lineTo(13.0908f, 15.8052f) - close() - } - } - .build() - return _swap!! - } - -private var _swap: ImageVector? = null diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Unary.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Unary.kt deleted file mode 100644 index 4a931c44..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Unary.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.icons.iconpack - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathFillType.Companion.NonZero -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap.Companion.Butt -import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.ImageVector.Builder -import androidx.compose.ui.graphics.vector.path -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack - -@Suppress("UnusedReceiverParameter") -val IconPack.Unary: ImageVector - get() { - if (_unary != null) { - return _unary!! - } - _unary = Builder(name = "Unary", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, - viewportWidth = 24.0f, viewportHeight = 24.0f).apply { - path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(9.0454f, 11.1177f) - horizontalLineTo(14.9545f) - verticalLineTo(11.8933f) - horizontalLineTo(9.0454f) - verticalLineTo(11.1177f) - close() - } - path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(12.4431f, 8.5325f) - lineTo(12.4431f, 14.4416f) - horizontalLineTo(11.6676f) - lineTo(11.6676f, 8.5325f) - lineTo(12.4431f, 8.5325f) - close() - } - path(fill = SolidColor(Color(0xFF000000)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(9.0454f, 15.1234f) - horizontalLineTo(14.9545f) - verticalLineTo(15.8052f) - horizontalLineTo(9.0454f) - verticalLineTo(15.1234f) - close() - } - } - .build() - return _unary!! - } - -private var _unary: ImageVector? = null diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Up.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Up.kt deleted file mode 100644 index e2197970..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/icons/iconpack/Up.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.icons.iconpack - -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.PathFillType.Companion.NonZero -import androidx.compose.ui.graphics.SolidColor -import androidx.compose.ui.graphics.StrokeCap.Companion.Butt -import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.graphics.vector.ImageVector.Builder -import androidx.compose.ui.graphics.vector.path -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.icons.IconPack - -@Suppress("UnusedReceiverParameter") -val IconPack.Up: ImageVector - get() { - if (_up != null) { - return _up!! - } - _up = Builder(name = "Up", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, viewportWidth = - 24.0f, viewportHeight = 24.0f).apply { - path(fill = SolidColor(Color(0xFF1C1B1F)), stroke = null, strokeLineWidth = 0.0f, - strokeLineCap = Butt, strokeLineJoin = Miter, strokeLineMiter = 4.0f, - pathFillType = NonZero) { - moveTo(11.5453f, 15.8052f) - verticalLineTo(10.2711f) - lineTo(8.9999f, 12.8166f) - lineTo(8.3635f, 12.1688f) - lineTo(11.9999f, 8.5325f) - lineTo(15.6363f, 12.1688f) - lineTo(14.9999f, 12.8166f) - lineTo(12.4544f, 10.2711f) - verticalLineTo(15.8052f) - horizontalLineTo(11.5453f) - close() - } - } - .build() - return _up!! - } - -private var _up: ImageVector? = null diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/ClipboardManagerExt.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/ClipboardManagerExt.kt deleted file mode 100644 index f3ef26bb..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/ClipboardManagerExt.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.textfield - -import androidx.compose.ui.platform.ClipboardManager -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.base.Token - -/** - * Copy value to clipboard with fractional symbols. - * - * Example: - * "123456.789" will be copied as "123456,789" - * - * @param value Internal [TextFieldValue] without formatting with [Token.Digit.dot] as fractional. - */ -internal fun ClipboardManager.copyWithFractional( - value: TextFieldValue, - formatterSymbols: FormatterSymbols -) = this.setText( - AnnotatedString( - value.annotatedString - .subSequence(value.selection) - .text - .replace(Token.Digit.dot, formatterSymbols.fractional) - ) -) - -internal fun ClipboardManager.copy(value: TextFieldValue) = this.setText( - AnnotatedString( - value.annotatedString - .subSequence(value.selection) - .text - ) -) diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FixedInputTextFIeld.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FixedInputTextFIeld.kt deleted file mode 100644 index 9cdee727..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FixedInputTextFIeld.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.textfield - -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.interaction.PressInteraction -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.BasicTextField -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.platform.LocalTextInputService -import androidx.compose.ui.platform.LocalTextToolbar -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.textfield.texttoolbar.UnittoTextToolbar -import com.sadellie.unitto.core.ui.theme.LocalNumberTypography - -@Composable -fun FixedInputTextField( - modifier: Modifier = Modifier, - value: String, - formatterSymbols: FormatterSymbols, - textColor: Color, - onClick: (cleanValue: String) -> Unit -) { - val clipboardManager = LocalClipboardManager.current - val expression = value.take(1000) - var expressionValue by remember(expression) { - mutableStateOf(TextFieldValue(expression, TextRange(expression.length))) - } - - val expressionInteractionSource = remember(expression) { MutableInteractionSource() } - LaunchedEffect(expressionInteractionSource) { - expressionInteractionSource.interactions.collect { - if (it is PressInteraction.Release) onClick(value) - } - } - - CompositionLocalProvider( - LocalTextInputService provides null, - LocalTextToolbar provides UnittoTextToolbar( - view = LocalView.current, - copyCallback = { - clipboardManager.copyWithFractional(expressionValue, formatterSymbols) - expressionValue = expressionValue.copy(selection = TextRange(expressionValue.selection.end)) - } - ) - ) { - BasicTextField( - value = expressionValue, - onValueChange = { expressionValue = it }, - maxLines = 1, - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 8.dp) - .horizontalScroll(rememberScrollState(), reverseScrolling = true), - textStyle = LocalNumberTypography.current.displaySmall.copy(color = textColor, textAlign = TextAlign.End), - readOnly = true, - visualTransformation = ExpressionTransformer(formatterSymbols), - interactionSource = expressionInteractionSource - ) - } -} diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FormatterSymbols.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FormatterSymbols.kt deleted file mode 100644 index a1462edd..00000000 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/textfield/FormatterSymbols.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.core.ui.common.textfield - -import com.sadellie.unitto.core.base.Separator - -sealed class FormatterSymbols(val grouping: String, val fractional: String) { - data object Spaces : FormatterSymbols(" ", ".") - data object Period : FormatterSymbols(".", ",") - data object Comma : FormatterSymbols(",", ".") -} - -object AllFormatterSymbols { - private val allFormatterSymbols by lazy { - hashMapOf( - Separator.SPACE to FormatterSymbols.Spaces, - Separator.PERIOD to FormatterSymbols.Period, - Separator.COMMA to FormatterSymbols.Comma - ) - } - - /** - * Defaults to [FormatterSymbols.Spaces] if not found. - * - * @see Separator - */ - fun getById(separator: Int): FormatterSymbols { - return allFormatterSymbols.getOrElse(separator) { FormatterSymbols.Spaces } - } -} diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/CleanAndFilterExpression.kt b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/CleanAndFilterExpression.kt similarity index 70% rename from core/ui/src/test/java/com/sadellie/unitto/core/ui/CleanAndFilterExpression.kt rename to core/ui/src/test/java/app/myzel394/numberhub/core/ui/CleanAndFilterExpression.kt index 147e7a97..5cffba44 100644 --- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/CleanAndFilterExpression.kt +++ b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/CleanAndFilterExpression.kt @@ -16,42 +16,48 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.clearAndFilterExpression +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.clearAndFilterExpression import org.junit.Assert.assertEquals import org.junit.Test class CleanAndFilterExpression { + + private val formatterSymbols = FormatterSymbols(Token.COMMA, Token.PERIOD) + @Test fun noAdditionalSymbols() { - assertEquals("123", "123".clearAndFilterExpression(FormatterSymbols.Comma)) - assertEquals("123.456", "123.456".clearAndFilterExpression(FormatterSymbols.Comma)) + assertEquals("123", "123".clearAndFilterExpression(formatterSymbols)) + assertEquals("123.456", "123.456".clearAndFilterExpression(formatterSymbols)) } @Test fun hasFormatterSymbol() { - assertEquals("123456", "123,456".clearAndFilterExpression(FormatterSymbols.Comma)) - assertEquals("123456.789", "123,456.789".clearAndFilterExpression(FormatterSymbols.Comma)) + assertEquals("123456", "123,456".clearAndFilterExpression(formatterSymbols)) + assertEquals("123456.789", "123,456.789".clearAndFilterExpression(formatterSymbols)) } @Test fun hasWrongFormatterSymbol() { - assertEquals("123456", "123 456".clearAndFilterExpression(FormatterSymbols.Comma)) - assertEquals("123456.789", "123 456.789".clearAndFilterExpression(FormatterSymbols.Comma)) + assertEquals("123456", "123 456".clearAndFilterExpression(formatterSymbols)) + assertEquals("123456.789", "123 456.789".clearAndFilterExpression(formatterSymbols)) } @Test fun fractionExpression() { - assertEquals("1600+1234÷56789", "1,600 1234⁄56789".clearAndFilterExpression(FormatterSymbols.Comma)) - assertEquals("123456.789+1234÷56789", "123,456.789 1234⁄56789".clearAndFilterExpression(FormatterSymbols.Comma)) + assertEquals("1600+1234÷56789", "1,600 1234⁄56789".clearAndFilterExpression(formatterSymbols)) + assertEquals("123456.789+1234÷56789", "123,456.789 1234⁄56789".clearAndFilterExpression(formatterSymbols)) } + /* @Test fun garbage() { // 'e' is a known symbol - assertEquals("eeee−123", "pee pee poo poo -123".clearAndFilterExpression(FormatterSymbols.Comma)) - assertEquals("eeee−123.456", "pee pee poo poo -123.456".clearAndFilterExpression(FormatterSymbols.Comma)) + assertEquals("eeee−123", "pee pee poo poo -123".clearAndFilterExpression(formatterSymbols)) + assertEquals("eeee−123.456", "pee pee poo poo -123.456".clearAndFilterExpression(formatterSymbols)) } + */ } diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/ExpressionTransformerTest.kt similarity index 87% rename from core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt rename to core/ui/src/test/java/app/myzel394/numberhub/core/ui/ExpressionTransformerTest.kt index cc86d390..1b51a6f5 100644 --- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/ExpressionTransformerTest.kt +++ b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/ExpressionTransformerTest.kt @@ -16,16 +16,17 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui -import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.ExpressionTransformer import org.junit.Assert.assertEquals import org.junit.Test class ExpressionTransformerTest { - private val expr = ExpressionTransformer(FormatterSymbols.Comma) + private val expr = ExpressionTransformer(FormatterSymbols(Token.COMMA, Token.PERIOD)) // Use "|" for cursor private fun origToTrans(orig: String, trans: String) { diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterExpressionTest.kt b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/FormatterExpressionTest.kt similarity index 93% rename from core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterExpressionTest.kt rename to core/ui/src/test/java/app/myzel394/numberhub/core/ui/FormatterExpressionTest.kt index 6179d129..63b167e7 100644 --- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterExpressionTest.kt +++ b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/FormatterExpressionTest.kt @@ -16,10 +16,11 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression import org.junit.Assert.assertEquals import org.junit.Test @@ -40,7 +41,7 @@ class FormatterExpressionTest { @Test fun setSeparatorSpaces() { - fun String.format(): String = formatExpression(FormatterSymbols.Spaces) + fun String.format(): String = formatExpression(FormatterSymbols(Token.SPACE, Token.PERIOD)) assertEquals("123E+21", ENG_VALUE.format()) assertEquals("123.3E+21", ENG_VALUE_FRACTIONAL.format()) assertEquals("123E+21+(123 456.789)", ENG_VALUE_EXPRESSION.format()) @@ -57,7 +58,7 @@ class FormatterExpressionTest { @Test fun setSeparatorComma() { - fun String.format(): String = formatExpression(FormatterSymbols.Comma) + fun String.format(): String = formatExpression(FormatterSymbols(Token.COMMA, Token.PERIOD)) assertEquals("123E+21", ENG_VALUE.format()) assertEquals("123.3E+21", ENG_VALUE_FRACTIONAL.format()) assertEquals("123E+21+(123,456.789)", ENG_VALUE_EXPRESSION.format()) @@ -74,7 +75,7 @@ class FormatterExpressionTest { @Test fun setSeparatorPeriod() { - fun String.format(): String = formatExpression(FormatterSymbols.Period) + fun String.format(): String = formatExpression(FormatterSymbols(Token.PERIOD, Token.COMMA)) assertEquals("123E+21", ENG_VALUE.format()) assertEquals("123,3E+21", ENG_VALUE_FRACTIONAL.format()) assertEquals("123E+21+(123.456,789)", ENG_VALUE_EXPRESSION.format()) @@ -88,4 +89,4 @@ class FormatterExpressionTest { assertEquals("((((((((", SOME_BRACKETS.format()) assertEquals("1.600 1234⁄56789", FRACTION_VALUE.format()) } -} \ No newline at end of file +} diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/TextFieldValueExtensionsTest.kt similarity index 98% rename from core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt rename to core/ui/src/test/java/app/myzel394/numberhub/core/ui/TextFieldValueExtensionsTest.kt index 993195aa..30de7293 100644 --- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/TextFieldValueExtensionsTest.kt +++ b/core/ui/src/test/java/app/myzel394/numberhub/core/ui/TextFieldValueExtensionsTest.kt @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui +package app.myzel394.numberhub.core.ui import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.addBracket -import com.sadellie.unitto.core.ui.common.textfield.addTokens +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.addBracket +import app.myzel394.numberhub.core.ui.common.textfield.addTokens import org.junit.Assert.assertEquals import org.junit.Test @@ -332,7 +332,7 @@ class TextFieldValueExtensionsTest { .replace("-", Token.Operator.minus) .replace("/", Token.Operator.divide) .replace("*", Token.Operator.multiply), - selection = TextRange(selectionStart, selectionEnd) + selection = TextRange(selectionStart, selectionEnd), ) } } diff --git a/data/backup/build.gradle.kts b/data/backup/build.gradle.kts index ec96ab57..ef5bc946 100644 --- a/data/backup/build.gradle.kts +++ b/data/backup/build.gradle.kts @@ -23,7 +23,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.backup" +android.namespace = "app.myzel394.numberhub.data.backup" android { room { @@ -34,10 +34,6 @@ android { } dependencies { - implementation(libs.androidx.datastore.datastore.preferences) - implementation(libs.com.github.sadellie.themmo.core) - implementation(project(":data:database")) - implementation(project(":data:model")) implementation(project(":data:userprefs")) } diff --git a/data/backup/src/androidTest/java/com/sadellie/unitto/data/backup/BackupManagerTest.kt b/data/backup/src/androidTest/java/app/myzel394/numberhub/data/backup/BackupManagerTest.kt similarity index 94% rename from data/backup/src/androidTest/java/com/sadellie/unitto/data/backup/BackupManagerTest.kt rename to data/backup/src/androidTest/java/app/myzel394/numberhub/data/backup/BackupManagerTest.kt index 6c83f574..20566acd 100644 --- a/data/backup/src/androidTest/java/com/sadellie/unitto/data/backup/BackupManagerTest.kt +++ b/data/backup/src/androidTest/java/app/myzel394/numberhub/data/backup/BackupManagerTest.kt @@ -16,10 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.backup +package app.myzel394.numberhub.data.backup import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.junit.Assert.* import org.junit.runner.RunWith /** diff --git a/data/backup/src/main/java/com/sadellie/unitto/data/backup/BackupManager.kt b/data/backup/src/main/java/app/myzel394/numberhub/data/backup/BackupManager.kt similarity index 95% rename from data/backup/src/main/java/com/sadellie/unitto/data/backup/BackupManager.kt rename to data/backup/src/main/java/app/myzel394/numberhub/data/backup/BackupManager.kt index a189f054..079bc73a 100644 --- a/data/backup/src/main/java/com/sadellie/unitto/data/backup/BackupManager.kt +++ b/data/backup/src/main/java/app/myzel394/numberhub/data/backup/BackupManager.kt @@ -16,16 +16,16 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.backup +package app.myzel394.numberhub.data.backup import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri -import com.sadellie.unitto.data.database.DATABASE_NAME -import com.sadellie.unitto.data.database.UnittoDatabase -import com.sadellie.unitto.data.database.checkpoint -import com.sadellie.unitto.data.userprefs.USER_PREFERENCES +import app.myzel394.numberhub.data.database.DATABASE_NAME +import app.myzel394.numberhub.data.database.UnittoDatabase +import app.myzel394.numberhub.data.database.checkpoint +import app.myzel394.numberhub.data.userprefs.USER_PREFERENCES import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.File diff --git a/data/calculator/build.gradle.kts b/data/calculator/build.gradle.kts index b0d442a3..b183a190 100644 --- a/data/calculator/build.gradle.kts +++ b/data/calculator/build.gradle.kts @@ -22,7 +22,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.calculator" +android.namespace = "app.myzel394.numberhub.data.calculator" dependencies { implementation(project(":data:database")) diff --git a/data/calculator/src/main/java/com/sadellie/unitto/data/calculator/CalculatorHistoryRepositoryImpl.kt b/data/calculator/src/main/java/app/myzel394/numberhub/data/calculator/CalculatorHistoryRepositoryImpl.kt similarity index 65% rename from data/calculator/src/main/java/com/sadellie/unitto/data/calculator/CalculatorHistoryRepositoryImpl.kt rename to data/calculator/src/main/java/app/myzel394/numberhub/data/calculator/CalculatorHistoryRepositoryImpl.kt index cabc826f..a03757a0 100644 --- a/data/calculator/src/main/java/com/sadellie/unitto/data/calculator/CalculatorHistoryRepositoryImpl.kt +++ b/data/calculator/src/main/java/app/myzel394/numberhub/data/calculator/CalculatorHistoryRepositoryImpl.kt @@ -16,21 +16,22 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.calculator +package app.myzel394.numberhub.data.calculator -import com.sadellie.unitto.data.database.CalculatorHistoryDao -import com.sadellie.unitto.data.database.CalculatorHistoryEntity -import com.sadellie.unitto.data.model.HistoryItem -import com.sadellie.unitto.data.model.repository.CalculatorHistoryRepository +import app.myzel394.numberhub.data.database.CalculatorHistoryDao +import app.myzel394.numberhub.data.database.CalculatorHistoryEntity +import app.myzel394.numberhub.data.model.HistoryItem +import app.myzel394.numberhub.data.model.repository.CalculatorHistoryRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.withContext import java.util.Date import javax.inject.Inject class CalculatorHistoryRepositoryImpl @Inject constructor( - private val calculatorHistoryDao: CalculatorHistoryDao + private val calculatorHistoryDao: CalculatorHistoryDao, ) : CalculatorHistoryRepository { /** * Calculator history sorted by [CalculatorHistoryEntity.timestamp] from new to old (DESC). @@ -42,28 +43,32 @@ class CalculatorHistoryRepositoryImpl @Inject constructor( override suspend fun add( expression: String, - result: String - ) { + result: String, + ) = withContext(Dispatchers.IO) { calculatorHistoryDao.insert( CalculatorHistoryEntity( timestamp = System.currentTimeMillis(), expression = expression, - result = result - ) + result = result, + ), ) } - override suspend fun clear() { + override suspend fun delete(item: HistoryItem) = withContext(Dispatchers.IO) { + calculatorHistoryDao.delete(item.id) + } + + override suspend fun clear() = withContext(Dispatchers.IO) { calculatorHistoryDao.clear() } - private fun List.toHistoryItemList(): List { - return this.map { + private suspend fun List.toHistoryItemList(): List = withContext(Dispatchers.Default) { + this@toHistoryItemList.map { HistoryItem( id = it.entityId, date = Date(it.timestamp), expression = it.expression, - result = it.result + result = it.result, ) } } diff --git a/data/calculator/src/main/java/com/sadellie/unitto/data/calculator/DataStoreModule.kt b/data/calculator/src/main/java/app/myzel394/numberhub/data/calculator/DataStoreModule.kt similarity index 85% rename from data/calculator/src/main/java/com/sadellie/unitto/data/calculator/DataStoreModule.kt rename to data/calculator/src/main/java/app/myzel394/numberhub/data/calculator/DataStoreModule.kt index 5973e607..d0e27147 100644 --- a/data/calculator/src/main/java/com/sadellie/unitto/data/calculator/DataStoreModule.kt +++ b/data/calculator/src/main/java/app/myzel394/numberhub/data/calculator/DataStoreModule.kt @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.calculator +package app.myzel394.numberhub.data.calculator -import com.sadellie.unitto.data.database.CalculatorHistoryDao -import com.sadellie.unitto.data.model.repository.CalculatorHistoryRepository +import app.myzel394.numberhub.data.database.CalculatorHistoryDao +import app.myzel394.numberhub.data.model.repository.CalculatorHistoryRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn diff --git a/data/common/build.gradle.kts b/data/common/build.gradle.kts index 5d9d0e9a..ed55a3a8 100644 --- a/data/common/build.gradle.kts +++ b/data/common/build.gradle.kts @@ -21,7 +21,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.common" +android.namespace = "app.myzel394.numberhub.data.common" dependencies { implementation(libs.androidx.core.core.ktx) diff --git a/data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt b/data/common/src/main/java/app/myzel394/numberhub/data/common/BigDecimalUtils.kt similarity index 95% rename from data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt rename to data/common/src/main/java/app/myzel394/numberhub/data/common/BigDecimalUtils.kt index 3b5c0acb..6b946132 100644 --- a/data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt +++ b/data/common/src/main/java/app/myzel394/numberhub/data/common/BigDecimalUtils.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common -import com.sadellie.unitto.core.base.OutputFormat +import app.myzel394.numberhub.core.base.OutputFormat import java.math.BigDecimal import java.math.RoundingMode import kotlin.math.floor @@ -26,7 +26,7 @@ import kotlin.math.log10 fun BigDecimal.format( scale: Int, - outputFormat: Int + outputFormat: Int, ): String { return this .setMinimumRequiredScale(scale) @@ -85,9 +85,9 @@ internal fun BigDecimal.setMinimumRequiredScale(prefScale: Int): BigDecimal { -floor(log10(this.abs().remainder(BigDecimal.ONE).toDouble())).toInt() } else { 0 - } + }, ), - RoundingMode.HALF_EVEN + RoundingMode.HALF_EVEN, ) } diff --git a/data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt b/data/common/src/main/java/app/myzel394/numberhub/data/common/FlowUtils.kt similarity index 59% rename from data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt rename to data/common/src/main/java/app/myzel394/numberhub/data/common/FlowUtils.kt index 4861dd77..86bc2a5d 100644 --- a/data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt +++ b/data/common/src/main/java/app/myzel394/numberhub/data/common/FlowUtils.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow @@ -83,76 +83,5 @@ fun combine( ) } -@Suppress("UNCHECKED_CAST", "UNUSED") -fun combine( - flow: Flow, - flow2: Flow, - flow3: Flow, - flow4: Flow, - flow5: Flow, - flow6: Flow, - flow7: Flow, - flow8: Flow, - transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R, -): Flow = - kotlinx.coroutines.flow.combine( - flow, - flow2, - flow3, - flow4, - flow5, - flow6, - flow7, - flow8 - ) { args: Array<*> -> - transform( - args[0] as T1, - args[1] as T2, - args[2] as T3, - args[3] as T4, - args[4] as T5, - args[5] as T6, - args[6] as T7, - args[7] as T8, - ) - } - -@Suppress("UNCHECKED_CAST", "UNUSED") -fun combine( - flow: Flow, - flow2: Flow, - flow3: Flow, - flow4: Flow, - flow5: Flow, - flow6: Flow, - flow7: Flow, - flow8: Flow, - flow9: Flow, - transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R, -): Flow = - kotlinx.coroutines.flow.combine( - flow, - flow2, - flow3, - flow4, - flow5, - flow6, - flow7, - flow8, - flow9 - ) { args: Array<*> -> - transform( - args[0] as T1, - args[1] as T2, - args[2] as T3, - args[3] as T4, - args[4] as T5, - args[5] as T6, - args[6] as T7, - args[7] as T8, - args[8] as T9, - ) - } - fun Flow.stateIn(scope: CoroutineScope, initialValue: T): StateFlow = stateIn(scope, SharingStarted.WhileSubscribed(5000L), initialValue) diff --git a/data/common/src/main/java/com/sadellie/unitto/data/common/StringUtils.kt b/data/common/src/main/java/app/myzel394/numberhub/data/common/StringUtils.kt similarity index 95% rename from data/common/src/main/java/com/sadellie/unitto/data/common/StringUtils.kt rename to data/common/src/main/java/app/myzel394/numberhub/data/common/StringUtils.kt index 02f772f6..27ac1a56 100644 --- a/data/common/src/main/java/com/sadellie/unitto/data/common/StringUtils.kt +++ b/data/common/src/main/java/app/myzel394/numberhub/data/common/StringUtils.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common -import com.sadellie.unitto.core.base.Token +import app.myzel394.numberhub.core.base.Token /** * Compute Levenshtein Distance between this string and [secondString]. Doesn't matter which string is @@ -50,7 +50,7 @@ fun String.lev(secondString: String): Int { // Insert cost[j] + 1, // Delete - newCost[j - 1] + 1 + newCost[j - 1] + 1, ) } @@ -62,7 +62,6 @@ fun String.lev(secondString: String): Int { } fun String.isExpression(): Boolean { - if (isEmpty()) return false // Positive numbers and zero diff --git a/data/common/src/main/java/com/sadellie/unitto/data/common/TimeZoneUtils.kt b/data/common/src/main/java/app/myzel394/numberhub/data/common/TimeZoneUtils.kt similarity index 98% rename from data/common/src/main/java/com/sadellie/unitto/data/common/TimeZoneUtils.kt rename to data/common/src/main/java/app/myzel394/numberhub/data/common/TimeZoneUtils.kt index 38df0676..21bb6adb 100644 --- a/data/common/src/main/java/com/sadellie/unitto/data/common/TimeZoneUtils.kt +++ b/data/common/src/main/java/app/myzel394/numberhub/data/common/TimeZoneUtils.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common import android.icu.text.LocaleDisplayNames import android.icu.text.TimeZoneNames diff --git a/data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt b/data/common/src/test/java/app/myzel394/numberhub/data/common/IsExpressionText.kt similarity index 97% rename from data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt rename to data/common/src/test/java/app/myzel394/numberhub/data/common/IsExpressionText.kt index c62fc57b..481c18e6 100644 --- a/data/common/src/test/java/com/sadellie/unitto/data/common/IsExpressionText.kt +++ b/data/common/src/test/java/app/myzel394/numberhub/data/common/IsExpressionText.kt @@ -16,12 +16,11 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common import org.junit.Assert.assertEquals import org.junit.Test - class IsExpressionText { @Test fun `empty string`() = assertEquals(false, "".isExpression()) diff --git a/data/common/src/test/java/com/sadellie/unitto/data/common/LevenshteinTest.kt b/data/common/src/test/java/app/myzel394/numberhub/data/common/LevenshteinTest.kt similarity index 97% rename from data/common/src/test/java/com/sadellie/unitto/data/common/LevenshteinTest.kt rename to data/common/src/test/java/app/myzel394/numberhub/data/common/LevenshteinTest.kt index cafb73ee..589a7071 100644 --- a/data/common/src/test/java/com/sadellie/unitto/data/common/LevenshteinTest.kt +++ b/data/common/src/test/java/app/myzel394/numberhub/data/common/LevenshteinTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common import org.junit.Assert.assertEquals import org.junit.Test @@ -62,4 +62,4 @@ class LevenshteinTest { fun levDifferentCases() { assertEquals(0, "red truck".lev("red TRUCK")) } -} \ No newline at end of file +} diff --git a/data/common/src/test/java/com/sadellie/unitto/data/common/MinimumRequiredScaleTest.kt b/data/common/src/test/java/app/myzel394/numberhub/data/common/MinimumRequiredScaleTest.kt similarity index 97% rename from data/common/src/test/java/com/sadellie/unitto/data/common/MinimumRequiredScaleTest.kt rename to data/common/src/test/java/app/myzel394/numberhub/data/common/MinimumRequiredScaleTest.kt index 261c238b..6a9d0fe3 100644 --- a/data/common/src/test/java/com/sadellie/unitto/data/common/MinimumRequiredScaleTest.kt +++ b/data/common/src/test/java/app/myzel394/numberhub/data/common/MinimumRequiredScaleTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common import org.junit.Assert.assertEquals import org.junit.Test @@ -44,4 +44,4 @@ class MinimumRequiredScaleTest { val bd = BigDecimal("0.000000123456").setMinimumRequiredScale(9) assertEquals("0.000000123", bd.toPlainString()) } -} \ No newline at end of file +} diff --git a/data/common/src/test/java/com/sadellie/unitto/data/common/NormalizeSuperscriptTest.kt b/data/common/src/test/java/app/myzel394/numberhub/data/common/NormalizeSuperscriptTest.kt similarity index 95% rename from data/common/src/test/java/com/sadellie/unitto/data/common/NormalizeSuperscriptTest.kt rename to data/common/src/test/java/app/myzel394/numberhub/data/common/NormalizeSuperscriptTest.kt index 87607dc2..0067fc49 100644 --- a/data/common/src/test/java/com/sadellie/unitto/data/common/NormalizeSuperscriptTest.kt +++ b/data/common/src/test/java/app/myzel394/numberhub/data/common/NormalizeSuperscriptTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.common +package app.myzel394.numberhub.data.common import org.junit.Assert.assertEquals import org.junit.Test diff --git a/data/converter/build.gradle.kts b/data/converter/build.gradle.kts index ccaf2c9b..14019298 100644 --- a/data/converter/build.gradle.kts +++ b/data/converter/build.gradle.kts @@ -23,7 +23,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.converter" +android.namespace = "app.myzel394.numberhub.data.converter" android.testOptions.unitTests.isIncludeAndroidResources = true android { @@ -35,14 +35,13 @@ android { } dependencies { - implementation(libs.androidx.lifecycle.lifecycle.runtime.compose) - implementation(libs.androidx.datastore.datastore.preferences) - + testImplementation(libs.org.robolectric.robolectric) implementation(libs.com.squareup.moshi.moshi.kotlin) implementation(libs.com.squareup.retrofit2.converter.moshi) implementation(project(":core:base")) implementation(project(":data:common")) implementation(project(":data:database")) + implementation(project(":data:evaluatto")) implementation(project(":data:model")) } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/BatchConvertResult.kt similarity index 70% rename from data/model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt rename to data/converter/src/main/java/app/myzel394/numberhub/data/converter/BatchConvertResult.kt index 9a8b0c48..ad87b382 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/BatchConvertResult.kt @@ -1,6 +1,6 @@ /* * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev + * Copyright (c) 2024 Elshan Agaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,10 +16,18 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.unit +package app.myzel394.numberhub.data.converter import java.math.BigDecimal -interface DefaultUnit : AbstractUnit { - fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal -} +interface BatchConvertResult + +@JvmInline +value class DefaultBatchConvertResult( + val value: BigDecimal, +) : BatchConvertResult + +@JvmInline +value class NumberBaseBatchConvertResult( + val value: String, +) : BatchConvertResult diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/ConverterResult.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/ConverterResult.kt new file mode 100644 index 00000000..dcf0e064 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/ConverterResult.kt @@ -0,0 +1,82 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter + +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import java.math.BigDecimal + +sealed class ConverterResult { + + sealed class Error : ConverterResult() { + data object Currency : Error() + + data object BadInput : Error() + + data object ConversionError : Error() + + data object DivideByZero : Error() + } + + data class Default( + val value: BigDecimal, + val calculation: BigDecimal, + ) : ConverterResult() + + data class NumberBase(val value: String) : ConverterResult() + + data class Time( + val negative: Boolean = false, + val day: BigDecimal = BigDecimal.ZERO, + val hour: BigDecimal = BigDecimal.ZERO, + val minute: BigDecimal = BigDecimal.ZERO, + val second: BigDecimal = BigDecimal.ZERO, + val millisecond: BigDecimal = BigDecimal.ZERO, + val microsecond: BigDecimal = BigDecimal.ZERO, + val nanosecond: BigDecimal = BigDecimal.ZERO, + val attosecond: BigDecimal = BigDecimal.ZERO, + ) : ConverterResult() + + data class FootInch( + val foot: BigDecimal, + val inch: BigDecimal, + ) : ConverterResult() { + companion object { + /** + * Creates an object for displaying formatted foot and inch output. Units are passed as objects so + * that changes in basic units don't require modifying the method. Also this method can't access + * units repository directly. + * + * @param input Input in feet. + * @param footUnit Foot unit [BasicUnit.Default]. + * @param inchUnit Inch unit [BasicUnit.Default]. + * @return Result where decimal places are converter into inches. + */ + fun fromBigDecimal( + input: BigDecimal, + footUnit: BasicUnit.Default, + inchUnit: BasicUnit.Default, + ): FootInch { + val (integral, fractional) = input.divideAndRemainder(BigDecimal.ONE) + return FootInch(integral, footUnit.convert(inchUnit, fractional)) + } + } + } + + data object Loading : ConverterResult() +} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitID.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitID.kt similarity index 99% rename from data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitID.kt rename to data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitID.kt index 2ba10d20..1abbf7bb 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitID.kt +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitID.kt @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.converter +@file:Suppress("ktlint:standard:property-naming") + +package app.myzel394.numberhub.data.converter /** * All UnitIDs. Long file. diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitSearchResultItem.kt similarity index 74% rename from data/model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt rename to data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitSearchResultItem.kt index a752aaa8..842bbc48 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitSearchResultItem.kt @@ -1,6 +1,6 @@ /* * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev + * Copyright (c) 2024 Elshan Agaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,45 +16,32 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.unit +package app.myzel394.numberhub.data.converter import android.content.Context -import com.sadellie.unitto.data.common.lev -import com.sadellie.unitto.data.common.normalizeSuperscript -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal +import app.myzel394.numberhub.data.common.lev +import app.myzel394.numberhub.data.common.normalizeSuperscript +import app.myzel394.numberhub.data.database.UnitsEntity +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit -interface AbstractUnit { - val id: String - val basicUnit: BigDecimal - val group: UnitGroup - val displayName: Int - val shortName: Int - val isFavorite: Boolean - val pairId: String? - val counter: Int +data class UnitSearchResultItem( + val basicUnit: BasicUnit, + val stats: UnitsEntity, + val conversion: BatchConvertResult?, +) - fun clone( - id: String = this.id, - basicUnit: BigDecimal = this.basicUnit, - group: UnitGroup = this.group, - displayName: Int = this.displayName, - shortName: Int = this.shortName, - isFavorite: Boolean = this.isFavorite, - pairId: String? = this.pairId, - counter: Int = this.counter, - ): AbstractUnit -} - -fun Sequence.filterByLev(stringA: String, context: Context): Sequence { +fun Sequence.filterByLev( + stringA: String, + context: Context, +): Sequence { val stringToCompare = stringA.trim().lowercase() // We don't need units where name is too different, half of the symbols is wrong in this situation val threshold: Int = stringToCompare.length / 2 // List of pair: Unit and it's levDist - val unitsWithDist = mutableListOf>() + val unitsWithDist = mutableListOf>() this.forEach { unit -> val unitShortName: String = context - .getString(unit.shortName) + .getString(unit.basicUnit.shortName) .lowercase() .normalizeSuperscript() /** @@ -67,7 +54,7 @@ fun Sequence.filterByLev(stringA: String, context: Context): Seque } val unitFullName: String = context - .getString(unit.displayName) + .getString(unit.basicUnit.displayName) .lowercase() .normalizeSuperscript() diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitsRepositoryImpl.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitsRepositoryImpl.kt new file mode 100644 index 00000000..8b897f9d --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/UnitsRepositoryImpl.kt @@ -0,0 +1,550 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2022-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter + +import android.content.Context +import android.util.Log +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.data.common.isGreaterThan +import app.myzel394.numberhub.data.common.isLessThan +import app.myzel394.numberhub.data.common.trimZeros +import app.myzel394.numberhub.data.converter.collections.accelerationCollection +import app.myzel394.numberhub.data.converter.collections.angleCollection +import app.myzel394.numberhub.data.converter.collections.areaCollection +import app.myzel394.numberhub.data.converter.collections.currencyCollection +import app.myzel394.numberhub.data.converter.collections.dataCollection +import app.myzel394.numberhub.data.converter.collections.dataTransferCollection +import app.myzel394.numberhub.data.converter.collections.electrostaticCapacitance +import app.myzel394.numberhub.data.converter.collections.energyCollection +import app.myzel394.numberhub.data.converter.collections.flowRateCollection +import app.myzel394.numberhub.data.converter.collections.fluxCollection +import app.myzel394.numberhub.data.converter.collections.forceCollection +import app.myzel394.numberhub.data.converter.collections.fuelConsumptionCollection +import app.myzel394.numberhub.data.converter.collections.lengthCollection +import app.myzel394.numberhub.data.converter.collections.luminanceCollection +import app.myzel394.numberhub.data.converter.collections.massCollection +import app.myzel394.numberhub.data.converter.collections.numberBaseCollection +import app.myzel394.numberhub.data.converter.collections.powerCollection +import app.myzel394.numberhub.data.converter.collections.prefixCollection +import app.myzel394.numberhub.data.converter.collections.pressureCollection +import app.myzel394.numberhub.data.converter.collections.speedCollection +import app.myzel394.numberhub.data.converter.collections.temperatureCollection +import app.myzel394.numberhub.data.converter.collections.timeCollection +import app.myzel394.numberhub.data.converter.collections.torqueCollection +import app.myzel394.numberhub.data.converter.collections.volumeCollection +import app.myzel394.numberhub.data.converter.remote.CurrencyApi +import app.myzel394.numberhub.data.database.CurrencyRatesDao +import app.myzel394.numberhub.data.database.CurrencyRatesEntity +import app.myzel394.numberhub.data.database.UnitsDao +import app.myzel394.numberhub.data.database.UnitsEntity +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import dagger.hilt.android.qualifiers.ApplicationContext +import io.github.sadellie.evaluatto.Expression +import io.github.sadellie.evaluatto.ExpressionException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.math.BigDecimal +import java.math.RoundingMode +import java.time.LocalDate +import javax.inject.Inject + +class UnitsRepositoryImpl @Inject constructor( + private val unitsDao: UnitsDao, + private val currencyRatesDao: CurrencyRatesDao, + @ApplicationContext private val mContext: Context, +) { + private val inMemory = lengthCollection + + currencyCollection + + massCollection + + speedCollection + + temperatureCollection + + areaCollection + + timeCollection + + volumeCollection + + dataCollection + + pressureCollection + + accelerationCollection + + energyCollection + + powerCollection + + angleCollection + + dataTransferCollection + + fluxCollection + + numberBaseCollection + + electrostaticCapacitance + + prefixCollection + + forceCollection + + torqueCollection + + flowRateCollection + + luminanceCollection + + fuelConsumptionCollection + + suspend fun getById(id: String): BasicUnit = withContext(Dispatchers.Default) { + return@withContext inMemory.first { it.id == id } + } + + suspend fun getPairId(id: String): String = withContext(Dispatchers.IO) { + val basedUnitPair = getUnitStats(id).pairedUnitId + if (basedUnitPair != null) return@withContext basedUnitPair + + val inMemoryUnit = inMemory.first { it.id == id } + val collection = inMemory.filter { it.group == inMemoryUnit.group } + + val pair = collection + .map { getById(it.id) to getUnitStats(it.id) } + .sortedByDescending { it.second.frequency } + .firstOrNull { it.second.isFavorite }?.first ?: collection.first() + + return@withContext pair.id + } + + suspend fun incrementCounter(id: String) = withContext(Dispatchers.IO) { + val basedUnit = unitsDao.getById(id) + + if (basedUnit == null) { + unitsDao.insertUnit( + UnitsEntity( + unitId = id, + frequency = 1, + ), + ) + } else { + unitsDao.insertUnit( + UnitsEntity( + unitId = basedUnit.unitId, + isFavorite = basedUnit.isFavorite, + pairedUnitId = basedUnit.pairedUnitId, + frequency = basedUnit.frequency + 1, + ), + ) + } + } + + suspend fun setPair( + id: String, + pairId: String, + ) = withContext(Dispatchers.IO) { + val basedUnit = unitsDao.getById(id) + + if (basedUnit == null) { + unitsDao.insertUnit( + UnitsEntity( + unitId = id, + pairedUnitId = pairId, + ), + ) + } else { + unitsDao.insertUnit( + UnitsEntity( + unitId = basedUnit.unitId, + isFavorite = basedUnit.isFavorite, + pairedUnitId = pairId, + frequency = basedUnit.frequency, + ), + ) + } + } + + suspend fun favorite(id: String) = withContext(Dispatchers.IO) { + val basedUnit = unitsDao.getById(id) + + if (basedUnit == null) { + unitsDao.insertUnit( + UnitsEntity( + unitId = id, + isFavorite = true, + ), + ) + } else { + unitsDao.insertUnit( + UnitsEntity( + unitId = basedUnit.unitId, + isFavorite = !basedUnit.isFavorite, + pairedUnitId = basedUnit.pairedUnitId, + frequency = basedUnit.frequency, + ), + ) + } + } + + suspend fun filterUnits( + query: String, + unitGroups: List, + favoritesOnly: Boolean, + sorting: UnitsListSorting, + ): Map> = withContext(Dispatchers.IO) { + return@withContext filterUnitCollections( + query = query, + unitGroups = unitGroups, + favoritesOnly = favoritesOnly, + sorting = sorting, + ) + .groupBy { it.basicUnit.group } + } + + suspend fun filterUnitsAndBatchConvert( + query: String, + unitGroup: UnitGroup, + favoritesOnly: Boolean, + sorting: UnitsListSorting, + unitFromId: String, + input: String?, + ): Map> = withContext(Dispatchers.IO) { + val units = filterUnitCollections( + query = query, + unitGroups = listOf(unitGroup), + favoritesOnly = favoritesOnly, + sorting = sorting, + ) + + if (input == null) { + return@withContext units.groupBy { it.basicUnit.group } + } + + val unitWithConversions = try { + when (unitGroup) { + UnitGroup.CURRENCY -> { + val inputBD = BigDecimal(input) + + val validCurrencyPairs = withContext(Dispatchers.IO) { + currencyRatesDao.getLatestRates(unitFromId) + } + .filter { it.pairUnitValue?.isGreaterThan(BigDecimal.ZERO) ?: false } + + val validIds = validCurrencyPairs.map { it.pairUnitId } + + units + .filter { it.basicUnit.id in validIds } + .map { unitTo -> + unitTo.basicUnit as BasicUnit.Default + val factor = validCurrencyPairs + .first { it.pairUnitId == unitTo.basicUnit.id } + .pairUnitValue + val conversion = inputBD.multiply(factor) + + unitTo.copy( + conversion = DefaultBatchConvertResult(conversion), + ) + } + } + + UnitGroup.NUMBER_BASE -> { + val unitFrom = getById(unitFromId) as BasicUnit.NumberBase + + units.map { unitTo -> + unitTo.basicUnit as BasicUnit.NumberBase + val conversion = unitFrom.convert(unitTo.basicUnit, input) + + unitTo.copy( + conversion = NumberBaseBatchConvertResult(conversion), + ) + } + } + + else -> { + val unitFrom = getById(unitFromId) as BasicUnit.Default + val inputBD = BigDecimal(input) + + units.map { unitTo -> + unitTo.basicUnit as BasicUnit.Default + val conversion = unitFrom.convert(unitTo.basicUnit, inputBD) + + unitTo.copy( + conversion = DefaultBatchConvertResult(conversion), + ) + } + } + } + } catch (e: Exception) { + Log.e("UnitsRepositoryImpl", "Failed to batch convert: $e") + units + } + + return@withContext unitWithConversions.groupBy { it.basicUnit.group } + } + + suspend fun convertDefault( + unitFromId: String, + unitToId: String, + value1: String, + value2: String, + formatTime: Boolean, + ): ConverterResult = withContext(Dispatchers.Default) { + val calculated: BigDecimal = try { + // Calculate expression in first text field + var calculated1 = Expression(value1.ifEmpty { Token.Digit._0 }).calculate() + + // Calculate expression in second text field + if (unitFromId == UnitID.foot) { + val calculatedInches = Expression(value2.ifEmpty { Token.Digit._0 }).calculate() + // turn inches into feet so that it all comes down to converting from feet only + val inches = getById(UnitID.inch) as BasicUnit.Default + val feet = getById(UnitID.foot) as BasicUnit.Default + val inchesConvertedToFeet = inches.convert(feet, calculatedInches) + + calculated1 += inchesConvertedToFeet + } + + calculated1 + } catch (e: ExpressionException.DivideByZero) { + return@withContext ConverterResult.Error.DivideByZero + } catch (e: Exception) { + return@withContext ConverterResult.Error.BadInput + } + + return@withContext try { + val unitFrom = getById(unitFromId) as BasicUnit.Default + val unitTo = getById(unitToId) as BasicUnit.Default + + when { + (unitFrom.group == UnitGroup.TIME) and (formatTime) -> + convertTime(unitFrom, calculated) + + unitTo.id == UnitID.foot -> + convertToFoot(unitFrom, unitTo, calculated) + + unitFrom.group == UnitGroup.CURRENCY -> + convertCurrencies(unitFromId, unitToId, calculated) + + else -> + convertDefault(unitFrom, unitTo, calculated) + } + } catch (e: Exception) { + ConverterResult.Error.ConversionError + } + } + + suspend fun convertNumberBase( + unitFromId: String, + unitToId: String, + value: String, + ): ConverterResult = withContext(Dispatchers.Default) { + return@withContext try { + val unitFrom = getById(unitFromId) as BasicUnit.NumberBase + val unitTo = getById(unitToId) as BasicUnit.NumberBase + val conversion = unitFrom.convert(unitTo, value) + + ConverterResult.NumberBase(conversion) + } catch (e: Exception) { + ConverterResult.Error.ConversionError + } + } + + private suspend fun getUnitStats(id: String): UnitsEntity = withContext(Dispatchers.IO) { + unitsDao.getById(id) ?: UnitsEntity(unitId = id) + } + + private fun convertDefault( + unitFrom: BasicUnit.Default, + unitTo: BasicUnit.Default, + value: BigDecimal, + ): ConverterResult.Default = ConverterResult.Default(unitFrom.convert(unitTo, value), value) + + internal fun convertTime( + unitFrom: BasicUnit.Default, + value: BigDecimal, + ): ConverterResult.Time { + val input = value.multiply(unitFrom.factor) + + val negative = input < BigDecimal.ZERO + val inputAbs = input.abs() + + if (inputAbs.isLessThan(attosecondBasicUnit)) { + return ConverterResult.Time( + negative = negative, + day = BigDecimal.ZERO, + hour = BigDecimal.ZERO, + minute = BigDecimal.ZERO, + second = BigDecimal.ZERO, + millisecond = BigDecimal.ZERO, + microsecond = BigDecimal.ZERO, + nanosecond = BigDecimal.ZERO, + attosecond = inputAbs, + ) + } + + if (inputAbs.isLessThan(nanosecondBasicUnit)) { + return ConverterResult.Time( + negative = negative, + day = BigDecimal.ZERO, + hour = BigDecimal.ZERO, + minute = BigDecimal.ZERO, + second = BigDecimal.ZERO, + millisecond = BigDecimal.ZERO, + microsecond = BigDecimal.ZERO, + nanosecond = BigDecimal.ZERO, + attosecond = inputAbs.trimZeros(), + ) + } + + // DAY + var division = inputAbs.divideAndRemainder(dayBasicUnit) + val day = division.component1().setScale(0, RoundingMode.HALF_EVEN) + var remainingSeconds = division.component2().setScale(0, RoundingMode.HALF_EVEN) + + division = remainingSeconds.divideAndRemainder(hourBasicUnit) + val hour = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(minuteBasicUnit) + val minute = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(secondBasicUnit) + val second = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(millisecondBasicUnit) + val millisecond = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(microsecondBasicUnit) + val microsecond = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(nanosecondBasicUnit) + val nanosecond = division.component1() + remainingSeconds = division.component2() + + val attosecond = remainingSeconds + + return ConverterResult.Time( + negative = negative, + day = day, + hour = hour, + minute = minute, + second = second, + millisecond = millisecond, + microsecond = microsecond, + nanosecond = nanosecond, + attosecond = attosecond, + ) + } + + private suspend fun convertToFoot( + unitFrom: BasicUnit.Default, + unitTo: BasicUnit.Default, + value: BigDecimal, + ): ConverterResult.FootInch = ConverterResult.FootInch.fromBigDecimal( + input = unitFrom.convert(unitTo, value), + footUnit = unitTo, + inchUnit = getById(UnitID.inch) as BasicUnit.Default, + ) + + private suspend fun convertCurrencies( + unitFromId: String, + unitToId: String, + value: BigDecimal, + ): ConverterResult = withContext(Dispatchers.IO) { + refreshCurrencyRates(unitFromId, unitToId) + + val latestRate = currencyRatesDao.getLatestRate(unitFromId, unitToId) + if (latestRate?.pairUnitValue == null) return@withContext ConverterResult.Error.Currency + + val conversion = value.multiply(latestRate.pairUnitValue) + + return@withContext ConverterResult.Default(conversion, value) + } + + private suspend fun filterUnitCollections( + query: String, + unitGroups: List, + favoritesOnly: Boolean, + sorting: UnitsListSorting, + ): Sequence = withContext(Dispatchers.IO) { + var units = inMemory + .filter { it.group in unitGroups } + .map { UnitSearchResultItem(it, getUnitStats(it.id), null) } + .asSequence() + + if (favoritesOnly) { + units = units.filter { it.stats.isFavorite } + } + + units = when (sorting) { + UnitsListSorting.USAGE -> units.sortedByDescending { it.stats.frequency } + UnitsListSorting.ALPHABETICAL -> units.sortedBy { mContext.getString(it.basicUnit.displayName) } + UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit.factor } + UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit.factor } + else -> units + } + + units = if (query.isEmpty()) { + units.sortedByDescending { it.stats.isFavorite } + } else { + units.filterByLev(query, mContext) + } + return@withContext units + } + + private suspend fun refreshCurrencyRates(unitFromId: String, unitToId: String) = withContext(Dispatchers.IO) { + val latestUpdateDate = currencyRatesDao.getLatestRateTimeStamp(unitFromId) + val currentDate = LocalDate.now().toEpochDay() + + if (latestUpdateDate != currentDate) { + // Need to update cache needed + try { + val conversions = CurrencyApi.service.getCurrencyPairs(unitFromId) + val rates = conversions.currency + .map { (pairId, pairValue) -> + CurrencyRatesEntity( + baseUnitId = unitFromId, + date = currentDate, + pairUnitId = pairId, + pairUnitValue = BigDecimal.valueOf(pairValue), + ) + } + currencyRatesDao.insertRates(rates) + } catch (e: Exception) { + Log.w("UnitsRepositoryImpl", "Updating currency rates failed: $e"); + // If fails, try to get the currency `unitToId` and calculate the rate + // example: + + val latestReverseData = currencyRatesDao.getLatestRate(unitToId, unitFromId); + + if (latestReverseData != null) { + val reverseRate = BigDecimal.ONE.divide(latestReverseData.pairUnitValue, 10, RoundingMode.HALF_EVEN) + + Log.d("UnitsRepositoryImpl", "Updated currency via reverse rate: $reverseRate"); + + currencyRatesDao.insertRates( + listOf( + CurrencyRatesEntity( + baseUnitId = unitFromId, + date = currentDate, + pairUnitId = unitToId, + pairUnitValue = reverseRate, + ), + ), + ) + } + } + } + } +} + +private val dayBasicUnit by lazy { BigDecimal("86400000000000000000000") } +private val hourBasicUnit by lazy { BigDecimal("3600000000000000000000") } +private val minuteBasicUnit by lazy { BigDecimal("60000000000000000000") } +private val secondBasicUnit by lazy { BigDecimal("1000000000000000000") } +private val millisecondBasicUnit by lazy { BigDecimal("1000000000000000") } +private val microsecondBasicUnit by lazy { BigDecimal("1000000000000") } +private val nanosecondBasicUnit by lazy { BigDecimal("1000000000") } +private val attosecondBasicUnit by lazy { BigDecimal("1") } diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Acceleration.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Acceleration.kt new file mode 100644 index 00000000..8c6865e1 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Acceleration.kt @@ -0,0 +1,53 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val accelerationCollection: List by lazy { + listOf( + NormalUnit(UnitID.attometer_per_square_second, BigDecimal("1"), UnitGroup.ACCELERATION, R.string.unit_attometer_per_square_second, R.string.unit_attometer_per_square_second_short), + NormalUnit(UnitID.femtometer_per_square_second, BigDecimal("1000"), UnitGroup.ACCELERATION, R.string.unit_femtometer_per_square_second, R.string.unit_femtometer_per_square_second_short), + NormalUnit(UnitID.picometer_per_square_second, BigDecimal("1000000"), UnitGroup.ACCELERATION, R.string.unit_picometer_per_square_second, R.string.unit_picometer_per_square_second_short), + NormalUnit(UnitID.nanometer_per_square_second, BigDecimal("1000000000"), UnitGroup.ACCELERATION, R.string.unit_nanometer_per_square_second, R.string.unit_nanometer_per_square_second_short), + NormalUnit(UnitID.micrometer_per_square_second, BigDecimal("1000000000000"), UnitGroup.ACCELERATION, R.string.unit_micrometer_per_square_second, R.string.unit_micrometer_per_square_second_short), + NormalUnit(UnitID.millimeter_per_square_second, BigDecimal("1000000000000000"), UnitGroup.ACCELERATION, R.string.unit_millimeter_per_square_second, R.string.unit_millimeter_per_square_second_short), + NormalUnit(UnitID.centimeter_per_square_second, BigDecimal("10000000000000000"), UnitGroup.ACCELERATION, R.string.unit_centimeter_per_square_second, R.string.unit_centimeter_per_square_second_short), + NormalUnit(UnitID.decimeter_per_square_second, BigDecimal("100000000000000000"), UnitGroup.ACCELERATION, R.string.unit_decimeter_per_square_second, R.string.unit_decimeter_per_square_second_short), + NormalUnit(UnitID.meter_per_square_second, BigDecimal("1000000000000000000"), UnitGroup.ACCELERATION, R.string.unit_meter_per_square_second, R.string.unit_meter_per_square_second_short), + NormalUnit(UnitID.kilometer_per_square_second, BigDecimal("1000000000000000000000"), UnitGroup.ACCELERATION, R.string.unit_kilometer_per_square_second, R.string.unit_kilometer_per_square_second_short), + NormalUnit(UnitID.dekameter_per_square_second, BigDecimal("10000000000000000000"), UnitGroup.ACCELERATION, R.string.unit_dekameter_per_square_second, R.string.unit_dekameter_per_square_second_short), + NormalUnit(UnitID.hectometer_per_square_second, BigDecimal("100000000000000000000"), UnitGroup.ACCELERATION, R.string.unit_hectometer_per_square_second, R.string.unit_hectometer_per_square_second_short), + NormalUnit(UnitID.gal, BigDecimal("10000000000000000"), UnitGroup.ACCELERATION, R.string.unit_gal, R.string.unit_gal_short), + NormalUnit(UnitID.mercury_surface_gravity, BigDecimal("3700000000000000000"), UnitGroup.ACCELERATION, R.string.unit_mercury_surface_gravity, R.string.unit_mercury_surface_gravity_short), + NormalUnit(UnitID.venus_surface_gravity, BigDecimal("8870000000000000000"), UnitGroup.ACCELERATION, R.string.unit_venus_surface_gravity, R.string.unit_venus_surface_gravity_short), + NormalUnit(UnitID.earth_surface_gravity, BigDecimal("9806550000000000000"), UnitGroup.ACCELERATION, R.string.unit_earth_surface_gravity, R.string.unit_earth_surface_gravity_short), + NormalUnit(UnitID.mars_surface_gravity, BigDecimal("3710000000000000000"), UnitGroup.ACCELERATION, R.string.unit_mars_surface_gravity, R.string.unit_mars_surface_gravity_short), + NormalUnit(UnitID.jupiter_surface_gravity, BigDecimal("24790000000000000000"), UnitGroup.ACCELERATION, R.string.unit_jupiter_surface_gravity, R.string.unit_jupiter_surface_gravity_short), + NormalUnit(UnitID.saturn_surface_gravity, BigDecimal("10440000000000000000"), UnitGroup.ACCELERATION, R.string.unit_saturn_surface_gravity, R.string.unit_saturn_surface_gravity_short), + NormalUnit(UnitID.uranus_surface_gravity, BigDecimal("8870000000000000000"), UnitGroup.ACCELERATION, R.string.unit_uranus_surface_gravity, R.string.unit_uranus_surface_gravity_short), + NormalUnit(UnitID.neptune_surface_gravity, BigDecimal("11150000000000000000"), UnitGroup.ACCELERATION, R.string.unit_neptune_surface_gravity, R.string.unit_neptune_surface_gravity_short), + NormalUnit(UnitID.sun_surface_gravity, BigDecimal("274000000000000000000"), UnitGroup.ACCELERATION, R.string.unit_sun_surface_gravity, R.string.unit_sun_surface_gravity_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Angle.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Angle.kt new file mode 100644 index 00000000..59dbe58b --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Angle.kt @@ -0,0 +1,37 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val angleCollection: List by lazy { + listOf( + NormalUnit(UnitID.angle_second, BigDecimal("1"), UnitGroup.ANGLE, R.string.unit_angle_second, R.string.unit_angle_second_short), + NormalUnit(UnitID.angle_minute, BigDecimal("60"), UnitGroup.ANGLE, R.string.unit_angle_minute, R.string.unit_angle_minute_short), + NormalUnit(UnitID.degree, BigDecimal("3600"), UnitGroup.ANGLE, R.string.unit_degree, R.string.unit_degree_short), + NormalUnit(UnitID.radian, BigDecimal("206264.8062471"), UnitGroup.ANGLE, R.string.unit_radian, R.string.unit_radian_short), + NormalUnit(UnitID.sextant, BigDecimal("216000"), UnitGroup.ANGLE, R.string.unit_sextant, R.string.unit_sextant_short), + NormalUnit(UnitID.turn, BigDecimal("1296000"), UnitGroup.ANGLE, R.string.unit_turn, R.string.unit_turn_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Area.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Area.kt new file mode 100644 index 00000000..44be791c --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Area.kt @@ -0,0 +1,45 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val areaCollection: List by lazy { + listOf( + NormalUnit(UnitID.cent, BigDecimal("6083246572000000000000000000000000"), UnitGroup.AREA, R.string.unit_cent, R.string.unit_cent_short), + NormalUnit(UnitID.acre, BigDecimal("60832465720000000000000000000000"), UnitGroup.AREA, R.string.unit_acre, R.string.unit_acre_short), + NormalUnit(UnitID.hectare, BigDecimal("150320296400000000000000000000000"), UnitGroup.AREA, R.string.unit_hectare, R.string.unit_hectare_short ), + NormalUnit(UnitID.square_foot, BigDecimal("1396521251000000000000000000"), UnitGroup.AREA, R.string.unit_square_foot, R.string.unit_square_foot_short), + NormalUnit(UnitID.square_mile, BigDecimal("38932778060000000000000000000000000"), UnitGroup.AREA, R.string.unit_square_mile, R.string.unit_square_mile_short), + NormalUnit(UnitID.square_yard, BigDecimal("12568691260000000000000000000"), UnitGroup.AREA, R.string.unit_square_yard, R.string.unit_square_yard_short), + NormalUnit(UnitID.square_inch, BigDecimal("9698064247000000000000000"), UnitGroup.AREA, R.string.unit_square_inch, R.string.unit_square_inch_short), + NormalUnit(UnitID.square_micrometer, BigDecimal("15032029640000000"), UnitGroup.AREA, R.string.unit_square_micrometer, R.string.unit_square_micrometer_short), + NormalUnit(UnitID.square_millimeter, BigDecimal("15032029640000000000000"), UnitGroup.AREA, R.string.unit_square_millimeter, R.string.unit_square_millimeter_short), + NormalUnit(UnitID.square_centimeter, BigDecimal("1503202964000000000000000"), UnitGroup.AREA, R.string.unit_square_centimeter, R.string.unit_square_centimeter_short), + NormalUnit(UnitID.square_decimeter, BigDecimal("150320296400000000000000000"), UnitGroup.AREA, R.string.unit_square_decimeter, R.string.unit_square_decimeter_short), + NormalUnit(UnitID.square_meter, BigDecimal("15032029640000000000000000000"), UnitGroup.AREA, R.string.unit_square_meter, R.string.unit_square_meter_short), + NormalUnit(UnitID.square_kilometer, BigDecimal("15032029640000000000000000000000000"), UnitGroup.AREA, R.string.unit_square_kilometer, R.string.unit_square_kilometer_short), + NormalUnit(UnitID.electron_cross_section, BigDecimal("1"), UnitGroup.AREA, R.string.unit_electron_cross_section, R.string.unit_electron_cross_section_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Currency.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Currency.kt new file mode 100644 index 00000000..82a06101 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Currency.kt @@ -0,0 +1,239 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val currencyCollection: List by lazy { + listOf( + NormalUnit(UnitID.currency_1inch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_1inch, R.string.unit_currency_1inch_short, backward = true), + NormalUnit(UnitID.currency_ada, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ada, R.string.unit_currency_ada_short, backward = true), + NormalUnit(UnitID.currency_aed, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aed, R.string.unit_currency_aed_short, backward = true), + NormalUnit(UnitID.currency_afn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_afn, R.string.unit_currency_afn_short, backward = true), + NormalUnit(UnitID.currency_algo, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_algo, R.string.unit_currency_algo_short, backward = true), + NormalUnit(UnitID.currency_all, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_all, R.string.unit_currency_all_short, backward = true), + NormalUnit(UnitID.currency_amd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_amd, R.string.unit_currency_amd_short, backward = true), + NormalUnit(UnitID.currency_ang, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ang, R.string.unit_currency_ang_short, backward = true), + NormalUnit(UnitID.currency_aoa, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aoa, R.string.unit_currency_aoa_short, backward = true), + NormalUnit(UnitID.currency_ars, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ars, R.string.unit_currency_ars_short, backward = true), + NormalUnit(UnitID.currency_atom, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_atom, R.string.unit_currency_atom_short, backward = true), + NormalUnit(UnitID.currency_aud, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aud, R.string.unit_currency_aud_short, backward = true), + NormalUnit(UnitID.currency_avax, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_avax, R.string.unit_currency_avax_short, backward = true), + NormalUnit(UnitID.currency_awg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_awg, R.string.unit_currency_awg_short, backward = true), + NormalUnit(UnitID.currency_azn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_azn, R.string.unit_currency_azn_short, backward = true), + NormalUnit(UnitID.currency_bam, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bam, R.string.unit_currency_bam_short, backward = true), + NormalUnit(UnitID.currency_bbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bbd, R.string.unit_currency_bbd_short, backward = true), + NormalUnit(UnitID.currency_bch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bch, R.string.unit_currency_bch_short, backward = true), + NormalUnit(UnitID.currency_bdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bdt, R.string.unit_currency_bdt_short, backward = true), + NormalUnit(UnitID.currency_bgn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bgn, R.string.unit_currency_bgn_short, backward = true), + NormalUnit(UnitID.currency_bhd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bhd, R.string.unit_currency_bhd_short, backward = true), + NormalUnit(UnitID.currency_bif, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bif, R.string.unit_currency_bif_short, backward = true), + NormalUnit(UnitID.currency_bmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bmd, R.string.unit_currency_bmd_short, backward = true), + NormalUnit(UnitID.currency_bnb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnb, R.string.unit_currency_bnb_short, backward = true), + NormalUnit(UnitID.currency_bnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnd, R.string.unit_currency_bnd_short, backward = true), + NormalUnit(UnitID.currency_bob, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bob, R.string.unit_currency_bob_short, backward = true), + NormalUnit(UnitID.currency_brl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_brl, R.string.unit_currency_brl_short, backward = true), + NormalUnit(UnitID.currency_bsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bsd, R.string.unit_currency_bsd_short, backward = true), + NormalUnit(UnitID.currency_btc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btc, R.string.unit_currency_btc_short, backward = true), + NormalUnit(UnitID.currency_btn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btn, R.string.unit_currency_btn_short, backward = true), + NormalUnit(UnitID.currency_busd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_busd, R.string.unit_currency_busd_short, backward = true), + NormalUnit(UnitID.currency_bwp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bwp, R.string.unit_currency_bwp_short, backward = true), + NormalUnit(UnitID.currency_byn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byn, R.string.unit_currency_byn_short, backward = true), + NormalUnit(UnitID.currency_byr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byr, R.string.unit_currency_byr_short, backward = true), + NormalUnit(UnitID.currency_bzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bzd, R.string.unit_currency_bzd_short, backward = true), + NormalUnit(UnitID.currency_cad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cad, R.string.unit_currency_cad_short, backward = true), + NormalUnit(UnitID.currency_cdf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cdf, R.string.unit_currency_cdf_short, backward = true), + NormalUnit(UnitID.currency_chf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chf, R.string.unit_currency_chf_short, backward = true), + NormalUnit(UnitID.currency_chz, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chz, R.string.unit_currency_chz_short, backward = true), + NormalUnit(UnitID.currency_clf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clf, R.string.unit_currency_clf_short, backward = true), + NormalUnit(UnitID.currency_clp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clp, R.string.unit_currency_clp_short, backward = true), + NormalUnit(UnitID.currency_cny, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cny, R.string.unit_currency_cny_short, backward = true), + NormalUnit(UnitID.currency_cop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cop, R.string.unit_currency_cop_short, backward = true), + NormalUnit(UnitID.currency_crc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_crc, R.string.unit_currency_crc_short, backward = true), + NormalUnit(UnitID.currency_cro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cro, R.string.unit_currency_cro_short, backward = true), + NormalUnit(UnitID.currency_cuc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cuc, R.string.unit_currency_cuc_short, backward = true), + NormalUnit(UnitID.currency_cup, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cup, R.string.unit_currency_cup_short, backward = true), + NormalUnit(UnitID.currency_cve, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cve, R.string.unit_currency_cve_short, backward = true), + NormalUnit(UnitID.currency_czk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_czk, R.string.unit_currency_czk_short, backward = true), + NormalUnit(UnitID.currency_dai, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dai, R.string.unit_currency_dai_short, backward = true), + NormalUnit(UnitID.currency_djf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_djf, R.string.unit_currency_djf_short, backward = true), + NormalUnit(UnitID.currency_dkk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dkk, R.string.unit_currency_dkk_short, backward = true), + NormalUnit(UnitID.currency_doge, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_doge, R.string.unit_currency_doge_short, backward = true), + NormalUnit(UnitID.currency_dop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dop, R.string.unit_currency_dop_short, backward = true), + NormalUnit(UnitID.currency_dot, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dot, R.string.unit_currency_dot_short, backward = true), + NormalUnit(UnitID.currency_dzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dzd, R.string.unit_currency_dzd_short, backward = true), + NormalUnit(UnitID.currency_egld, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egld, R.string.unit_currency_egld_short, backward = true), + NormalUnit(UnitID.currency_egp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egp, R.string.unit_currency_egp_short, backward = true), + NormalUnit(UnitID.currency_enj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_enj, R.string.unit_currency_enj_short, backward = true), + NormalUnit(UnitID.currency_ern, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ern, R.string.unit_currency_ern_short, backward = true), + NormalUnit(UnitID.currency_etb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etb, R.string.unit_currency_etb_short, backward = true), + NormalUnit(UnitID.currency_etc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etc, R.string.unit_currency_etc_short, backward = true), + NormalUnit(UnitID.currency_eth, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eth, R.string.unit_currency_eth_short, backward = true), + NormalUnit(UnitID.currency_eur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eur, R.string.unit_currency_eur_short, backward = true), + NormalUnit(UnitID.currency_fil, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fil, R.string.unit_currency_fil_short, backward = true), + NormalUnit(UnitID.currency_fjd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fjd, R.string.unit_currency_fjd_short, backward = true), + NormalUnit(UnitID.currency_fkp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fkp, R.string.unit_currency_fkp_short, backward = true), + NormalUnit(UnitID.currency_ftt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ftt, R.string.unit_currency_ftt_short, backward = true), + NormalUnit(UnitID.currency_gbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gbp, R.string.unit_currency_gbp_short, backward = true), + NormalUnit(UnitID.currency_gel, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gel, R.string.unit_currency_gel_short, backward = true), + NormalUnit(UnitID.currency_ggp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ggp, R.string.unit_currency_ggp_short, backward = true), + NormalUnit(UnitID.currency_ghs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ghs, R.string.unit_currency_ghs_short, backward = true), + NormalUnit(UnitID.currency_gip, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gip, R.string.unit_currency_gip_short, backward = true), + NormalUnit(UnitID.currency_gmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gmd, R.string.unit_currency_gmd_short, backward = true), + NormalUnit(UnitID.currency_gnf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gnf, R.string.unit_currency_gnf_short, backward = true), + NormalUnit(UnitID.currency_grt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_grt, R.string.unit_currency_grt_short, backward = true), + NormalUnit(UnitID.currency_gtq, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gtq, R.string.unit_currency_gtq_short, backward = true), + NormalUnit(UnitID.currency_gyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gyd, R.string.unit_currency_gyd_short, backward = true), + NormalUnit(UnitID.currency_hkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hkd, R.string.unit_currency_hkd_short, backward = true), + NormalUnit(UnitID.currency_hnl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hnl, R.string.unit_currency_hnl_short, backward = true), + NormalUnit(UnitID.currency_hrk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hrk, R.string.unit_currency_hrk_short, backward = true), + NormalUnit(UnitID.currency_htg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_htg, R.string.unit_currency_htg_short, backward = true), + NormalUnit(UnitID.currency_huf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_huf, R.string.unit_currency_huf_short, backward = true), + NormalUnit(UnitID.currency_icp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_icp, R.string.unit_currency_icp_short, backward = true), + NormalUnit(UnitID.currency_idr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_idr, R.string.unit_currency_idr_short, backward = true), + NormalUnit(UnitID.currency_ils, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ils, R.string.unit_currency_ils_short, backward = true), + NormalUnit(UnitID.currency_imp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_imp, R.string.unit_currency_imp_short, backward = true), + NormalUnit(UnitID.currency_inj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inj, R.string.unit_currency_inj_short, backward = true), + NormalUnit(UnitID.currency_inr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inr, R.string.unit_currency_inr_short, backward = true), + NormalUnit(UnitID.currency_iqd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_iqd, R.string.unit_currency_iqd_short, backward = true), + NormalUnit(UnitID.currency_irr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_irr, R.string.unit_currency_irr_short, backward = true), + NormalUnit(UnitID.currency_isk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_isk, R.string.unit_currency_isk_short, backward = true), + NormalUnit(UnitID.currency_jep, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jep, R.string.unit_currency_jep_short, backward = true), + NormalUnit(UnitID.currency_jmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jmd, R.string.unit_currency_jmd_short, backward = true), + NormalUnit(UnitID.currency_jod, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jod, R.string.unit_currency_jod_short, backward = true), + NormalUnit(UnitID.currency_jpy, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jpy, R.string.unit_currency_jpy_short, backward = true), + NormalUnit(UnitID.currency_kes, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kes, R.string.unit_currency_kes_short, backward = true), + NormalUnit(UnitID.currency_kgs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kgs, R.string.unit_currency_kgs_short, backward = true), + NormalUnit(UnitID.currency_khr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_khr, R.string.unit_currency_khr_short, backward = true), + NormalUnit(UnitID.currency_kmf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kmf, R.string.unit_currency_kmf_short, backward = true), + NormalUnit(UnitID.currency_kpw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kpw, R.string.unit_currency_kpw_short, backward = true), + NormalUnit(UnitID.currency_krw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_krw, R.string.unit_currency_krw_short, backward = true), + NormalUnit(UnitID.currency_ksm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ksm, R.string.unit_currency_ksm_short, backward = true), + NormalUnit(UnitID.currency_kwd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kwd, R.string.unit_currency_kwd_short, backward = true), + NormalUnit(UnitID.currency_kyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kyd, R.string.unit_currency_kyd_short, backward = true), + NormalUnit(UnitID.currency_kzt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kzt, R.string.unit_currency_kzt_short, backward = true), + NormalUnit(UnitID.currency_lak, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lak, R.string.unit_currency_lak_short, backward = true), + NormalUnit(UnitID.currency_lbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lbp, R.string.unit_currency_lbp_short, backward = true), + NormalUnit(UnitID.currency_link, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_link, R.string.unit_currency_link_short, backward = true), + NormalUnit(UnitID.currency_lkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lkr, R.string.unit_currency_lkr_short, backward = true), + NormalUnit(UnitID.currency_lrd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lrd, R.string.unit_currency_lrd_short, backward = true), + NormalUnit(UnitID.currency_lsl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lsl, R.string.unit_currency_lsl_short, backward = true), + NormalUnit(UnitID.currency_ltc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltc, R.string.unit_currency_ltc_short, backward = true), + NormalUnit(UnitID.currency_ltl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltl, R.string.unit_currency_ltl_short, backward = true), + NormalUnit(UnitID.currency_luna, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_luna, R.string.unit_currency_luna_short, backward = true), + NormalUnit(UnitID.currency_lvl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lvl, R.string.unit_currency_lvl_short, backward = true), + NormalUnit(UnitID.currency_lyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lyd, R.string.unit_currency_lyd_short, backward = true), + NormalUnit(UnitID.currency_mad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mad, R.string.unit_currency_mad_short, backward = true), + NormalUnit(UnitID.currency_matic, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_matic, R.string.unit_currency_matic_short, backward = true), + NormalUnit(UnitID.currency_mdl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mdl, R.string.unit_currency_mdl_short, backward = true), + NormalUnit(UnitID.currency_mga, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mga, R.string.unit_currency_mga_short, backward = true), + NormalUnit(UnitID.currency_mkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mkd, R.string.unit_currency_mkd_short, backward = true), + NormalUnit(UnitID.currency_mmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mmk, R.string.unit_currency_mmk_short, backward = true), + NormalUnit(UnitID.currency_mnt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mnt, R.string.unit_currency_mnt_short, backward = true), + NormalUnit(UnitID.currency_mop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mop, R.string.unit_currency_mop_short, backward = true), + NormalUnit(UnitID.currency_mro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mro, R.string.unit_currency_mro_short, backward = true), + NormalUnit(UnitID.currency_mur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mur, R.string.unit_currency_mur_short, backward = true), + NormalUnit(UnitID.currency_mvr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mvr, R.string.unit_currency_mvr_short, backward = true), + NormalUnit(UnitID.currency_mwk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mwk, R.string.unit_currency_mwk_short, backward = true), + NormalUnit(UnitID.currency_mxn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mxn, R.string.unit_currency_mxn_short, backward = true), + NormalUnit(UnitID.currency_myr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_myr, R.string.unit_currency_myr_short, backward = true), + NormalUnit(UnitID.currency_mzn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mzn, R.string.unit_currency_mzn_short, backward = true), + NormalUnit(UnitID.currency_nad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nad, R.string.unit_currency_nad_short, backward = true), + NormalUnit(UnitID.currency_ngn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ngn, R.string.unit_currency_ngn_short, backward = true), + NormalUnit(UnitID.currency_nio, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nio, R.string.unit_currency_nio_short, backward = true), + NormalUnit(UnitID.currency_nok, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nok, R.string.unit_currency_nok_short, backward = true), + NormalUnit(UnitID.currency_npr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_npr, R.string.unit_currency_npr_short, backward = true), + NormalUnit(UnitID.currency_nzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nzd, R.string.unit_currency_nzd_short, backward = true), + NormalUnit(UnitID.currency_omr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_omr, R.string.unit_currency_omr_short, backward = true), + NormalUnit(UnitID.currency_one, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_one, R.string.unit_currency_one_short, backward = true), + NormalUnit(UnitID.currency_pab, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pab, R.string.unit_currency_pab_short, backward = true), + NormalUnit(UnitID.currency_pen, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pen, R.string.unit_currency_pen_short, backward = true), + NormalUnit(UnitID.currency_pgk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pgk, R.string.unit_currency_pgk_short, backward = true), + NormalUnit(UnitID.currency_php, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_php, R.string.unit_currency_php_short, backward = true), + NormalUnit(UnitID.currency_pkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pkr, R.string.unit_currency_pkr_short, backward = true), + NormalUnit(UnitID.currency_pln, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pln, R.string.unit_currency_pln_short, backward = true), + NormalUnit(UnitID.currency_pyg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pyg, R.string.unit_currency_pyg_short, backward = true), + NormalUnit(UnitID.currency_qar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_qar, R.string.unit_currency_qar_short, backward = true), + NormalUnit(UnitID.currency_ron, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ron, R.string.unit_currency_ron_short, backward = true), + NormalUnit(UnitID.currency_rsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rsd, R.string.unit_currency_rsd_short, backward = true), + NormalUnit(UnitID.currency_rub, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rub, R.string.unit_currency_rub_short, backward = true), + NormalUnit(UnitID.currency_rwf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rwf, R.string.unit_currency_rwf_short, backward = true), + NormalUnit(UnitID.currency_sar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sar, R.string.unit_currency_sar_short, backward = true), + NormalUnit(UnitID.currency_sbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sbd, R.string.unit_currency_sbd_short, backward = true), + NormalUnit(UnitID.currency_scr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_scr, R.string.unit_currency_scr_short, backward = true), + NormalUnit(UnitID.currency_sdg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sdg, R.string.unit_currency_sdg_short, backward = true), + NormalUnit(UnitID.currency_sek, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sek, R.string.unit_currency_sek_short, backward = true), + NormalUnit(UnitID.currency_sgd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sgd, R.string.unit_currency_sgd_short, backward = true), + NormalUnit(UnitID.currency_shib, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shib, R.string.unit_currency_shib_short, backward = true), + NormalUnit(UnitID.currency_shp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shp, R.string.unit_currency_shp_short, backward = true), + NormalUnit(UnitID.currency_sll, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sll, R.string.unit_currency_sll_short, backward = true), + NormalUnit(UnitID.currency_sol, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sol, R.string.unit_currency_sol_short, backward = true), + NormalUnit(UnitID.currency_sos, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sos, R.string.unit_currency_sos_short, backward = true), + NormalUnit(UnitID.currency_srd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_srd, R.string.unit_currency_srd_short, backward = true), + NormalUnit(UnitID.currency_std, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_std, R.string.unit_currency_std_short, backward = true), + NormalUnit(UnitID.currency_svc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_svc, R.string.unit_currency_svc_short, backward = true), + NormalUnit(UnitID.currency_syp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_syp, R.string.unit_currency_syp_short, backward = true), + NormalUnit(UnitID.currency_szl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_szl, R.string.unit_currency_szl_short, backward = true), + NormalUnit(UnitID.currency_thb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_thb, R.string.unit_currency_thb_short, backward = true), + NormalUnit(UnitID.currency_theta, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_theta, R.string.unit_currency_theta_short, backward = true), + NormalUnit(UnitID.currency_tjs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tjs, R.string.unit_currency_tjs_short, backward = true), + NormalUnit(UnitID.currency_tmt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tmt, R.string.unit_currency_tmt_short, backward = true), + NormalUnit(UnitID.currency_tnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tnd, R.string.unit_currency_tnd_short, backward = true), + NormalUnit(UnitID.currency_top, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_top, R.string.unit_currency_top_short, backward = true), + NormalUnit(UnitID.currency_trx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_trx, R.string.unit_currency_trx_short, backward = true), + NormalUnit(UnitID.currency_try, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_try, R.string.unit_currency_try_short, backward = true), + NormalUnit(UnitID.currency_ttd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ttd, R.string.unit_currency_ttd_short, backward = true), + NormalUnit(UnitID.currency_twd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_twd, R.string.unit_currency_twd_short, backward = true), + NormalUnit(UnitID.currency_tzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tzs, R.string.unit_currency_tzs_short, backward = true), + NormalUnit(UnitID.currency_uah, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uah, R.string.unit_currency_uah_short, backward = true), + NormalUnit(UnitID.currency_ugx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ugx, R.string.unit_currency_ugx_short, backward = true), + NormalUnit(UnitID.currency_uni, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uni, R.string.unit_currency_uni_short, backward = true), + NormalUnit(UnitID.currency_usd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usd, R.string.unit_currency_usd_short, backward = true), + NormalUnit(UnitID.currency_usdc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdc, R.string.unit_currency_usdc_short, backward = true), + NormalUnit(UnitID.currency_usdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdt, R.string.unit_currency_usdt_short, backward = true), + NormalUnit(UnitID.currency_uyu, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uyu, R.string.unit_currency_uyu_short, backward = true), + NormalUnit(UnitID.currency_uzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uzs, R.string.unit_currency_uzs_short, backward = true), + NormalUnit(UnitID.currency_vef, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vef, R.string.unit_currency_vef_short, backward = true), + NormalUnit(UnitID.currency_vet, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vet, R.string.unit_currency_vet_short, backward = true), + NormalUnit(UnitID.currency_vnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vnd, R.string.unit_currency_vnd_short, backward = true), + NormalUnit(UnitID.currency_vuv, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vuv, R.string.unit_currency_vuv_short, backward = true), + NormalUnit(UnitID.currency_wbtc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wbtc, R.string.unit_currency_wbtc_short, backward = true), + NormalUnit(UnitID.currency_wst, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wst, R.string.unit_currency_wst_short, backward = true), + NormalUnit(UnitID.currency_xaf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xaf, R.string.unit_currency_xaf_short, backward = true), + NormalUnit(UnitID.currency_xag, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xag, R.string.unit_currency_xag_short, backward = true), + NormalUnit(UnitID.currency_xau, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xau, R.string.unit_currency_xau_short, backward = true), + NormalUnit(UnitID.currency_xcd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xcd, R.string.unit_currency_xcd_short, backward = true), + NormalUnit(UnitID.currency_xdr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xdr, R.string.unit_currency_xdr_short, backward = true), + NormalUnit(UnitID.currency_xlm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xlm, R.string.unit_currency_xlm_short, backward = true), + NormalUnit(UnitID.currency_xmr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xmr, R.string.unit_currency_xmr_short, backward = true), + NormalUnit(UnitID.currency_xof, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xof, R.string.unit_currency_xof_short, backward = true), + NormalUnit(UnitID.currency_xpf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xpf, R.string.unit_currency_xpf_short, backward = true), + NormalUnit(UnitID.currency_xrp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xrp, R.string.unit_currency_xrp_short, backward = true), + NormalUnit(UnitID.currency_yer, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_yer, R.string.unit_currency_yer_short, backward = true), + NormalUnit(UnitID.currency_zar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zar, R.string.unit_currency_zar_short, backward = true), + NormalUnit(UnitID.currency_zmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmk, R.string.unit_currency_zmk_short, backward = true), + NormalUnit(UnitID.currency_zmw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmw, R.string.unit_currency_zmw_short, backward = true), + NormalUnit(UnitID.currency_zwl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zwl, R.string.unit_currency_zwl_short, backward = true), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Data.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Data.kt new file mode 100644 index 00000000..0e77ea84 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Data.kt @@ -0,0 +1,51 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val dataCollection: List by lazy { + listOf( + NormalUnit(UnitID.bit, BigDecimal("1"), UnitGroup.DATA, R.string.unit_bit, R.string.unit_bit_short), + NormalUnit(UnitID.kibibit, BigDecimal("1024"), UnitGroup.DATA, R.string.unit_kibibit, R.string.unit_kibibit_short), + NormalUnit(UnitID.kilobit, BigDecimal("1000"), UnitGroup.DATA, R.string.unit_kilobit, R.string.unit_kilobit_short), + NormalUnit(UnitID.megabit, BigDecimal("1000000"), UnitGroup.DATA, R.string.unit_megabit, R.string.unit_megabit_short), + NormalUnit(UnitID.mebibit, BigDecimal("1048576"), UnitGroup.DATA, R.string.unit_mebibit, R.string.unit_mebibit_short), + NormalUnit(UnitID.gigabit, BigDecimal("1000000000"), UnitGroup.DATA, R.string.unit_gigabit, R.string.unit_gigabit_short), + NormalUnit(UnitID.gibibit, BigDecimal("1073741824"), UnitGroup.DATA, R.string.unit_gibibit, R.string.unit_gibibit_short), + NormalUnit(UnitID.terabit, BigDecimal("1000000000000"), UnitGroup.DATA, R.string.unit_terabit, R.string.unit_terabit_short), + NormalUnit(UnitID.petabit, BigDecimal("1000000000000000"), UnitGroup.DATA, R.string.unit_petabit, R.string.unit_petabit_short), + NormalUnit(UnitID.exabit, BigDecimal("1000000000000000000"), UnitGroup.DATA, R.string.unit_exabit, R.string.unit_exabit_short), + NormalUnit(UnitID.byte, BigDecimal("8"), UnitGroup.DATA, R.string.unit_byte, R.string.unit_byte_short), + NormalUnit(UnitID.kibibyte, BigDecimal("8192"), UnitGroup.DATA, R.string.unit_kibibyte, R.string.unit_kibibyte_short), + NormalUnit(UnitID.kilobyte, BigDecimal("8000"), UnitGroup.DATA, R.string.unit_kilobyte, R.string.unit_kilobyte_short), + NormalUnit(UnitID.megabyte, BigDecimal("8000000"), UnitGroup.DATA, R.string.unit_megabyte, R.string.unit_megabyte_short), + NormalUnit(UnitID.mebibyte, BigDecimal("8388608"), UnitGroup.DATA, R.string.unit_mebibyte, R.string.unit_mebibyte_short), + NormalUnit(UnitID.gigabyte, BigDecimal("8000000000"), UnitGroup.DATA, R.string.unit_gigabyte, R.string.unit_gigabyte_short), + NormalUnit(UnitID.gibibyte, BigDecimal("8589934592"), UnitGroup.DATA, R.string.unit_gibibyte, R.string.unit_gibibyte_short), + NormalUnit(UnitID.terabyte, BigDecimal("8000000000000"), UnitGroup.DATA, R.string.unit_terabyte, R.string.unit_terabyte_short), + NormalUnit(UnitID.petabyte, BigDecimal("8000000000000000"), UnitGroup.DATA, R.string.unit_petabyte, R.string.unit_petabyte_short), + NormalUnit(UnitID.exabyte, BigDecimal("8000000000000000000"), UnitGroup.DATA, R.string.unit_exabyte, R.string.unit_exabyte_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/DataTransfer.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/DataTransfer.kt new file mode 100644 index 00000000..d78e7e21 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/DataTransfer.kt @@ -0,0 +1,51 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val dataTransferCollection: List by lazy { + listOf( + NormalUnit(UnitID.bit_per_second, BigDecimal("1"), UnitGroup.DATA_TRANSFER, R.string.unit_bit_per_second, R.string.unit_bit_per_second_short), + NormalUnit(UnitID.kibibit_per_second, BigDecimal("1024"), UnitGroup.DATA_TRANSFER, R.string.unit_kibibit_per_second, R.string.unit_kibibit_per_second_short), + NormalUnit(UnitID.kilobit_per_second, BigDecimal("1000"), UnitGroup.DATA_TRANSFER, R.string.unit_kilobit_per_second, R.string.unit_kilobit_per_second_short), + NormalUnit(UnitID.megabit_per_second, BigDecimal("1000000"), UnitGroup.DATA_TRANSFER, R.string.unit_megabit_per_second, R.string.unit_megabit_per_second_short), + NormalUnit(UnitID.mebibit_per_second, BigDecimal("1048576"), UnitGroup.DATA_TRANSFER, R.string.unit_mebibit_per_second, R.string.unit_mebibit_per_second_short), + NormalUnit(UnitID.gigabit_per_second, BigDecimal("1000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_gigabit_per_second, R.string.unit_gigabit_per_second_short), + NormalUnit(UnitID.gibibit_per_second, BigDecimal("1073741824"), UnitGroup.DATA_TRANSFER, R.string.unit_gibibit_per_second, R.string.unit_gibibit_per_second_short), + NormalUnit(UnitID.terabit_per_second, BigDecimal("1000000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_terabit_per_second, R.string.unit_terabit_per_second_short), + NormalUnit(UnitID.petabit_per_second, BigDecimal("1000000000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_petabit_per_second, R.string.unit_petabit_per_second_short), + NormalUnit(UnitID.exabit_per_second, BigDecimal("1000000000000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_exabit_per_second, R.string.unit_exabit_per_second_short), + NormalUnit(UnitID.byte_per_second, BigDecimal("8"), UnitGroup.DATA_TRANSFER, R.string.unit_byte_per_second, R.string.unit_byte_per_second_short), + NormalUnit(UnitID.kibibyte_per_second, BigDecimal("8192"), UnitGroup.DATA_TRANSFER, R.string.unit_kibibyte_per_second, R.string.unit_kibibyte_per_second_short), + NormalUnit(UnitID.kilobyte_per_second, BigDecimal("8000"), UnitGroup.DATA_TRANSFER, R.string.unit_kilobyte_per_second, R.string.unit_kilobyte_per_second_short), + NormalUnit(UnitID.megabyte_per_second, BigDecimal("8000000"), UnitGroup.DATA_TRANSFER, R.string.unit_megabyte_per_second, R.string.unit_megabyte_per_second_short), + NormalUnit(UnitID.mebibyte_per_second, BigDecimal("8388608"), UnitGroup.DATA_TRANSFER, R.string.unit_mebibyte_per_second, R.string.unit_mebibyte_per_second_short), + NormalUnit(UnitID.gigabyte_per_second, BigDecimal("8000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_gigabyte_per_second, R.string.unit_gigabyte_per_second_short), + NormalUnit(UnitID.gibibyte_per_second, BigDecimal("8589934592"), UnitGroup.DATA_TRANSFER, R.string.unit_gibibyte_per_second, R.string.unit_gibibyte_per_second_short), + NormalUnit(UnitID.terabyte_per_second, BigDecimal("8000000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_terabyte_per_second, R.string.unit_terabyte_per_second_short), + NormalUnit(UnitID.petabyte_per_second, BigDecimal("8000000000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_petabyte_per_second, R.string.unit_petabyte_per_second_short), + NormalUnit(UnitID.exabyte_per_second, BigDecimal("8000000000000000000"), UnitGroup.DATA_TRANSFER, R.string.unit_exabyte_per_second, R.string.unit_exabyte_per_second_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/ElectrostaticCapacitance.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/ElectrostaticCapacitance.kt new file mode 100644 index 00000000..2867086e --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/ElectrostaticCapacitance.kt @@ -0,0 +1,43 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val electrostaticCapacitance: List by lazy { + listOf( + NormalUnit(UnitID.attofarad, BigDecimal("1"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_attofarad, R.string.unit_attofarad_short), + NormalUnit(UnitID.picofarad, BigDecimal("1000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_picofarad, R.string.unit_picofarad_short), + NormalUnit(UnitID.statfarad, BigDecimal("1112650.0561"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_statfarad, R.string.unit_statfarad_short), + NormalUnit(UnitID.nanofarad, BigDecimal("1000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_nanofarad, R.string.unit_nanofarad_short), + NormalUnit(UnitID.microfarad, BigDecimal("1000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_microfarad, R.string.unit_microfarad_short), + NormalUnit(UnitID.millifarad, BigDecimal("1000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_millifarad, R.string.unit_millifarad_short), + NormalUnit(UnitID.farad, BigDecimal("1000000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_farad, R.string.unit_farad_short), + NormalUnit(UnitID.kilofarad, BigDecimal("1000000000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_kilofarad, R.string.unit_kilofarad_short), + NormalUnit(UnitID.megafarad, BigDecimal("1000000000000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_megafarad, R.string.unit_megafarad_short), + NormalUnit(UnitID.gigafarad, BigDecimal("1000000000000000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_gigafarad, R.string.unit_gigafarad_short), + NormalUnit(UnitID.petafarad, BigDecimal("1000000000000000000000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_petafarad, R.string.unit_petafarad_short), + NormalUnit(UnitID.exafarad, BigDecimal("1000000000000000000000000000000000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_exafarad, R.string.unit_exafarad_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Energy.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Energy.kt new file mode 100644 index 00000000..98a066cd --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Energy.kt @@ -0,0 +1,44 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val energyCollection: List by lazy { + listOf( + NormalUnit(UnitID.electron_volt, BigDecimal("0.160217733"), UnitGroup.ENERGY, R.string.unit_electron_volt, R.string.unit_electron_volt_short), + NormalUnit(UnitID.attojoule, BigDecimal("1.00"), UnitGroup.ENERGY, R.string.unit_attojoule, R.string.unit_attojoule_short), + NormalUnit(UnitID.joule, BigDecimal("1000000000000000000"), UnitGroup.ENERGY, R.string.unit_joule, R.string.unit_joule_short), + NormalUnit(UnitID.kilojoule, BigDecimal("1000000000000000000000"), UnitGroup.ENERGY, R.string.unit_kilojoule, R.string.unit_kilojoule_short), + NormalUnit(UnitID.megajoule, BigDecimal("1000000000000000000000000"), UnitGroup.ENERGY, R.string.unit_megajoule, R.string.unit_megajoule_short), + NormalUnit(UnitID.gigajoule, BigDecimal("1000000000000000000000000000"), UnitGroup.ENERGY, R.string.unit_gigajoule, R.string.unit_gigajoule_short), + NormalUnit(UnitID.energy_ton, BigDecimal("4184000000000000000000000000"), UnitGroup.ENERGY, R.string.unit_energy_ton, R.string.unit_energy_ton_short), + NormalUnit(UnitID.kiloton, BigDecimal("4184000000000000000000000000000"), UnitGroup.ENERGY, R.string.unit_kiloton, R.string.unit_kiloton_short), + NormalUnit(UnitID.megaton, BigDecimal("4184000000000000000000000000000000"), UnitGroup.ENERGY, R.string.unit_megaton, R.string.unit_megaton_short), + NormalUnit(UnitID.gigaton, BigDecimal("4184000000000000000000000000000000000"), UnitGroup.ENERGY, R.string.unit_gigaton, R.string.unit_gigaton_short), + NormalUnit(UnitID.energy_horse_power_metric, BigDecimal("2647795500000000000000000"), UnitGroup.ENERGY, R.string.unit_energy_horse_power_metric, R.string.unit_energy_horse_power_metric_short), + NormalUnit(UnitID.calorie_th, BigDecimal("4184000000000000000"), UnitGroup.ENERGY, R.string.unit_calorie_th, R.string.unit_calorie_th_short), + NormalUnit(UnitID.kilocalorie_th, BigDecimal("4184000000000000000000"), UnitGroup.ENERGY, R.string.unit_kilocalorie_th, R.string.unit_kilocalorie_th_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/FlowRate.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/FlowRate.kt new file mode 100644 index 00000000..350d99fb --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/FlowRate.kt @@ -0,0 +1,52 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +val flowRateCollection: List by lazy { + listOf( + NormalUnit(UnitID.liter_per_hour, BigDecimal("3600000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_hour, R.string.unit_liter_per_hour_short, true), + NormalUnit(UnitID.liter_per_minute, BigDecimal("60000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_minute, R.string.unit_liter_per_minute_short, true), + NormalUnit(UnitID.liter_per_second, BigDecimal("1000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_second, R.string.unit_liter_per_second_short, true), + NormalUnit(UnitID.milliliter_per_hour, BigDecimal("3600000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_hour, R.string.unit_milliliter_per_hour_short, true), + NormalUnit(UnitID.milliliter_per_minute, BigDecimal("60000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_minute, R.string.unit_milliliter_per_minute_short, true), + NormalUnit(UnitID.milliliter_per_second, BigDecimal("1000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_second, R.string.unit_milliliter_per_second_short, true), + NormalUnit(UnitID.cubic_meter_per_hour, BigDecimal("3600"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_hour, R.string.unit_cubic_meter_per_hour_short, true), + NormalUnit(UnitID.cubic_meter_per_minute, BigDecimal("60"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_minute, R.string.unit_cubic_meter_per_minute_short, true), + NormalUnit(UnitID.cubic_meter_per_second, BigDecimal("1"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_second, R.string.unit_cubic_meter_per_second_short, true), + NormalUnit(UnitID.cubic_millimeter_per_hour, BigDecimal("3600000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_hour, R.string.unit_cubic_millimeter_per_hour_short, true), + NormalUnit(UnitID.cubic_millimeter_per_minute, BigDecimal("60000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_minute, R.string.unit_cubic_millimeter_per_minute_short, true), + NormalUnit(UnitID.cubic_millimeter_per_second, BigDecimal("1000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_second, R.string.unit_cubic_millimeter_per_second_short, true), + NormalUnit(UnitID.cubic_foot_per_hour, BigDecimal("127132.80019736"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_hour, R.string.unit_cubic_foot_per_hour_short, true), + NormalUnit(UnitID.cubic_foot_per_minute, BigDecimal("2118.8800032893"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_minute, R.string.unit_cubic_foot_per_minute_short, true), + NormalUnit(UnitID.cubic_foot_per_second, BigDecimal("35.314666721489"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_second, R.string.unit_cubic_foot_per_second_short, true), + NormalUnit(UnitID.gallons_per_hour_us, BigDecimal("951019.38848933"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_us, R.string.unit_gallon_per_hour_us_short, true), + NormalUnit(UnitID.gallons_per_minute_us, BigDecimal("15850.323141489"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_us, R.string.unit_gallon_per_minute_us_short, true), + NormalUnit(UnitID.gallons_per_second_us, BigDecimal("264.17205235815"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_us, R.string.unit_gallon_per_second_us_short, true), + NormalUnit(UnitID.gallons_per_hour_imperial, BigDecimal("791889.29387672"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_imperial, R.string.unit_gallon_per_hour_imperial_short, true), + NormalUnit(UnitID.gallons_per_minute_imperial, BigDecimal("13198.154897945"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_imperial, R.string.unit_gallon_per_minute_imperial_short, true), + NormalUnit(UnitID.gallons_per_second_imperial, BigDecimal("219.96924829909"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_imperial, R.string.unit_gallon_per_second_imperial_short, true), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Flux.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Flux.kt new file mode 100644 index 00000000..21703bfc --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Flux.kt @@ -0,0 +1,38 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val fluxCollection: List by lazy { + listOf( + NormalUnit(UnitID.maxwell, BigDecimal("1"), UnitGroup.FLUX, R.string.unit_maxwell, R.string.unit_maxwell_short), + NormalUnit(UnitID.microweber, BigDecimal("100"), UnitGroup.FLUX, R.string.unit_microweber, R.string.unit_microweber_short), + NormalUnit(UnitID.milliweber, BigDecimal("100000"), UnitGroup.FLUX, R.string.unit_milliweber, R.string.unit_milliweber_short), + NormalUnit(UnitID.weber, BigDecimal("100000000"), UnitGroup.FLUX, R.string.unit_weber, R.string.unit_weber_short), + NormalUnit(UnitID.kiloweber, BigDecimal("100000000000"), UnitGroup.FLUX, R.string.unit_kiloweber, R.string.unit_kiloweber_short), + NormalUnit(UnitID.megaweber, BigDecimal("100000000000000"), UnitGroup.FLUX, R.string.unit_megaweber, R.string.unit_megaweber_short), + NormalUnit(UnitID.gigaweber, BigDecimal("100000000000000000"), UnitGroup.FLUX, R.string.unit_gigaweber, R.string.unit_gigaweber_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Force.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Force.kt new file mode 100644 index 00000000..dbf23ced --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Force.kt @@ -0,0 +1,46 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +val forceCollection: List by lazy { + listOf( + NormalUnit(UnitID.attonewton, BigDecimal("1"), UnitGroup.FORCE, R.string.unit_attonewton, R.string.unit_attonewton_short), + NormalUnit(UnitID.dyne, BigDecimal("10000000000000"), UnitGroup.FORCE, R.string.unit_dyne, R.string.unit_dyne_short), + NormalUnit(UnitID.millinewton, BigDecimal("1000000000000000"), UnitGroup.FORCE, R.string.unit_millinewton, R.string.unit_millinewton_short), + NormalUnit(UnitID.joule_per_centimeter, BigDecimal("10000000000000000"), UnitGroup.FORCE, R.string.unit_joule_per_centimeter, R.string.unit_joule_per_centimeter_short), + NormalUnit(UnitID.newton, BigDecimal("1000000000000000000"), UnitGroup.FORCE, R.string.unit_newton, R.string.unit_newton_short), + NormalUnit(UnitID.joule_per_meter, BigDecimal("1000000000000000000"), UnitGroup.FORCE, R.string.unit_joule_per_meter, R.string.unit_joule_per_meter_short), + NormalUnit(UnitID.kilonewton, BigDecimal("1000000000000000000000"), UnitGroup.FORCE, R.string.unit_kilonewton, R.string.unit_kilonewton_short), + NormalUnit(UnitID.gram_force, BigDecimal("9806650000000000"), UnitGroup.FORCE, R.string.unit_gram_force, R.string.unit_gram_force_short), + NormalUnit(UnitID.kilogram_force, BigDecimal("9806650000000000000"), UnitGroup.FORCE, R.string.unit_kilogram_force, R.string.unit_kilogram_force_short), + NormalUnit(UnitID.ton_force, BigDecimal("9806650000000000000000"), UnitGroup.FORCE, R.string.unit_ton_force, R.string.unit_ton_force_short), + NormalUnit(UnitID.ounce_force, BigDecimal("278013850953423000"), UnitGroup.FORCE, R.string.unit_ounce_force, R.string.unit_ounce_force_short), + NormalUnit(UnitID.pound_force, BigDecimal("4448221615255000000"), UnitGroup.FORCE, R.string.unit_pound_force, R.string.unit_pound_force_short), + NormalUnit(UnitID.kilopound_force, BigDecimal("4448221615255000000000"), UnitGroup.FORCE, R.string.unit_kilopound_force, R.string.unit_kilopound_force_short), + NormalUnit(UnitID.pond, BigDecimal("9806650000000000"), UnitGroup.FORCE, R.string.unit_pond, R.string.unit_pond_short), + NormalUnit(UnitID.kilopond, BigDecimal("9806650000000000000"), UnitGroup.FORCE, R.string.unit_kilopond, R.string.unit_kilopond_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/FuelConsumption.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/FuelConsumption.kt new file mode 100644 index 00000000..b22d5a7a --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/FuelConsumption.kt @@ -0,0 +1,41 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +val fuelConsumptionCollection: List by lazy { + listOf( + NormalUnit( UnitID.kilometer_per_liter, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_km_per_l, R.string.unit_km_per_l_short), + NormalUnit(UnitID.liter_per_kilometer, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_km, R.string.unit_l_per_km_short, true), + NormalUnit(UnitID.liter_per_100_kilometer, BigDecimal("100"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_100_km, R.string.unit_l_per_100_km_short, true), + NormalUnit( UnitID.mile_per_gallon_uk, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_uk, R.string.unit_mi_per_gallon_uk_short), + NormalUnit( UnitID.mile_per_gallon_us, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_us, R.string.unit_mi_per_gallon_us_short), + NormalUnit( UnitID.mile_us_per_liter, BigDecimal("1.609344"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_us_per_l, R.string.unit_mi_us_per_l_short), + NormalUnit(UnitID.gallon_us_per_mile, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_mile, R.string.unit_gallon_us_per_mile_short, true), + NormalUnit(UnitID.gallon_uk_per_mile, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_mile, R.string.unit_gallon_uk_per_mile_short, true), + NormalUnit(UnitID.gallon_us_per_100_mile, BigDecimal("42.51437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_100_mile, R.string.unit_gallon_us_per_100_mile_short, true), + NormalUnit(UnitID.gallon_uk_per_100_mile, BigDecimal("35.400618996"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_100_mile, R.string.unit_gallon_uk_per_100_mile_short, true), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Length.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Length.kt new file mode 100644 index 00000000..fa83e71b --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Length.kt @@ -0,0 +1,58 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val lengthCollection: List by lazy { + listOf( + NormalUnit(UnitID.attometer, BigDecimal("1"), UnitGroup.LENGTH, R.string.unit_attometer, R.string.unit_attometer_short), + NormalUnit(UnitID.nanometer, BigDecimal("1000000000"), UnitGroup.LENGTH, R.string.unit_nanometer, R.string.unit_nanometer_short), + NormalUnit(UnitID.micrometer, BigDecimal("1000000000000"), UnitGroup.LENGTH, R.string.unit_micrometer, R.string.unit_micrometer_short), + NormalUnit(UnitID.millimeter, BigDecimal("1000000000000000"), UnitGroup.LENGTH, R.string.unit_millimeter, R.string.unit_millimeter_short), + NormalUnit(UnitID.centimeter, BigDecimal("10000000000000000"), UnitGroup.LENGTH, R.string.unit_centimeter, R.string.unit_centimeter_short), + NormalUnit(UnitID.decimeter, BigDecimal("100000000000000000"), UnitGroup.LENGTH, R.string.unit_decimeter, R.string.unit_decimeter_short), + NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), + NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), + NormalUnit(UnitID.nautical_mile, BigDecimal("1852000000000000000000"), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), + NormalUnit(UnitID.inch, BigDecimal("25400000000000000"), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), + NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), + NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), + NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), + NormalUnit(UnitID.light_year, BigDecimal("9460730472000000000000000000000000"), UnitGroup.LENGTH, R.string.unit_light_year, R.string.unit_light_year_short), + NormalUnit(UnitID.parsec, BigDecimal("30856775814913600000000000000000000"), UnitGroup.LENGTH, R.string.unit_parsec, R.string.unit_parsec_short), + NormalUnit(UnitID.kiloparsec, BigDecimal("30856775814913600000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kiloparsec, R.string.unit_kiloparsec_short), + NormalUnit(UnitID.megaparsec, BigDecimal("30856775814913600000000000000000000000000"), UnitGroup.LENGTH, R.string.unit_megaparsec, R.string.unit_megaparsec_short), + NormalUnit(UnitID.mercury_equatorial_radius, BigDecimal("2439700000000000000000000"), UnitGroup.LENGTH, R.string.unit_mercury_equatorial_radius, R.string.unit_mercury_equatorial_radius_short), + NormalUnit(UnitID.venus_equatorial_radius, BigDecimal("6051800000000000000000000"), UnitGroup.LENGTH, R.string.unit_venus_equatorial_radius, R.string.unit_venus_equatorial_radius_short), + NormalUnit(UnitID.earth_equatorial_radius, BigDecimal("6371000000000000000000000"), UnitGroup.LENGTH, R.string.unit_earth_equatorial_radius, R.string.unit_earth_equatorial_radius_short), + NormalUnit(UnitID.mars_equatorial_radius, BigDecimal("3389500000000000000000000"), UnitGroup.LENGTH, R.string.unit_mars_equatorial_radius, R.string.unit_mars_equatorial_radius_short), + NormalUnit(UnitID.jupiter_equatorial_radius, BigDecimal("69911000000000000000000000"), UnitGroup.LENGTH, R.string.unit_jupiter_equatorial_radius, R.string.unit_jupiter_equatorial_radius_short), + NormalUnit(UnitID.saturn_equatorial_radius, BigDecimal("58232000000000000000000000"), UnitGroup.LENGTH, R.string.unit_saturn_equatorial_radius, R.string.unit_saturn_equatorial_radius_short), + NormalUnit(UnitID.uranus_equatorial_radius, BigDecimal("25362000000000000000000000"), UnitGroup.LENGTH, R.string.unit_uranus_equatorial_radius, R.string.unit_uranus_equatorial_radius_short), + NormalUnit(UnitID.neptune_equatorial_radius, BigDecimal("24622000000000000000000000"), UnitGroup.LENGTH, R.string.unit_neptune_equatorial_radius, R.string.unit_neptune_equatorial_radius_short), + NormalUnit(UnitID.sun_equatorial_radius, BigDecimal("695508000000000000000000000"), UnitGroup.LENGTH, R.string.unit_sun_equatorial_radius, R.string.unit_sun_equatorial_radius_short), + ) +} + diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Luminance.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Luminance.kt new file mode 100644 index 00000000..53ccbd48 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Luminance.kt @@ -0,0 +1,50 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +val luminanceCollection: List by lazy { + listOf( + NormalUnit(UnitID.candela_per_square_meter, BigDecimal("31415926.5359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_meter, R.string.unit_candela_per_square_meter_short), + NormalUnit(UnitID.candela_per_square_centimeter, BigDecimal("314159265359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_centimeter, R.string.unit_candela_per_square_centimeter_short), + NormalUnit(UnitID.candela_per_square_foot, BigDecimal("338158218.89"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_foot, R.string.unit_candela_per_square_foot_short), + NormalUnit(UnitID.candela_per_square_inch, BigDecimal("48694783520"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_inch, R.string.unit_candela_per_square_inch_short), + NormalUnit(UnitID.kilocandela_per_square_meter, BigDecimal("31415926535.9"), UnitGroup.LUMINANCE, R.string.unit_kilocandela_per_square_meter, R.string.unit_kilocandela_per_square_meter_short), + NormalUnit(UnitID.stilb, BigDecimal("314159265359"), UnitGroup.LUMINANCE, R.string.unit_stilb, R.string.unit_stilb_short), + NormalUnit(UnitID.lumen_per_square_meter_per_steradian, BigDecimal("31415926.5359"), UnitGroup.LUMINANCE, R.string.unit_lumen_per_square_meter_per_steradian, R.string.unit_lumen_per_square_meter_per_steradian_short), + NormalUnit(UnitID.lumen_per_square_centimeter_per_steradian, BigDecimal("314159265359"), UnitGroup.LUMINANCE, R.string.unit_lumen_per_square_centimeter_per_steradian, R.string.unit_lumen_per_square_centimeter_per_steradian_short), + NormalUnit(UnitID.lumen_per_square_foot_per_steradian, BigDecimal("338158218.89"), UnitGroup.LUMINANCE, R.string.unit_lumen_per_square_foot_per_steradian, R.string.unit_lumen_per_square_foot_per_steradian_short), + NormalUnit(UnitID.watt_per_square_centimeter_per_steradian, BigDecimal("214570778240185"), UnitGroup.LUMINANCE, R.string.unit_watt_per_square_centimeter_per_steradian, R.string.unit_watt_per_square_centimeter_per_steradian_short), + NormalUnit(UnitID.nit, BigDecimal("31415926.5359"), UnitGroup.LUMINANCE, R.string.unit_nit, R.string.unit_nit_short), + NormalUnit(UnitID.millinit, BigDecimal("31415.9265359"), UnitGroup.LUMINANCE, R.string.unit_millinit, R.string.unit_millinit_short), + NormalUnit(UnitID.lambert, BigDecimal("100000000000"), UnitGroup.LUMINANCE, R.string.unit_lambert, R.string.unit_lambert_short), + NormalUnit(UnitID.millilambert, BigDecimal("100000000"), UnitGroup.LUMINANCE, R.string.unit_millilambert, R.string.unit_millilambert_short), + NormalUnit(UnitID.foot_lambert, BigDecimal("107639104.167"), UnitGroup.LUMINANCE, R.string.unit_foot_lambert, R.string.unit_foot_lambert_short), + NormalUnit(UnitID.apostilb, BigDecimal("10000000"), UnitGroup.LUMINANCE, R.string.unit_apostilb, R.string.unit_apostilb_short), + NormalUnit(UnitID.blondel, BigDecimal("10000000"), UnitGroup.LUMINANCE, R.string.unit_blondel, R.string.unit_blondel_short), + NormalUnit(UnitID.skot, BigDecimal("10000"), UnitGroup.LUMINANCE, R.string.unit_skot, R.string.unit_skot_short), + NormalUnit(UnitID.bril, BigDecimal("1"), UnitGroup.LUMINANCE, R.string.unit_bril, R.string.unit_bril_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Mass.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Mass.kt new file mode 100644 index 00000000..5ea058c0 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Mass.kt @@ -0,0 +1,52 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val massCollection: List by lazy { + listOf( + NormalUnit(UnitID.electron_mass_rest, BigDecimal("0.00000000000000000000000000091093897"), UnitGroup.MASS, R.string.unit_electron_mass_rest, R.string.unit_electron_mass_rest_short), + NormalUnit(UnitID.atomic_mass_unit, BigDecimal("0.0000000000000000000000016605402"), UnitGroup.MASS, R.string.unit_atomic_mass_unit, R.string.unit_atomic_mass_unit_short), + NormalUnit(UnitID.microgram, BigDecimal("0.000001"), UnitGroup.MASS, R.string.unit_microgram, R.string.unit_microgram_short), + NormalUnit(UnitID.milligram, BigDecimal("0.001"), UnitGroup.MASS, R.string.unit_milligram, R.string.unit_milligram_short), + NormalUnit(UnitID.grain, BigDecimal("0.06479891"), UnitGroup.MASS, R.string.unit_grain, R.string.unit_grain_short), + NormalUnit(UnitID.gram, BigDecimal("1"), UnitGroup.MASS, R.string.unit_gram, R.string.unit_gram_short), + NormalUnit(UnitID.kilogram, BigDecimal("1000"), UnitGroup.MASS, R.string.unit_kilogram, R.string.unit_kilogram_short), + NormalUnit(UnitID.metric_ton, BigDecimal("1000000"), UnitGroup.MASS, R.string.unit_metric_ton, R.string.unit_metric_ton_short), + NormalUnit(UnitID.imperial_ton, BigDecimal("1016046.9088"), UnitGroup.MASS, R.string.unit_imperial_ton, R.string.unit_imperial_ton_short), + NormalUnit(UnitID.ounce, BigDecimal("28.349523125"), UnitGroup.MASS, R.string.unit_ounce, R.string.unit_ounce_short), + NormalUnit(UnitID.carat, BigDecimal("0.2"), UnitGroup.MASS, R.string.unit_carat, R.string.unit_carat_short), + NormalUnit(UnitID.pound, BigDecimal("453.59237"), UnitGroup.MASS, R.string.unit_pound, R.string.unit_pound_short), + NormalUnit(UnitID.mercury_mass, BigDecimal("330104000000000000000000000"), UnitGroup.MASS, R.string.unit_mercury_mass, R.string.unit_mercury_mass_short), + NormalUnit(UnitID.venus_mass, BigDecimal("4867320000000000000000000000"), UnitGroup.MASS, R.string.unit_venus_mass, R.string.unit_venus_mass_short), + NormalUnit(UnitID.earth_mass, BigDecimal("5972190000000000000000000000"), UnitGroup.MASS, R.string.unit_earth_mass, R.string.unit_earth_mass_short), + NormalUnit(UnitID.mars_mass, BigDecimal("641693000000000000000000000"), UnitGroup.MASS, R.string.unit_mars_mass, R.string.unit_mars_mass_short), + NormalUnit(UnitID.jupiter_mass, BigDecimal("1898130000000000000000000000000"), UnitGroup.MASS, R.string.unit_jupiter_mass, R.string.unit_jupiter_mass_short), + NormalUnit(UnitID.saturn_mass, BigDecimal("568319000000000000000000000000"), UnitGroup.MASS, R.string.unit_saturn_mass, R.string.unit_saturn_mass_short), + NormalUnit(UnitID.uranus_mass, BigDecimal("86810300000000000000000000000"), UnitGroup.MASS, R.string.unit_uranus_mass, R.string.unit_uranus_mass_short), + NormalUnit(UnitID.neptune_mass, BigDecimal("102410000000000000000000000000"), UnitGroup.MASS, R.string.unit_neptune_mass, R.string.unit_neptune_mass_short), + NormalUnit(UnitID.sun_mass, BigDecimal("1989100000000000000000000000000000"), UnitGroup.MASS, R.string.unit_sun_mass, R.string.unit_sun_mass_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/NumberBase.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/NumberBase.kt new file mode 100644 index 00000000..161fe243 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/NumberBase.kt @@ -0,0 +1,46 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NumberBaseUnit +import java.math.BigDecimal + +internal val numberBaseCollection: List by lazy { + listOf( + NumberBaseUnit(UnitID.binary, BigDecimal("2.0"), UnitGroup.NUMBER_BASE, R.string.unit_binary, R.string.unit_binary_short), + NumberBaseUnit(UnitID.ternary, BigDecimal("3.0"), UnitGroup.NUMBER_BASE, R.string.unit_ternary, R.string.unit_ternary_short), + NumberBaseUnit(UnitID.quaternary, BigDecimal("4.0"), UnitGroup.NUMBER_BASE, R.string.unit_quaternary, R.string.unit_quaternary_short), + NumberBaseUnit(UnitID.quinary, BigDecimal("5.0"), UnitGroup.NUMBER_BASE, R.string.unit_quinary, R.string.unit_quinary_short), + NumberBaseUnit(UnitID.senary, BigDecimal("6.0"), UnitGroup.NUMBER_BASE, R.string.unit_senary, R.string.unit_senary_short), + NumberBaseUnit(UnitID.septenary, BigDecimal("7.0"), UnitGroup.NUMBER_BASE, R.string.unit_septenary, R.string.unit_septenary_short), + NumberBaseUnit(UnitID.octal, BigDecimal("8.0"), UnitGroup.NUMBER_BASE, R.string.unit_octal, R.string.unit_octal_short), + NumberBaseUnit(UnitID.nonary, BigDecimal("9.0"), UnitGroup.NUMBER_BASE, R.string.unit_nonary, R.string.unit_nonary_short), + NumberBaseUnit(UnitID.decimal, BigDecimal("10.0"), UnitGroup.NUMBER_BASE, R.string.unit_decimal, R.string.unit_decimal_short), + NumberBaseUnit(UnitID.undecimal, BigDecimal("11.0"), UnitGroup.NUMBER_BASE, R.string.unit_undecimal, R.string.unit_undecimal_short), + NumberBaseUnit(UnitID.duodecimal, BigDecimal("12.0"), UnitGroup.NUMBER_BASE, R.string.unit_duodecimal, R.string.unit_duodecimal_short), + NumberBaseUnit(UnitID.tridecimal, BigDecimal("13.0"), UnitGroup.NUMBER_BASE, R.string.unit_tridecimal, R.string.unit_tridecimal_short), + NumberBaseUnit(UnitID.tetradecimal, BigDecimal("14.0"), UnitGroup.NUMBER_BASE, R.string.unit_tetradecimal, R.string.unit_tetradecimal_short), + NumberBaseUnit(UnitID.pentadecimal, BigDecimal("15.0"), UnitGroup.NUMBER_BASE, R.string.unit_pentadecimal, R.string.unit_pentadecimal_short), + NumberBaseUnit(UnitID.hexadecimal, BigDecimal("16.0"), UnitGroup.NUMBER_BASE, R.string.unit_hexadecimal, R.string.unit_hexadecimal_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Power.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Power.kt new file mode 100644 index 00000000..9240df9e --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Power.kt @@ -0,0 +1,36 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val powerCollection: List by lazy { + listOf( + NormalUnit(UnitID.attowatt, BigDecimal("1"), UnitGroup.POWER, R.string.unit_attowatt, R.string.unit_attowatt_short), + NormalUnit(UnitID.watt, BigDecimal("1000000000000000000"), UnitGroup.POWER, R.string.unit_watt, R.string.unit_watt_short), + NormalUnit(UnitID.kilowatt, BigDecimal("1000000000000000000000"), UnitGroup.POWER, R.string.unit_kilowatt, R.string.unit_kilowatt_short), + NormalUnit(UnitID.megawatt, BigDecimal("1000000000000000000000000"), UnitGroup.POWER, R.string.unit_megawatt, R.string.unit_megawatt_short), + NormalUnit(UnitID.horse_power_mechanical, BigDecimal("745699871582285700000"), UnitGroup.POWER, R.string.unit_horse_power_mechanical, R.string.unit_horse_power_mechanical_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Prefix.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Prefix.kt new file mode 100644 index 00000000..e9f97413 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Prefix.kt @@ -0,0 +1,56 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +val prefixCollection: List by lazy { + listOf( + NormalUnit(UnitID.prefix_quetta, BigDecimal("1000000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_quetta, R.string.unit_prefix_quetta_short), + NormalUnit(UnitID.prefix_ronna, BigDecimal("1000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_ronna, R.string.unit_prefix_ronna_short), + NormalUnit(UnitID.prefix_yotta, BigDecimal("1000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_yotta, R.string.unit_prefix_yotta_short), + NormalUnit(UnitID.prefix_zetta, BigDecimal("1000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_zetta, R.string.unit_prefix_zetta_short), + NormalUnit(UnitID.prefix_exa, BigDecimal("1000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_exa, R.string.unit_prefix_exa_short), + NormalUnit(UnitID.prefix_peta, BigDecimal("1000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_peta, R.string.unit_prefix_peta_short), + NormalUnit(UnitID.prefix_tera, BigDecimal("1000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_tera, R.string.unit_prefix_tera_short), + NormalUnit(UnitID.prefix_giga, BigDecimal("1000000000"), UnitGroup.PREFIX, R.string.unit_prefix_giga, R.string.unit_prefix_giga_short), + NormalUnit(UnitID.prefix_mega, BigDecimal("1000000"), UnitGroup.PREFIX, R.string.unit_prefix_mega, R.string.unit_prefix_mega_short), + NormalUnit(UnitID.prefix_kilo, BigDecimal("1000"), UnitGroup.PREFIX, R.string.unit_prefix_kilo, R.string.unit_prefix_kilo_short), + NormalUnit(UnitID.prefix_hecto, BigDecimal("100"), UnitGroup.PREFIX, R.string.unit_prefix_hecto, R.string.unit_prefix_hecto_short), + NormalUnit(UnitID.prefix_deca, BigDecimal("10"), UnitGroup.PREFIX, R.string.unit_prefix_deca, R.string.unit_prefix_deca_short), + NormalUnit(UnitID.prefix_base, BigDecimal("1"), UnitGroup.PREFIX, R.string.unit_prefix_base, R.string.unit_prefix_base_short), + NormalUnit(UnitID.prefix_deci, BigDecimal("0.1"), UnitGroup.PREFIX, R.string.unit_prefix_deci, R.string.unit_prefix_deci_short), + NormalUnit(UnitID.prefix_centi, BigDecimal("0.01"), UnitGroup.PREFIX, R.string.unit_prefix_centi, R.string.unit_prefix_centi_short), + NormalUnit(UnitID.prefix_milli, BigDecimal("0.001"), UnitGroup.PREFIX, R.string.unit_prefix_milli, R.string.unit_prefix_milli_short), + NormalUnit(UnitID.prefix_micro, BigDecimal("0.000001"), UnitGroup.PREFIX, R.string.unit_prefix_micro, R.string.unit_prefix_micro_short), + NormalUnit(UnitID.prefix_nano, BigDecimal("0.000000001"), UnitGroup.PREFIX, R.string.unit_prefix_nano, R.string.unit_prefix_nano_short), + NormalUnit(UnitID.prefix_pico, BigDecimal("0.000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_pico, R.string.unit_prefix_pico_short), + NormalUnit(UnitID.prefix_femto, BigDecimal("0.000000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_femto, R.string.unit_prefix_femto_short), + NormalUnit(UnitID.prefix_atto, BigDecimal("0.000000000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_atto, R.string.unit_prefix_atto_short), + NormalUnit(UnitID.prefix_zepto, BigDecimal("0.000000000000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_zepto, R.string.unit_prefix_zepto_short), + NormalUnit(UnitID.prefix_yocto, BigDecimal("0.000000000000000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_yocto, R.string.unit_prefix_yocto_short), + NormalUnit(UnitID.prefix_ronto, BigDecimal("0.000000000000000000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_ronto, R.string.unit_prefix_ronto_short), + NormalUnit(UnitID.prefix_quecto, BigDecimal("0.000000000000000000000000000001"), UnitGroup.PREFIX, R.string.unit_prefix_quecto, R.string.unit_prefix_quecto_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Pressure.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Pressure.kt new file mode 100644 index 00000000..4df49506 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Pressure.kt @@ -0,0 +1,61 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val pressureCollection: List by lazy { + listOf( + NormalUnit(UnitID.attopascal, BigDecimal("1"), UnitGroup.PRESSURE, R.string.unit_attopascal, R.string.unit_attopascal_short), + NormalUnit(UnitID.femtopascal, BigDecimal("1000"), UnitGroup.PRESSURE, R.string.unit_femtopascal, R.string.unit_femtopascal_short), + NormalUnit(UnitID.picopascal, BigDecimal("1000000"), UnitGroup.PRESSURE, R.string.unit_picopascal, R.string.unit_picopascal_short), + NormalUnit(UnitID.nanopascal, BigDecimal("1000000000"), UnitGroup.PRESSURE, R.string.unit_nanopascal, R.string.unit_nanopascal_short), + NormalUnit(UnitID.micropascal, BigDecimal("1000000000000"), UnitGroup.PRESSURE, R.string.unit_micropascal, R.string.unit_micropascal_short), + NormalUnit(UnitID.millipascal, BigDecimal("1000000000000000"), UnitGroup.PRESSURE, R.string.unit_millipascal, R.string.unit_millipascal_short), + NormalUnit(UnitID.centipascal, BigDecimal("10000000000000000"), UnitGroup.PRESSURE, R.string.unit_centipascal, R.string.unit_centipascal_short), + NormalUnit(UnitID.decipascal, BigDecimal("100000000000000000"), UnitGroup.PRESSURE, R.string.unit_decipascal, R.string.unit_decipascal_short), + NormalUnit(UnitID.pascal, BigDecimal("1000000000000000000"), UnitGroup.PRESSURE, R.string.unit_pascal, R.string.unit_pascal_short), + NormalUnit(UnitID.dekapascal, BigDecimal("10000000000000000000"), UnitGroup.PRESSURE, R.string.unit_dekapascal, R.string.unit_dekapascal_short), + NormalUnit(UnitID.hectopascal, BigDecimal("100000000000000000000"), UnitGroup.PRESSURE, R.string.unit_hectopascal, R.string.unit_hectopascal_short), + NormalUnit(UnitID.millibar, BigDecimal("100000000000000000000"), UnitGroup.PRESSURE, R.string.unit_millibar, R.string.unit_millibar_short), + NormalUnit(UnitID.bar, BigDecimal("100000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_bar, R.string.unit_bar_short), + NormalUnit(UnitID.kilopascal, BigDecimal("1000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_kilopascal, R.string.unit_kilopascal_short), + NormalUnit(UnitID.megapascal, BigDecimal("1000000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_megapascal, R.string.unit_megapascal_short), + NormalUnit(UnitID.gigapascal, BigDecimal("1000000000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_gigapascal, R.string.unit_gigapascal_short), + NormalUnit(UnitID.terapascal, BigDecimal("1000000000000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_terapascal, R.string.unit_terapascal_short), + NormalUnit(UnitID.petapascal, BigDecimal("1000000000000000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_petapascal, R.string.unit_petapascal_short), + NormalUnit(UnitID.exapascal, BigDecimal("1000000000000000000000000000000000000"), UnitGroup.PRESSURE, R.string.unit_exapascal, R.string.unit_exapascal_short), + NormalUnit(UnitID.psi, BigDecimal("6894757293178300000000"), UnitGroup.PRESSURE, R.string.unit_psi, R.string.unit_psi_short), + NormalUnit(UnitID.ksi, BigDecimal("6894757293178300000000000"), UnitGroup.PRESSURE, R.string.unit_ksi, R.string.unit_ksi_short), + NormalUnit(UnitID.standard_atmosphere, BigDecimal("101325000000000000000000"), UnitGroup.PRESSURE, R.string.unit_standard_atmosphere, R.string.unit_standard_atmosphere_short), + NormalUnit(UnitID.torr, BigDecimal("133322368421082810000"), UnitGroup.PRESSURE, R.string.unit_torr, R.string.unit_torr_short), + NormalUnit(UnitID.micron_of_mercury, BigDecimal("133322368421082810"), UnitGroup.PRESSURE, R.string.unit_micron_of_mercury, R.string.unit_micron_of_mercury_short), + NormalUnit(UnitID.millimeter_of_mercury, BigDecimal("133322368421082810000"), UnitGroup.PRESSURE, R.string.unit_millimeter_of_mercury, R.string.unit_millimeter_of_mercury_short), + NormalUnit(UnitID.kilogram_force_per_square_meter, BigDecimal("9806650000000000000"), UnitGroup.PRESSURE, R.string.unit_kilogram_force_per_square_meter, R.string.unit_kilogram_force_per_square_meter_short), + NormalUnit(UnitID.kilogram_force_per_square_centimeter, BigDecimal("98066500000000000000000"), UnitGroup.PRESSURE, R.string.unit_kilogram_force_per_square_centimeter, R.string.unit_kilogram_force_per_square_centimeter_short), + NormalUnit(UnitID.gram_force_per_square_centimeter, BigDecimal("98066500000000000000"), UnitGroup.PRESSURE, R.string.unit_gram_force_per_square_centimeter, R.string.unit_gram_force_per_square_centimeter_short), + NormalUnit(UnitID.pound_force_per_square_foot, BigDecimal("47880258980000000000"), UnitGroup.PRESSURE, R.string.unit_pound_force_per_square_foot, R.string.unit_pound_force_per_square_foot_short), + NormalUnit(UnitID.pound_force_per_square_inch, BigDecimal("6894757293178300000000"), UnitGroup.PRESSURE, R.string.unit_pound_force_per_square_inch, R.string.unit_pound_force_per_square_inch_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Speed.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Speed.kt new file mode 100644 index 00000000..24ca8919 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Speed.kt @@ -0,0 +1,64 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val speedCollection: List by lazy { + listOf( + NormalUnit( UnitID.millimeter_per_hour, BigDecimal("1"), UnitGroup.SPEED, R.string.unit_millimeter_per_hour, R.string.unit_millimeter_per_hour_short), + NormalUnit( UnitID.millimeter_per_minute, BigDecimal("60"), UnitGroup.SPEED, R.string.unit_millimeter_per_minute, R.string.unit_millimeter_per_minute_short), + NormalUnit( UnitID.millimeter_per_second, BigDecimal("3600"), UnitGroup.SPEED, R.string.unit_millimeter_per_second, R.string.unit_millimeter_per_second_short), + NormalUnit( UnitID.centimeter_per_hour, BigDecimal("10"), UnitGroup.SPEED, R.string.unit_centimeter_per_hour, R.string.unit_centimeter_per_hour_short), + NormalUnit( UnitID.centimeter_per_minute, BigDecimal("600"), UnitGroup.SPEED, R.string.unit_centimeter_per_minute, R.string.unit_centimeter_per_minute_short), + NormalUnit( UnitID.centimeter_per_second, BigDecimal("36000"), UnitGroup.SPEED, R.string.unit_centimeter_per_second, R.string.unit_centimeter_per_second_short), + NormalUnit( UnitID.meter_per_hour, BigDecimal("1000"), UnitGroup.SPEED, R.string.unit_meter_per_hour, R.string.unit_meter_per_hour_short), + NormalUnit( UnitID.meter_per_minute, BigDecimal("60000"), UnitGroup.SPEED, R.string.unit_meter_per_minute, R.string.unit_meter_per_minute_short), + NormalUnit( UnitID.meter_per_second, BigDecimal("3600000"), UnitGroup.SPEED, R.string.unit_meter_per_second, R.string.unit_meter_per_second_short), + NormalUnit( UnitID.kilometer_per_hour, BigDecimal("1000000"), UnitGroup.SPEED, R.string.unit_kilometer_per_hour, R.string.unit_kilometer_per_hour_short), + NormalUnit( UnitID.kilometer_per_minute, BigDecimal("60000000"), UnitGroup.SPEED, R.string.unit_kilometer_per_minute, R.string.unit_kilometer_per_minute_short), + NormalUnit( UnitID.kilometer_per_second, BigDecimal("3600000000"), UnitGroup.SPEED, R.string.unit_kilometer_per_second, R.string.unit_kilometer_per_second_short), + NormalUnit( UnitID.foot_per_hour, BigDecimal("304.8"), UnitGroup.SPEED, R.string.unit_foot_per_hour, R.string.unit_foot_per_hour_short), + NormalUnit( UnitID.foot_per_minute, BigDecimal("18288"), UnitGroup.SPEED, R.string.unit_foot_per_minute, R.string.unit_foot_per_minute_short), + NormalUnit( UnitID.foot_per_second, BigDecimal("1097280"), UnitGroup.SPEED, R.string.unit_foot_per_second, R.string.unit_foot_per_second_short), + NormalUnit( UnitID.yard_per_hour, BigDecimal("914.4"), UnitGroup.SPEED, R.string.unit_yard_per_hour, R.string.unit_yard_per_hour_short), + NormalUnit( UnitID.yard_per_minute, BigDecimal("54864"), UnitGroup.SPEED, R.string.unit_yard_per_minute, R.string.unit_yard_per_minute_short), + NormalUnit( UnitID.yard_per_second, BigDecimal("3291840"), UnitGroup.SPEED, R.string.unit_yard_per_second, R.string.unit_yard_per_second_short), + NormalUnit( UnitID.mile_per_hour, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_mile_per_hour, R.string.unit_mile_per_hour_short), + NormalUnit( UnitID.mile_per_minute, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_mile_per_minute, R.string.unit_mile_per_minute_short), + NormalUnit( UnitID.mile_per_second, BigDecimal("5793638400"), UnitGroup.SPEED, R.string.unit_mile_per_second, R.string.unit_mile_per_second_short), + NormalUnit(UnitID.minute_per_kilometer, BigDecimal("60000000"), UnitGroup.SPEED, R.string.unit_minute_per_kilometer, R.string.unit_minute_per_kilometer_short, true), + NormalUnit(UnitID.minute_per_mile, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_minute_per_mile, R.string.unit_minute_per_mile_short, true), + NormalUnit(UnitID.hour_per_kilometer, BigDecimal("1000000"), UnitGroup.SPEED, R.string.unit_hour_per_kilometer, R.string.unit_hour_per_kilometer_short, true), + NormalUnit(UnitID.hour_per_mile, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_hour_per_mile, R.string.unit_hour_per_mile_short, true), + NormalUnit( UnitID.knot, BigDecimal("1852000"), UnitGroup.SPEED, R.string.unit_knot, R.string.unit_knot_short), + NormalUnit( UnitID.velocity_of_light_in_vacuum, BigDecimal("1079252848799998"), UnitGroup.SPEED, R.string.unit_velocity_of_light_in_vacuum, R.string.unit_velocity_of_light_in_vacuum_short), + NormalUnit( UnitID.cosmic_velocity_first, BigDecimal("28440000000"), UnitGroup.SPEED, R.string.unit_cosmic_velocity_first, R.string.unit_cosmic_velocity_first_short), + NormalUnit( UnitID.cosmic_velocity_second, BigDecimal("40320000000"), UnitGroup.SPEED, R.string.unit_cosmic_velocity_second, R.string.unit_cosmic_velocity_second_short), + NormalUnit( UnitID.cosmic_velocity_third, BigDecimal("60012000000"), UnitGroup.SPEED, R.string.unit_cosmic_velocity_third, R.string.unit_cosmic_velocity_third_short), + NormalUnit( UnitID.earths_orbital_speed, BigDecimal("107154000000"), UnitGroup.SPEED, R.string.unit_earths_orbital_speed, R.string.unit_earths_orbital_speed_short), + NormalUnit( UnitID.mach, BigDecimal("1236960000"), UnitGroup.SPEED, R.string.unit_mach, R.string.unit_mach_short), + NormalUnit( UnitID.mach_si_standard, BigDecimal("1062167040"), UnitGroup.SPEED, R.string.unit_mach_si_standard, R.string.unit_mach_si_standard_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Temperature.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Temperature.kt new file mode 100644 index 00000000..22b4bf44 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Temperature.kt @@ -0,0 +1,110 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.MAX_PRECISION +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import java.math.BigDecimal +import java.math.RoundingMode + +internal val temperatureCollection: List by lazy { + val celsius = object : BasicUnit.Default { + override val id: String = UnitID.celsius + override val group: UnitGroup = UnitGroup.TEMPERATURE + override val displayName: Int = R.string.unit_celsius + override val shortName: Int = R.string.unit_celsius_short + override val factor: BigDecimal = BigDecimal.ONE + override val backward: Boolean = false + + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) { + UnitID.fahrenheit -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .times(BigDecimal("1.8")) + .plus(BigDecimal("32")) + } + + UnitID.kelvin -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .plus(BigDecimal("273.15")) + } + + else -> value + } + } + + val fahrenheit = object : BasicUnit.Default { + override val id: String = UnitID.fahrenheit + override val group: UnitGroup = UnitGroup.TEMPERATURE + override val displayName: Int = R.string.unit_fahrenheit + override val shortName: Int = R.string.unit_fahrenheit_short + override val factor: BigDecimal = BigDecimal.ONE + override val backward: Boolean = false + + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) { + UnitID.celsius -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("32")) + .times(BigDecimal("5")) + .div(BigDecimal("9")) + } + UnitID.kelvin -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("32")) + .times(BigDecimal("5")) + .div(BigDecimal("9")) + .add(BigDecimal("273.15")) + } + else -> value + } + } + + val kelvin = object : BasicUnit.Default { + override val id: String = UnitID.kelvin + override val group: UnitGroup = UnitGroup.TEMPERATURE + override val displayName: Int = R.string.unit_kelvin + override val shortName: Int = R.string.unit_kelvin_short + override val factor: BigDecimal = BigDecimal.ONE + override val backward: Boolean = false + + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) { + UnitID.celsius -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("273.15")) + } + UnitID.fahrenheit -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("273.15")) + .times(BigDecimal("1.8")) + .plus(BigDecimal("32")) + } + else -> value + } + } + + listOf(celsius, fahrenheit, kelvin) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Time.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Time.kt new file mode 100644 index 00000000..303f77f9 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Time.kt @@ -0,0 +1,41 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val timeCollection: List by lazy { + listOf( + NormalUnit(UnitID.attosecond, BigDecimal("1"), UnitGroup.TIME, R.string.unit_attosecond, R.string.unit_attosecond_short), + NormalUnit(UnitID.nanosecond, BigDecimal("1000000000"), UnitGroup.TIME, R.string.unit_nanosecond, R.string.unit_nanosecond_short), + NormalUnit(UnitID.microsecond, BigDecimal("1000000000000"), UnitGroup.TIME, R.string.unit_microsecond, R.string.unit_microsecond_short), + NormalUnit(UnitID.millisecond, BigDecimal("1000000000000000"), UnitGroup.TIME, R.string.unit_millisecond, R.string.unit_millisecond_short), + NormalUnit(UnitID.jiffy, BigDecimal("10000000000000000"), UnitGroup.TIME, R.string.unit_jiffy, R.string.unit_jiffy_short), + NormalUnit(UnitID.second, BigDecimal("1000000000000000000"), UnitGroup.TIME, R.string.unit_second, R.string.unit_second_short), + NormalUnit(UnitID.minute, BigDecimal("60000000000000000000"), UnitGroup.TIME, R.string.unit_minute, R.string.unit_minute_short), + NormalUnit(UnitID.hour, BigDecimal("3600000000000000000000"), UnitGroup.TIME, R.string.unit_hour, R.string.unit_hour_short), + NormalUnit(UnitID.day, BigDecimal("86400000000000000000000"), UnitGroup.TIME, R.string.unit_day, R.string.unit_day_short), + NormalUnit(UnitID.week, BigDecimal("604800000000000000000000"), UnitGroup.TIME, R.string.unit_week, R.string.unit_week_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Torque.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Torque.kt new file mode 100644 index 00000000..c5c9ad72 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Torque.kt @@ -0,0 +1,48 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +val torqueCollection: List by lazy { + listOf( + NormalUnit(UnitID.dyne_millimeter, BigDecimal("1"), UnitGroup.TORQUE, R.string.unit_dyne_millimeter, R.string.unit_dyne_millimeter_short), + NormalUnit(UnitID.dyne_centimeter, BigDecimal("10"), UnitGroup.TORQUE, R.string.unit_dyne_centimeter, R.string.unit_dyne_centimeter_short), + NormalUnit(UnitID.dyne_meter, BigDecimal("1000"), UnitGroup.TORQUE, R.string.unit_dyne_meter, R.string.unit_dyne_meter_short), + NormalUnit(UnitID.newton_millimeter, BigDecimal("100000"), UnitGroup.TORQUE, R.string.unit_newton_millimeter, R.string.unit_newton_millimeter_short), + NormalUnit(UnitID.newton_centimeter, BigDecimal("1000000"), UnitGroup.TORQUE, R.string.unit_newton_centimeter, R.string.unit_newton_centimeter_short), + NormalUnit(UnitID.newton_meter, BigDecimal("100000000"), UnitGroup.TORQUE, R.string.unit_newton_meter, R.string.unit_newton_meter_short), + NormalUnit(UnitID.kilonewton_meter, BigDecimal("100000000000"), UnitGroup.TORQUE, R.string.unit_kilonewton_meter, R.string.unit_kilonewton_meter_short), + NormalUnit(UnitID.gram_force_millimeter, BigDecimal("980.665"), UnitGroup.TORQUE, R.string.unit_gram_force_millimeter, R.string.unit_gram_force_millimeter_short), + NormalUnit(UnitID.gram_force_centimeter, BigDecimal("9806.65"), UnitGroup.TORQUE, R.string.unit_gram_force_centimeter, R.string.unit_gram_force_centimeter_short), + NormalUnit(UnitID.kilogram_force_millimeter, BigDecimal("980665"), UnitGroup.TORQUE, R.string.unit_kilogram_force_millimeter, R.string.unit_kilogram_force_millimeter_short), + NormalUnit(UnitID.gram_force_meter, BigDecimal("980665"), UnitGroup.TORQUE, R.string.unit_gram_force_meter, R.string.unit_gram_force_meter_short), + NormalUnit(UnitID.kilogram_force_centimeter, BigDecimal("9806650"), UnitGroup.TORQUE, R.string.unit_kilogram_force_centimeter, R.string.unit_kilogram_force_centimeter_short), + NormalUnit(UnitID.kilogram_force_meter, BigDecimal("980665000"), UnitGroup.TORQUE, R.string.unit_kilogram_force_meter, R.string.unit_kilogram_force_meter_short), + NormalUnit(UnitID.ounce_force_foot, BigDecimal("8473862.4"), UnitGroup.TORQUE, R.string.unit_ounce_force_foot, R.string.unit_ounce_force_foot_short), + NormalUnit(UnitID.ounce_force_inch, BigDecimal("706155.2"), UnitGroup.TORQUE, R.string.unit_ounce_force_inch, R.string.unit_ounce_force_inch_short), + NormalUnit(UnitID.pound_force_foot, BigDecimal("135581800"), UnitGroup.TORQUE, R.string.unit_pound_force_foot, R.string.unit_pound_force_foot_short), + NormalUnit(UnitID.pound_force_inch, BigDecimal("11298483.333333334"), UnitGroup.TORQUE, R.string.unit_pound_force_inch, R.string.unit_pound_force_inch_short), + ) +} diff --git a/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Volume.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Volume.kt new file mode 100644 index 00000000..0a506cb2 --- /dev/null +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/collections/Volume.kt @@ -0,0 +1,56 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter.collections + +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +internal val volumeCollection: List by lazy { + listOf( + NormalUnit(UnitID.attoliter, BigDecimal("1"), UnitGroup.VOLUME, R.string.unit_attoliter, R.string.unit_attoliter_short), + NormalUnit(UnitID.milliliter, BigDecimal("1000000000000000"), UnitGroup.VOLUME, R.string.unit_milliliter, R.string.unit_milliliter_short), + NormalUnit(UnitID.liter, BigDecimal("1000000000000000000"), UnitGroup.VOLUME, R.string.unit_liter, R.string.unit_liter_short), + NormalUnit(UnitID.us_liquid_gallon, BigDecimal("3785411783999977000"), UnitGroup.VOLUME, R.string.unit_us_liquid_gallon, R.string.unit_us_liquid_gallon_short), + NormalUnit(UnitID.us_liquid_quart, BigDecimal("946352945999994200"), UnitGroup.VOLUME, R.string.unit_us_liquid_quart, R.string.unit_us_liquid_quart_short), + NormalUnit(UnitID.us_liquid_pint, BigDecimal("473176472999997100"), UnitGroup.VOLUME, R.string.unit_us_liquid_pint, R.string.unit_us_liquid_pint_short), + NormalUnit(UnitID.us_legal_cup, BigDecimal("236588236499998560"), UnitGroup.VOLUME, R.string.unit_us_legal_cup, R.string.unit_us_legal_cup_short), + NormalUnit(UnitID.us_fluid_ounce, BigDecimal("29573529562499996"), UnitGroup.VOLUME, R.string.unit_us_fluid_ounce, R.string.unit_us_fluid_ounce_short), + NormalUnit(UnitID.us_tablespoon, BigDecimal("14786764781249998"), UnitGroup.VOLUME, R.string.unit_us_tablespoon, R.string.unit_us_tablespoon_short), + NormalUnit(UnitID.us_teaspoon, BigDecimal("4928921593749952"), UnitGroup.VOLUME, R.string.unit_us_teaspoon, R.string.unit_us_teaspoon_short), + NormalUnit(UnitID.imperial_gallon, BigDecimal("4546089999999954400"), UnitGroup.VOLUME, R.string.unit_imperial_gallon, R.string.unit_imperial_gallon_short), + NormalUnit(UnitID.imperial_quart, BigDecimal("1136522500000001400"), UnitGroup.VOLUME, R.string.unit_imperial_quart, R.string.unit_imperial_quart_short), + NormalUnit(UnitID.imperial_pint, BigDecimal("568261250000000700"), UnitGroup.VOLUME, R.string.unit_imperial_pint, R.string.unit_imperial_pint_short), + NormalUnit(UnitID.imperial_cup, BigDecimal("284130625000000350"), UnitGroup.VOLUME, R.string.unit_imperial_cup, R.string.unit_imperial_cup_short), + NormalUnit(UnitID.imperial_fluid_ounce, BigDecimal("28413062500000036"), UnitGroup.VOLUME, R.string.unit_imperial_fluid_ounce, R.string.unit_imperial_fluid_ounce_short), + NormalUnit(UnitID.imperial_tablespoon, BigDecimal("17758164062500148"), UnitGroup.VOLUME, R.string.unit_imperial_tablespoon, R.string.unit_imperial_tablespoon_short), + NormalUnit(UnitID.imperial_teaspoon, BigDecimal("5919388020833314"), UnitGroup.VOLUME, R.string.unit_imperial_teaspoon, R.string.unit_imperial_teaspoon_short), + NormalUnit(UnitID.cubic_millimeter, BigDecimal("1000000000000"), UnitGroup.VOLUME, R.string.unit_cubic_millimeter, R.string.unit_cubic_millimeter_short), + NormalUnit(UnitID.cubic_centimeter, BigDecimal("1000000000000000"), UnitGroup.VOLUME, R.string.unit_cubic_centimeter, R.string.unit_cubic_centimeter_short), + NormalUnit(UnitID.cubic_meter, BigDecimal("1000000000000000000000"), UnitGroup.VOLUME, R.string.unit_cubic_meter, R.string.unit_cubic_meter_short), + NormalUnit(UnitID.cubic_kilometer, BigDecimal("1000000000000000000000000000000"), UnitGroup.VOLUME, R.string.unit_cubic_kilometer, R.string.unit_cubic_kilometer_short), + NormalUnit(UnitID.cubic_inch, BigDecimal("16387064000000000"), UnitGroup.VOLUME, R.string.unit_cubic_inch, R.string.unit_cubic_inch_short), + NormalUnit(UnitID.cubic_foot, BigDecimal("28316846590000000000"), UnitGroup.VOLUME, R.string.unit_cubic_foot, R.string.unit_cubic_foot_short), + NormalUnit(UnitID.cubic_yard, BigDecimal("764554857983995500000"), UnitGroup.VOLUME, R.string.unit_cubic_yard, R.string.unit_cubic_yard_short), + NormalUnit(UnitID.cubic_mile, BigDecimal("4168181825440539000000000000000"), UnitGroup.VOLUME, R.string.unit_cubic_mile, R.string.unit_cubic_mile_short), + ) +} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/remote/CurrencyApiService.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/remote/CurrencyApiService.kt similarity index 86% rename from data/converter/src/main/java/com/sadellie/unitto/data/converter/remote/CurrencyApiService.kt rename to data/converter/src/main/java/app/myzel394/numberhub/data/converter/remote/CurrencyApiService.kt index 79aaf93e..6202260a 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/remote/CurrencyApiService.kt +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/remote/CurrencyApiService.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.converter.remote +package app.myzel394.numberhub.data.converter.remote import com.squareup.moshi.Moshi import retrofit2.Retrofit @@ -24,7 +24,7 @@ import retrofit2.converter.moshi.MoshiConverterFactory import retrofit2.http.GET import retrofit2.http.Path -private const val BASE_URL = "https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/" +private const val BASE_URL = "https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/" private val moshi = Moshi.Builder() .add(CurrencyAdapter()) @@ -44,8 +44,8 @@ interface CurrencyApiService { */ @GET("{baseCurrency}.json") suspend fun getCurrencyPairs( - @Path("baseCurrency") baseCurrency: String - ) : CurrencyUnitResponse + @Path("baseCurrency") baseCurrency: String, + ): CurrencyUnitResponse } object CurrencyApi { diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/remote/CurrencyUnitResponse.kt b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/remote/CurrencyUnitResponse.kt similarity index 84% rename from data/converter/src/main/java/com/sadellie/unitto/data/converter/remote/CurrencyUnitResponse.kt rename to data/converter/src/main/java/app/myzel394/numberhub/data/converter/remote/CurrencyUnitResponse.kt index dacfbf3a..86cffc17 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/remote/CurrencyUnitResponse.kt +++ b/data/converter/src/main/java/app/myzel394/numberhub/data/converter/remote/CurrencyUnitResponse.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.converter.remote +package app.myzel394.numberhub.data.converter.remote import com.squareup.moshi.FromJson import com.squareup.moshi.ToJson @@ -29,7 +29,7 @@ import com.squareup.moshi.ToJson */ data class CurrencyUnitResponse( val date: String, - val currency: Map + val currency: Map, ) /** @@ -37,13 +37,15 @@ data class CurrencyUnitResponse( */ internal class CurrencyAdapter { @Suppress("UNUSED", "UNUSED_PARAMETER", "SameReturnValue") - @ToJson fun toJson(card: CurrencyUnitResponse): String? = null + @ToJson + fun toJson(card: CurrencyUnitResponse): String? = null @Suppress("UNUSED", "UNCHECKED_CAST") - @FromJson fun fromJson(response: Map): CurrencyUnitResponse { + @FromJson + fun fromJson(response: Map): CurrencyUnitResponse { return CurrencyUnitResponse( date = response["date"] as String, - currency = (response[response.keys.elementAt(1)]) as Map + currency = (response[response.keys.elementAt(1)]) as Map, ) } } diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt deleted file mode 100644 index 177bb65b..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter - -import android.content.Context -import com.sadellie.unitto.data.database.CurrencyRatesDao -import com.sadellie.unitto.data.database.UnitsDao -import com.sadellie.unitto.data.model.repository.UnitsRepository -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent - -@Module -@InstallIn(SingletonComponent::class) -class DataStoreModule { - @Provides - fun provideUnitsRepository( - unitsDao: UnitsDao, - currencyRatesDao: CurrencyRatesDao, - @ApplicationContext appContext: Context - ): UnitsRepository { - return UnitsRepositoryImpl( - unitsDao = unitsDao, - currencyRatesDao = currencyRatesDao, - mContext = appContext - ) - } -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt deleted file mode 100644 index 39947fca..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2022-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter - -import android.content.Context -import android.util.Log -import com.sadellie.unitto.data.converter.collections.accelerationCollection -import com.sadellie.unitto.data.converter.collections.angleCollection -import com.sadellie.unitto.data.converter.collections.areaCollection -import com.sadellie.unitto.data.converter.collections.currencyCollection -import com.sadellie.unitto.data.converter.collections.dataCollection -import com.sadellie.unitto.data.converter.collections.dataTransferCollection -import com.sadellie.unitto.data.converter.collections.electrostaticCapacitance -import com.sadellie.unitto.data.converter.collections.energyCollection -import com.sadellie.unitto.data.converter.collections.flowRateCollection -import com.sadellie.unitto.data.converter.collections.fluxCollection -import com.sadellie.unitto.data.converter.collections.forceCollection -import com.sadellie.unitto.data.converter.collections.fuelConsumptionCollection -import com.sadellie.unitto.data.converter.collections.lengthCollection -import com.sadellie.unitto.data.converter.collections.luminanceCollection -import com.sadellie.unitto.data.converter.collections.massCollection -import com.sadellie.unitto.data.converter.collections.numberBaseCollection -import com.sadellie.unitto.data.converter.collections.powerCollection -import com.sadellie.unitto.data.converter.collections.prefixCollection -import com.sadellie.unitto.data.converter.collections.pressureCollection -import com.sadellie.unitto.data.converter.collections.speedCollection -import com.sadellie.unitto.data.converter.collections.temperatureCollection -import com.sadellie.unitto.data.converter.collections.timeCollection -import com.sadellie.unitto.data.converter.collections.torqueCollection -import com.sadellie.unitto.data.converter.collections.volumeCollection -import com.sadellie.unitto.data.converter.remote.CurrencyApi -import com.sadellie.unitto.data.database.CurrencyRatesDao -import com.sadellie.unitto.data.database.CurrencyRatesEntity -import com.sadellie.unitto.data.database.UnitsDao -import com.sadellie.unitto.data.database.UnitsEntity -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.repository.UnitsRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit -import com.sadellie.unitto.data.model.unit.filterByLev -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.withContext -import java.math.BigDecimal -import java.time.LocalDate -import javax.inject.Inject - -class UnitsRepositoryImpl @Inject constructor( - private val unitsDao: UnitsDao, - private val currencyRatesDao: CurrencyRatesDao, - @ApplicationContext private val mContext: Context, -) : UnitsRepository { - private val _inMemoryUnits = MutableStateFlow( - lengthCollection + - currencyCollection + - massCollection + - speedCollection + - temperatureCollection + - areaCollection + - timeCollection + - volumeCollection + - dataCollection + - pressureCollection + - accelerationCollection + - energyCollection + - powerCollection + - angleCollection + - dataTransferCollection + - fluxCollection + - numberBaseCollection + - electrostaticCapacitance + - prefixCollection + - forceCollection + - torqueCollection + - flowRateCollection + - luminanceCollection + - fuelConsumptionCollection - ) - - override val units: Flow> = combine( - unitsDao.getAllFlow(), - _inMemoryUnits - ) { basedList, inMemoryList -> - return@combine inMemoryList.map { inMemoryUnit -> - val inBaseUnit = basedList.find { it.unitId == inMemoryUnit.id } - ?: return@map inMemoryUnit - inMemoryUnit.clone( - isFavorite = inBaseUnit.isFavorite, - counter = inBaseUnit.frequency, - pairId = inBaseUnit.pairedUnitId - ) - } - } - .flowOn(Dispatchers.IO) - - override suspend fun getById(id: String): AbstractUnit { - return units.first().first { it.id == id } - } - - override suspend fun getCollection(group: UnitGroup): List { - return units.first().filter { it.group == group } - } - - override suspend fun favorite(unit: AbstractUnit) = withContext(Dispatchers.IO) { - val basedUnit = unitsDao.getById(unit.id) - - if (basedUnit == null) { - unitsDao.insertUnit( - UnitsEntity( - unitId = unit.id, - isFavorite = true - ) - ) - } else { - unitsDao.insertUnit( - UnitsEntity( - unitId = basedUnit.unitId, - isFavorite = !basedUnit.isFavorite, - pairedUnitId = basedUnit.pairedUnitId, - frequency = basedUnit.frequency - ) - ) - } - } - - override suspend fun incrementCounter(unit: AbstractUnit) = withContext(Dispatchers.IO) { - val basedUnit = unitsDao.getById(unit.id) - - if (basedUnit == null) { - unitsDao.insertUnit( - UnitsEntity( - unitId = unit.id, - frequency = 1 - ) - ) - } else { - unitsDao.insertUnit( - UnitsEntity( - unitId = basedUnit.unitId, - isFavorite = basedUnit.isFavorite, - pairedUnitId = basedUnit.pairedUnitId, - frequency = basedUnit.frequency + 1 - ) - ) - } - } - - override suspend fun setPair(unit: AbstractUnit, pair: AbstractUnit) = withContext(Dispatchers.IO) { - val basedUnit = unitsDao.getById(unit.id) - - if (basedUnit == null) { - unitsDao.insertUnit( - UnitsEntity( - unitId = unit.id, - pairedUnitId = pair.id - ) - ) - } else { - unitsDao.insertUnit( - UnitsEntity( - unitId = basedUnit.unitId, - isFavorite = basedUnit.isFavorite, - pairedUnitId = pair.id, - frequency = basedUnit.frequency - ) - ) - } - } - - override suspend fun updateRates(unit: AbstractUnit): LocalDate? = withContext(Dispatchers.IO) { - var basedConversions = currencyRatesDao.getLatestRates(baseId = unit.id) - val epochDay = LocalDate.now().toEpochDay() - - if (basedConversions.firstOrNull()?.date != epochDay) { - try { - val conversions = CurrencyApi.service.getCurrencyPairs(unit.id) - val rates = conversions.currency - .map { (pairId, pairValue) -> - CurrencyRatesEntity( - baseUnitId = unit.id, - date = epochDay, - pairUnitId = pairId, - pairUnitValue = BigDecimal.valueOf(pairValue) - ) - } - currencyRatesDao.insertRates(rates) - - basedConversions = currencyRatesDao.getLatestRates(baseId = unit.id) - } catch (e: Exception) { - Log.d("UnitsRepository", "Skipped update: $e") - } - } - _inMemoryUnits.update { units -> - units.map { localUnit -> - if (localUnit.group != UnitGroup.CURRENCY) return@map localUnit - if (localUnit !is ReverseUnit) return@map localUnit - - val rate = basedConversions - .firstOrNull { localUnit.id == it.pairUnitId } - ?.pairUnitValue ?: BigDecimal.ZERO - - return@map if (rate > BigDecimal.ZERO) { - localUnit.copy(basicUnit = rate) - } else { - localUnit.copy(basicUnit = BigDecimal.ZERO) - } - } - } - - return@withContext basedConversions - .firstOrNull() - ?.date - ?.let { LocalDate.ofEpochDay(it) } - } - - override suspend fun filterUnits( - query: String, - unitGroup: UnitGroup?, - favoritesOnly: Boolean, - hideBrokenUnits: Boolean, - sorting: UnitsListSorting, - shownUnitGroups: List, - ): Map> { - // Leave only shown unit groups - var units: Sequence = if (unitGroup == null) { - units.first().filter { it.group in shownUnitGroups } - } else { - getCollection(unitGroup) - }.asSequence() - - if (favoritesOnly) { - units = units.filter { it.isFavorite } - } - if (hideBrokenUnits) { - units = units.filter { it.basicUnit > BigDecimal.ZERO } - } - - units = when (sorting) { - UnitsListSorting.USAGE -> units.sortedByDescending { it.counter } - UnitsListSorting.ALPHABETICAL -> units.sortedBy { mContext.getString(it.displayName) } - UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit } - UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit } - else -> units - } - - units = if (query.isEmpty()) { - units.sortedByDescending { it.isFavorite } - } else { - // For search we sort by popularity and Levenshtein distance (short and long name). - units.filterByLev(query, mContext) - } - return units.groupBy { it.group } - } -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt deleted file mode 100644 index 550b3e23..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -internal val accelerationCollection: List by lazy { - listOf( - NormalUnit(UnitID.attometer_per_square_second, BigDecimal.valueOf(1), UnitGroup.ACCELERATION, R.string.unit_attometer_per_square_second, R.string.unit_attometer_per_square_second_short), - NormalUnit(UnitID.femtometer_per_square_second, BigDecimal.valueOf(1E+3), UnitGroup.ACCELERATION, R.string.unit_femtometer_per_square_second, R.string.unit_femtometer_per_square_second_short), - NormalUnit(UnitID.picometer_per_square_second, BigDecimal.valueOf(1E+6), UnitGroup.ACCELERATION, R.string.unit_picometer_per_square_second, R.string.unit_picometer_per_square_second_short), - NormalUnit(UnitID.nanometer_per_square_second, BigDecimal.valueOf(1E+9), UnitGroup.ACCELERATION, R.string.unit_nanometer_per_square_second, R.string.unit_nanometer_per_square_second_short), - NormalUnit(UnitID.micrometer_per_square_second, BigDecimal.valueOf(1E+12), UnitGroup.ACCELERATION, R.string.unit_micrometer_per_square_second, R.string.unit_micrometer_per_square_second_short), - NormalUnit(UnitID.millimeter_per_square_second, BigDecimal.valueOf(1E+15), UnitGroup.ACCELERATION, R.string.unit_millimeter_per_square_second, R.string.unit_millimeter_per_square_second_short), - NormalUnit(UnitID.centimeter_per_square_second, BigDecimal.valueOf(1E+16), UnitGroup.ACCELERATION, R.string.unit_centimeter_per_square_second, R.string.unit_centimeter_per_square_second_short), - NormalUnit(UnitID.decimeter_per_square_second, BigDecimal.valueOf(1E+17), UnitGroup.ACCELERATION, R.string.unit_decimeter_per_square_second, R.string.unit_decimeter_per_square_second_short), - NormalUnit(UnitID.meter_per_square_second, BigDecimal.valueOf(1E+18), UnitGroup.ACCELERATION, R.string.unit_meter_per_square_second, R.string.unit_meter_per_square_second_short), - NormalUnit(UnitID.kilometer_per_square_second, BigDecimal.valueOf(1E+21), UnitGroup.ACCELERATION, R.string.unit_kilometer_per_square_second, R.string.unit_kilometer_per_square_second_short), - NormalUnit(UnitID.dekameter_per_square_second, BigDecimal.valueOf(1E+19), UnitGroup.ACCELERATION, R.string.unit_dekameter_per_square_second, R.string.unit_dekameter_per_square_second_short), - NormalUnit(UnitID.hectometer_per_square_second, BigDecimal.valueOf(1E+20), UnitGroup.ACCELERATION, R.string.unit_hectometer_per_square_second, R.string.unit_hectometer_per_square_second_short), - NormalUnit(UnitID.gal, BigDecimal.valueOf(1E+16), UnitGroup.ACCELERATION, R.string.unit_gal, R.string.unit_gal_short), - NormalUnit(UnitID.mercury_surface_gravity, BigDecimal.valueOf(3.7E+18), UnitGroup.ACCELERATION, R.string.unit_mercury_surface_gravity, R.string.unit_mercury_surface_gravity_short), - NormalUnit(UnitID.venus_surface_gravity, BigDecimal.valueOf(8.87E+18), UnitGroup.ACCELERATION, R.string.unit_venus_surface_gravity, R.string.unit_venus_surface_gravity_short), - NormalUnit(UnitID.earth_surface_gravity, BigDecimal.valueOf(9.80655E+18), UnitGroup.ACCELERATION, R.string.unit_earth_surface_gravity, R.string.unit_earth_surface_gravity_short), - NormalUnit(UnitID.mars_surface_gravity, BigDecimal.valueOf(3.71E+18), UnitGroup.ACCELERATION, R.string.unit_mars_surface_gravity, R.string.unit_mars_surface_gravity_short), - NormalUnit(UnitID.jupiter_surface_gravity, BigDecimal.valueOf(2.479E+19), UnitGroup.ACCELERATION, R.string.unit_jupiter_surface_gravity, R.string.unit_jupiter_surface_gravity_short), - NormalUnit(UnitID.saturn_surface_gravity, BigDecimal.valueOf(1.044E+19), UnitGroup.ACCELERATION, R.string.unit_saturn_surface_gravity, R.string.unit_saturn_surface_gravity_short), - NormalUnit(UnitID.uranus_surface_gravity, BigDecimal.valueOf(8.87E+18), UnitGroup.ACCELERATION, R.string.unit_uranus_surface_gravity, R.string.unit_uranus_surface_gravity_short), - NormalUnit(UnitID.neptune_surface_gravity, BigDecimal.valueOf(1.115E+19), UnitGroup.ACCELERATION, R.string.unit_neptune_surface_gravity, R.string.unit_neptune_surface_gravity_short), - NormalUnit(UnitID.sun_surface_gravity, BigDecimal.valueOf(2.74E+20), UnitGroup.ACCELERATION, R.string.unit_sun_surface_gravity, R.string.unit_sun_surface_gravity_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt deleted file mode 100644 index 1ab225c6..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val angleCollection: List by lazy { - listOf( - NormalUnit(UnitID.angle_second, BigDecimal.valueOf(1), UnitGroup.ANGLE, R.string.unit_angle_second, R.string.unit_angle_second_short), - NormalUnit(UnitID.angle_minute, BigDecimal.valueOf(60), UnitGroup.ANGLE, R.string.unit_angle_minute, R.string.unit_angle_minute_short), - NormalUnit(UnitID.degree, BigDecimal.valueOf(3600), UnitGroup.ANGLE, R.string.unit_degree, R.string.unit_degree_short), - NormalUnit(UnitID.radian, BigDecimal.valueOf(206264.8062471), UnitGroup.ANGLE, R.string.unit_radian, R.string.unit_radian_short), - NormalUnit(UnitID.sextant, BigDecimal.valueOf(216000), UnitGroup.ANGLE, R.string.unit_sextant, R.string.unit_sextant_short), - NormalUnit(UnitID.turn, BigDecimal.valueOf(1296000), UnitGroup.ANGLE, R.string.unit_turn, R.string.unit_turn_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt deleted file mode 100644 index 998e7c91..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val areaCollection: List by lazy { - listOf( - NormalUnit(UnitID.cent, BigDecimal.valueOf(6.083246572E+33), UnitGroup.AREA, R.string.unit_cent, R.string.unit_cent_short), - NormalUnit(UnitID.acre, BigDecimal.valueOf(6.083246572E+31), UnitGroup.AREA, R.string.unit_acre, R.string.unit_acre_short), - NormalUnit(UnitID.hectare, BigDecimal.valueOf(1.503202964E+32), UnitGroup.AREA, R.string.unit_hectare, R.string.unit_hectare_short ), - NormalUnit(UnitID.square_foot, BigDecimal.valueOf(1.396521251E+27), UnitGroup.AREA, R.string.unit_square_foot, R.string.unit_square_foot_short), - NormalUnit(UnitID.square_mile, BigDecimal.valueOf(3.893277806E+34), UnitGroup.AREA, R.string.unit_square_mile, R.string.unit_square_mile_short), - NormalUnit(UnitID.square_yard, BigDecimal.valueOf(1.256869126E+28), UnitGroup.AREA, R.string.unit_square_yard, R.string.unit_square_yard_short), - NormalUnit(UnitID.square_inch, BigDecimal.valueOf(9.698064247E+24), UnitGroup.AREA, R.string.unit_square_inch, R.string.unit_square_inch_short), - NormalUnit(UnitID.square_micrometer, BigDecimal.valueOf(1.503202964E+16), UnitGroup.AREA, R.string.unit_square_micrometer, R.string.unit_square_micrometer_short), - NormalUnit(UnitID.square_millimeter, BigDecimal.valueOf(1.503202964E+22), UnitGroup.AREA, R.string.unit_square_millimeter, R.string.unit_square_millimeter_short), - NormalUnit(UnitID.square_centimeter, BigDecimal.valueOf(1.503202964E+24), UnitGroup.AREA, R.string.unit_square_centimeter, R.string.unit_square_centimeter_short), - NormalUnit(UnitID.square_decimeter, BigDecimal.valueOf(1.503202964E+26), UnitGroup.AREA, R.string.unit_square_decimeter, R.string.unit_square_decimeter_short), - NormalUnit(UnitID.square_meter, BigDecimal.valueOf(1.503202964E+28), UnitGroup.AREA, R.string.unit_square_meter, R.string.unit_square_meter_short), - NormalUnit(UnitID.square_kilometer, BigDecimal.valueOf(1.503202964E+34), UnitGroup.AREA, R.string.unit_square_kilometer, R.string.unit_square_kilometer_short), - NormalUnit(UnitID.electron_cross_section, BigDecimal.valueOf(1.0), UnitGroup.AREA, R.string.unit_electron_cross_section, R.string.unit_electron_cross_section_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt deleted file mode 100644 index d49bb180..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val currencyCollection: List by lazy { - listOf( - ReverseUnit(UnitID.currency_1inch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_1inch, R.string.unit_currency_1inch_short), - ReverseUnit(UnitID.currency_ada, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ada, R.string.unit_currency_ada_short), - ReverseUnit(UnitID.currency_aed, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aed, R.string.unit_currency_aed_short), - ReverseUnit(UnitID.currency_afn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_afn, R.string.unit_currency_afn_short), - ReverseUnit(UnitID.currency_algo, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_algo, R.string.unit_currency_algo_short), - ReverseUnit(UnitID.currency_all, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_all, R.string.unit_currency_all_short), - ReverseUnit(UnitID.currency_amd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_amd, R.string.unit_currency_amd_short), - ReverseUnit(UnitID.currency_ang, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ang, R.string.unit_currency_ang_short), - ReverseUnit(UnitID.currency_aoa, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aoa, R.string.unit_currency_aoa_short), - ReverseUnit(UnitID.currency_ars, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ars, R.string.unit_currency_ars_short), - ReverseUnit(UnitID.currency_atom, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_atom, R.string.unit_currency_atom_short), - ReverseUnit(UnitID.currency_aud, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aud, R.string.unit_currency_aud_short), - ReverseUnit(UnitID.currency_avax, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_avax, R.string.unit_currency_avax_short), - ReverseUnit(UnitID.currency_awg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_awg, R.string.unit_currency_awg_short), - ReverseUnit(UnitID.currency_azn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_azn, R.string.unit_currency_azn_short), - ReverseUnit(UnitID.currency_bam, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bam, R.string.unit_currency_bam_short), - ReverseUnit(UnitID.currency_bbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bbd, R.string.unit_currency_bbd_short), - ReverseUnit(UnitID.currency_bch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bch, R.string.unit_currency_bch_short), - ReverseUnit(UnitID.currency_bdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bdt, R.string.unit_currency_bdt_short), - ReverseUnit(UnitID.currency_bgn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bgn, R.string.unit_currency_bgn_short), - ReverseUnit(UnitID.currency_bhd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bhd, R.string.unit_currency_bhd_short), - ReverseUnit(UnitID.currency_bif, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bif, R.string.unit_currency_bif_short), - ReverseUnit(UnitID.currency_bmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bmd, R.string.unit_currency_bmd_short), - ReverseUnit(UnitID.currency_bnb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnb, R.string.unit_currency_bnb_short), - ReverseUnit(UnitID.currency_bnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnd, R.string.unit_currency_bnd_short), - ReverseUnit(UnitID.currency_bob, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bob, R.string.unit_currency_bob_short), - ReverseUnit(UnitID.currency_brl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_brl, R.string.unit_currency_brl_short), - ReverseUnit(UnitID.currency_bsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bsd, R.string.unit_currency_bsd_short), - ReverseUnit(UnitID.currency_btc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btc, R.string.unit_currency_btc_short), - ReverseUnit(UnitID.currency_btn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btn, R.string.unit_currency_btn_short), - ReverseUnit(UnitID.currency_busd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_busd, R.string.unit_currency_busd_short), - ReverseUnit(UnitID.currency_bwp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bwp, R.string.unit_currency_bwp_short), - ReverseUnit(UnitID.currency_byn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byn, R.string.unit_currency_byn_short), - ReverseUnit(UnitID.currency_byr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byr, R.string.unit_currency_byr_short), - ReverseUnit(UnitID.currency_bzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bzd, R.string.unit_currency_bzd_short), - ReverseUnit(UnitID.currency_cad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cad, R.string.unit_currency_cad_short), - ReverseUnit(UnitID.currency_cdf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cdf, R.string.unit_currency_cdf_short), - ReverseUnit(UnitID.currency_chf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chf, R.string.unit_currency_chf_short), - ReverseUnit(UnitID.currency_chz, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chz, R.string.unit_currency_chz_short), - ReverseUnit(UnitID.currency_clf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clf, R.string.unit_currency_clf_short), - ReverseUnit(UnitID.currency_clp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clp, R.string.unit_currency_clp_short), - ReverseUnit(UnitID.currency_cny, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cny, R.string.unit_currency_cny_short), - ReverseUnit(UnitID.currency_cop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cop, R.string.unit_currency_cop_short), - ReverseUnit(UnitID.currency_crc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_crc, R.string.unit_currency_crc_short), - ReverseUnit(UnitID.currency_cro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cro, R.string.unit_currency_cro_short), - ReverseUnit(UnitID.currency_cuc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cuc, R.string.unit_currency_cuc_short), - ReverseUnit(UnitID.currency_cup, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cup, R.string.unit_currency_cup_short), - ReverseUnit(UnitID.currency_cve, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cve, R.string.unit_currency_cve_short), - ReverseUnit(UnitID.currency_czk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_czk, R.string.unit_currency_czk_short), - ReverseUnit(UnitID.currency_dai, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dai, R.string.unit_currency_dai_short), - ReverseUnit(UnitID.currency_djf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_djf, R.string.unit_currency_djf_short), - ReverseUnit(UnitID.currency_dkk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dkk, R.string.unit_currency_dkk_short), - ReverseUnit(UnitID.currency_doge, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_doge, R.string.unit_currency_doge_short), - ReverseUnit(UnitID.currency_dop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dop, R.string.unit_currency_dop_short), - ReverseUnit(UnitID.currency_dot, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dot, R.string.unit_currency_dot_short), - ReverseUnit(UnitID.currency_dzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dzd, R.string.unit_currency_dzd_short), - ReverseUnit(UnitID.currency_egld, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egld, R.string.unit_currency_egld_short), - ReverseUnit(UnitID.currency_egp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egp, R.string.unit_currency_egp_short), - ReverseUnit(UnitID.currency_enj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_enj, R.string.unit_currency_enj_short), - ReverseUnit(UnitID.currency_ern, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ern, R.string.unit_currency_ern_short), - ReverseUnit(UnitID.currency_etb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etb, R.string.unit_currency_etb_short), - ReverseUnit(UnitID.currency_etc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etc, R.string.unit_currency_etc_short), - ReverseUnit(UnitID.currency_eth, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eth, R.string.unit_currency_eth_short), - ReverseUnit(UnitID.currency_eur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eur, R.string.unit_currency_eur_short), - ReverseUnit(UnitID.currency_fil, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fil, R.string.unit_currency_fil_short), - ReverseUnit(UnitID.currency_fjd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fjd, R.string.unit_currency_fjd_short), - ReverseUnit(UnitID.currency_fkp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fkp, R.string.unit_currency_fkp_short), - ReverseUnit(UnitID.currency_ftt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ftt, R.string.unit_currency_ftt_short), - ReverseUnit(UnitID.currency_gbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gbp, R.string.unit_currency_gbp_short), - ReverseUnit(UnitID.currency_gel, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gel, R.string.unit_currency_gel_short), - ReverseUnit(UnitID.currency_ggp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ggp, R.string.unit_currency_ggp_short), - ReverseUnit(UnitID.currency_ghs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ghs, R.string.unit_currency_ghs_short), - ReverseUnit(UnitID.currency_gip, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gip, R.string.unit_currency_gip_short), - ReverseUnit(UnitID.currency_gmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gmd, R.string.unit_currency_gmd_short), - ReverseUnit(UnitID.currency_gnf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gnf, R.string.unit_currency_gnf_short), - ReverseUnit(UnitID.currency_grt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_grt, R.string.unit_currency_grt_short), - ReverseUnit(UnitID.currency_gtq, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gtq, R.string.unit_currency_gtq_short), - ReverseUnit(UnitID.currency_gyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gyd, R.string.unit_currency_gyd_short), - ReverseUnit(UnitID.currency_hkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hkd, R.string.unit_currency_hkd_short), - ReverseUnit(UnitID.currency_hnl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hnl, R.string.unit_currency_hnl_short), - ReverseUnit(UnitID.currency_hrk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hrk, R.string.unit_currency_hrk_short), - ReverseUnit(UnitID.currency_htg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_htg, R.string.unit_currency_htg_short), - ReverseUnit(UnitID.currency_huf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_huf, R.string.unit_currency_huf_short), - ReverseUnit(UnitID.currency_icp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_icp, R.string.unit_currency_icp_short), - ReverseUnit(UnitID.currency_idr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_idr, R.string.unit_currency_idr_short), - ReverseUnit(UnitID.currency_ils, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ils, R.string.unit_currency_ils_short), - ReverseUnit(UnitID.currency_imp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_imp, R.string.unit_currency_imp_short), - ReverseUnit(UnitID.currency_inj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inj, R.string.unit_currency_inj_short), - ReverseUnit(UnitID.currency_inr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inr, R.string.unit_currency_inr_short), - ReverseUnit(UnitID.currency_iqd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_iqd, R.string.unit_currency_iqd_short), - ReverseUnit(UnitID.currency_irr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_irr, R.string.unit_currency_irr_short), - ReverseUnit(UnitID.currency_isk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_isk, R.string.unit_currency_isk_short), - ReverseUnit(UnitID.currency_jep, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jep, R.string.unit_currency_jep_short), - ReverseUnit(UnitID.currency_jmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jmd, R.string.unit_currency_jmd_short), - ReverseUnit(UnitID.currency_jod, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jod, R.string.unit_currency_jod_short), - ReverseUnit(UnitID.currency_jpy, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jpy, R.string.unit_currency_jpy_short), - ReverseUnit(UnitID.currency_kes, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kes, R.string.unit_currency_kes_short), - ReverseUnit(UnitID.currency_kgs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kgs, R.string.unit_currency_kgs_short), - ReverseUnit(UnitID.currency_khr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_khr, R.string.unit_currency_khr_short), - ReverseUnit(UnitID.currency_kmf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kmf, R.string.unit_currency_kmf_short), - ReverseUnit(UnitID.currency_kpw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kpw, R.string.unit_currency_kpw_short), - ReverseUnit(UnitID.currency_krw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_krw, R.string.unit_currency_krw_short), - ReverseUnit(UnitID.currency_ksm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ksm, R.string.unit_currency_ksm_short), - ReverseUnit(UnitID.currency_kwd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kwd, R.string.unit_currency_kwd_short), - ReverseUnit(UnitID.currency_kyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kyd, R.string.unit_currency_kyd_short), - ReverseUnit(UnitID.currency_kzt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kzt, R.string.unit_currency_kzt_short), - ReverseUnit(UnitID.currency_lak, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lak, R.string.unit_currency_lak_short), - ReverseUnit(UnitID.currency_lbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lbp, R.string.unit_currency_lbp_short), - ReverseUnit(UnitID.currency_link, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_link, R.string.unit_currency_link_short), - ReverseUnit(UnitID.currency_lkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lkr, R.string.unit_currency_lkr_short), - ReverseUnit(UnitID.currency_lrd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lrd, R.string.unit_currency_lrd_short), - ReverseUnit(UnitID.currency_lsl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lsl, R.string.unit_currency_lsl_short), - ReverseUnit(UnitID.currency_ltc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltc, R.string.unit_currency_ltc_short), - ReverseUnit(UnitID.currency_ltl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltl, R.string.unit_currency_ltl_short), - ReverseUnit(UnitID.currency_luna, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_luna, R.string.unit_currency_luna_short), - ReverseUnit(UnitID.currency_lvl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lvl, R.string.unit_currency_lvl_short), - ReverseUnit(UnitID.currency_lyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lyd, R.string.unit_currency_lyd_short), - ReverseUnit(UnitID.currency_mad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mad, R.string.unit_currency_mad_short), - ReverseUnit(UnitID.currency_matic, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_matic, R.string.unit_currency_matic_short), - ReverseUnit(UnitID.currency_mdl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mdl, R.string.unit_currency_mdl_short), - ReverseUnit(UnitID.currency_mga, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mga, R.string.unit_currency_mga_short), - ReverseUnit(UnitID.currency_mkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mkd, R.string.unit_currency_mkd_short), - ReverseUnit(UnitID.currency_mmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mmk, R.string.unit_currency_mmk_short), - ReverseUnit(UnitID.currency_mnt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mnt, R.string.unit_currency_mnt_short), - ReverseUnit(UnitID.currency_mop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mop, R.string.unit_currency_mop_short), - ReverseUnit(UnitID.currency_mro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mro, R.string.unit_currency_mro_short), - ReverseUnit(UnitID.currency_mur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mur, R.string.unit_currency_mur_short), - ReverseUnit(UnitID.currency_mvr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mvr, R.string.unit_currency_mvr_short), - ReverseUnit(UnitID.currency_mwk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mwk, R.string.unit_currency_mwk_short), - ReverseUnit(UnitID.currency_mxn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mxn, R.string.unit_currency_mxn_short), - ReverseUnit(UnitID.currency_myr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_myr, R.string.unit_currency_myr_short), - ReverseUnit(UnitID.currency_mzn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mzn, R.string.unit_currency_mzn_short), - ReverseUnit(UnitID.currency_nad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nad, R.string.unit_currency_nad_short), - ReverseUnit(UnitID.currency_ngn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ngn, R.string.unit_currency_ngn_short), - ReverseUnit(UnitID.currency_nio, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nio, R.string.unit_currency_nio_short), - ReverseUnit(UnitID.currency_nok, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nok, R.string.unit_currency_nok_short), - ReverseUnit(UnitID.currency_npr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_npr, R.string.unit_currency_npr_short), - ReverseUnit(UnitID.currency_nzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nzd, R.string.unit_currency_nzd_short), - ReverseUnit(UnitID.currency_omr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_omr, R.string.unit_currency_omr_short), - ReverseUnit(UnitID.currency_one, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_one, R.string.unit_currency_one_short), - ReverseUnit(UnitID.currency_pab, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pab, R.string.unit_currency_pab_short), - ReverseUnit(UnitID.currency_pen, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pen, R.string.unit_currency_pen_short), - ReverseUnit(UnitID.currency_pgk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pgk, R.string.unit_currency_pgk_short), - ReverseUnit(UnitID.currency_php, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_php, R.string.unit_currency_php_short), - ReverseUnit(UnitID.currency_pkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pkr, R.string.unit_currency_pkr_short), - ReverseUnit(UnitID.currency_pln, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pln, R.string.unit_currency_pln_short), - ReverseUnit(UnitID.currency_pyg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pyg, R.string.unit_currency_pyg_short), - ReverseUnit(UnitID.currency_qar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_qar, R.string.unit_currency_qar_short), - ReverseUnit(UnitID.currency_ron, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ron, R.string.unit_currency_ron_short), - ReverseUnit(UnitID.currency_rsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rsd, R.string.unit_currency_rsd_short), - ReverseUnit(UnitID.currency_rub, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rub, R.string.unit_currency_rub_short), - ReverseUnit(UnitID.currency_rwf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rwf, R.string.unit_currency_rwf_short), - ReverseUnit(UnitID.currency_sar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sar, R.string.unit_currency_sar_short), - ReverseUnit(UnitID.currency_sbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sbd, R.string.unit_currency_sbd_short), - ReverseUnit(UnitID.currency_scr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_scr, R.string.unit_currency_scr_short), - ReverseUnit(UnitID.currency_sdg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sdg, R.string.unit_currency_sdg_short), - ReverseUnit(UnitID.currency_sek, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sek, R.string.unit_currency_sek_short), - ReverseUnit(UnitID.currency_sgd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sgd, R.string.unit_currency_sgd_short), - ReverseUnit(UnitID.currency_shib, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shib, R.string.unit_currency_shib_short), - ReverseUnit(UnitID.currency_shp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shp, R.string.unit_currency_shp_short), - ReverseUnit(UnitID.currency_sll, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sll, R.string.unit_currency_sll_short), - ReverseUnit(UnitID.currency_sol, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sol, R.string.unit_currency_sol_short), - ReverseUnit(UnitID.currency_sos, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sos, R.string.unit_currency_sos_short), - ReverseUnit(UnitID.currency_srd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_srd, R.string.unit_currency_srd_short), - ReverseUnit(UnitID.currency_std, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_std, R.string.unit_currency_std_short), - ReverseUnit(UnitID.currency_svc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_svc, R.string.unit_currency_svc_short), - ReverseUnit(UnitID.currency_syp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_syp, R.string.unit_currency_syp_short), - ReverseUnit(UnitID.currency_szl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_szl, R.string.unit_currency_szl_short), - ReverseUnit(UnitID.currency_thb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_thb, R.string.unit_currency_thb_short), - ReverseUnit(UnitID.currency_theta, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_theta, R.string.unit_currency_theta_short), - ReverseUnit(UnitID.currency_tjs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tjs, R.string.unit_currency_tjs_short), - ReverseUnit(UnitID.currency_tmt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tmt, R.string.unit_currency_tmt_short), - ReverseUnit(UnitID.currency_tnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tnd, R.string.unit_currency_tnd_short), - ReverseUnit(UnitID.currency_top, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_top, R.string.unit_currency_top_short), - ReverseUnit(UnitID.currency_trx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_trx, R.string.unit_currency_trx_short), - ReverseUnit(UnitID.currency_try, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_try, R.string.unit_currency_try_short), - ReverseUnit(UnitID.currency_ttd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ttd, R.string.unit_currency_ttd_short), - ReverseUnit(UnitID.currency_twd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_twd, R.string.unit_currency_twd_short), - ReverseUnit(UnitID.currency_tzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tzs, R.string.unit_currency_tzs_short), - ReverseUnit(UnitID.currency_uah, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uah, R.string.unit_currency_uah_short), - ReverseUnit(UnitID.currency_ugx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ugx, R.string.unit_currency_ugx_short), - ReverseUnit(UnitID.currency_uni, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uni, R.string.unit_currency_uni_short), - ReverseUnit(UnitID.currency_usd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usd, R.string.unit_currency_usd_short), - ReverseUnit(UnitID.currency_usdc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdc, R.string.unit_currency_usdc_short), - ReverseUnit(UnitID.currency_usdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdt, R.string.unit_currency_usdt_short), - ReverseUnit(UnitID.currency_uyu, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uyu, R.string.unit_currency_uyu_short), - ReverseUnit(UnitID.currency_uzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uzs, R.string.unit_currency_uzs_short), - ReverseUnit(UnitID.currency_vef, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vef, R.string.unit_currency_vef_short), - ReverseUnit(UnitID.currency_vet, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vet, R.string.unit_currency_vet_short), - ReverseUnit(UnitID.currency_vnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vnd, R.string.unit_currency_vnd_short), - ReverseUnit(UnitID.currency_vuv, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vuv, R.string.unit_currency_vuv_short), - ReverseUnit(UnitID.currency_wbtc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wbtc, R.string.unit_currency_wbtc_short), - ReverseUnit(UnitID.currency_wst, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wst, R.string.unit_currency_wst_short), - ReverseUnit(UnitID.currency_xaf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xaf, R.string.unit_currency_xaf_short), - ReverseUnit(UnitID.currency_xag, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xag, R.string.unit_currency_xag_short), - ReverseUnit(UnitID.currency_xau, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xau, R.string.unit_currency_xau_short), - ReverseUnit(UnitID.currency_xcd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xcd, R.string.unit_currency_xcd_short), - ReverseUnit(UnitID.currency_xdr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xdr, R.string.unit_currency_xdr_short), - ReverseUnit(UnitID.currency_xlm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xlm, R.string.unit_currency_xlm_short), - ReverseUnit(UnitID.currency_xmr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xmr, R.string.unit_currency_xmr_short), - ReverseUnit(UnitID.currency_xof, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xof, R.string.unit_currency_xof_short), - ReverseUnit(UnitID.currency_xpf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xpf, R.string.unit_currency_xpf_short), - ReverseUnit(UnitID.currency_xrp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xrp, R.string.unit_currency_xrp_short), - ReverseUnit(UnitID.currency_yer, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_yer, R.string.unit_currency_yer_short), - ReverseUnit(UnitID.currency_zar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zar, R.string.unit_currency_zar_short), - ReverseUnit(UnitID.currency_zmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmk, R.string.unit_currency_zmk_short), - ReverseUnit(UnitID.currency_zmw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmw, R.string.unit_currency_zmw_short), - ReverseUnit(UnitID.currency_zwl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zwl, R.string.unit_currency_zwl_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt deleted file mode 100644 index 6a34e733..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val dataCollection: List by lazy { - listOf( - NormalUnit(UnitID.bit, BigDecimal.valueOf(1), UnitGroup.DATA, R.string.unit_bit, R.string.unit_bit_short), - NormalUnit(UnitID.kibibit, BigDecimal.valueOf(1_024), UnitGroup.DATA, R.string.unit_kibibit, R.string.unit_kibibit_short), - NormalUnit(UnitID.kilobit, BigDecimal.valueOf(1_000), UnitGroup.DATA, R.string.unit_kilobit, R.string.unit_kilobit_short), - NormalUnit(UnitID.megabit, BigDecimal.valueOf(1_000_000), UnitGroup.DATA, R.string.unit_megabit, R.string.unit_megabit_short), - NormalUnit(UnitID.mebibit, BigDecimal.valueOf(1_048_576), UnitGroup.DATA, R.string.unit_mebibit, R.string.unit_mebibit_short), - NormalUnit(UnitID.gigabit, BigDecimal.valueOf(1_000_000_000), UnitGroup.DATA, R.string.unit_gigabit, R.string.unit_gigabit_short), - NormalUnit(UnitID.gibibit, BigDecimal.valueOf(1_073_741_824), UnitGroup.DATA, R.string.unit_gibibit, R.string.unit_gibibit_short), - NormalUnit(UnitID.terabit, BigDecimal.valueOf(1_000_000_000_000), UnitGroup.DATA, R.string.unit_terabit, R.string.unit_terabit_short), - NormalUnit(UnitID.petabit, BigDecimal.valueOf(1_000_000_000_000_000), UnitGroup.DATA, R.string.unit_petabit, R.string.unit_petabit_short), - NormalUnit(UnitID.exabit, BigDecimal.valueOf(1_000_000_000_000_000_000), UnitGroup.DATA, R.string.unit_exabit, R.string.unit_exabit_short), - NormalUnit(UnitID.byte, BigDecimal.valueOf(8), UnitGroup.DATA, R.string.unit_byte, R.string.unit_byte_short), - NormalUnit(UnitID.kibibyte, BigDecimal.valueOf(8_192), UnitGroup.DATA, R.string.unit_kibibyte, R.string.unit_kibibyte_short), - NormalUnit(UnitID.kilobyte, BigDecimal.valueOf(8_000), UnitGroup.DATA, R.string.unit_kilobyte, R.string.unit_kilobyte_short), - NormalUnit(UnitID.megabyte, BigDecimal.valueOf(8_000_000), UnitGroup.DATA, R.string.unit_megabyte, R.string.unit_megabyte_short), - NormalUnit(UnitID.mebibyte, BigDecimal.valueOf(8_388_608), UnitGroup.DATA, R.string.unit_mebibyte, R.string.unit_mebibyte_short), - NormalUnit(UnitID.gigabyte, BigDecimal.valueOf(8_000_000_000), UnitGroup.DATA, R.string.unit_gigabyte, R.string.unit_gigabyte_short), - NormalUnit(UnitID.gibibyte, BigDecimal.valueOf(8_589_934_592), UnitGroup.DATA, R.string.unit_gibibyte, R.string.unit_gibibyte_short), - NormalUnit(UnitID.terabyte, BigDecimal.valueOf(8_000_000_000_000), UnitGroup.DATA, R.string.unit_terabyte, R.string.unit_terabyte_short), - NormalUnit(UnitID.petabyte, BigDecimal.valueOf(8_000_000_000_000_000), UnitGroup.DATA, R.string.unit_petabyte, R.string.unit_petabyte_short), - NormalUnit(UnitID.exabyte, BigDecimal.valueOf(8_000_000_000_000_000_000), UnitGroup.DATA, R.string.unit_exabyte, R.string.unit_exabyte_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt deleted file mode 100644 index 87ee983f..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val dataTransferCollection: List by lazy { - listOf( - NormalUnit(UnitID.bit_per_second, BigDecimal.valueOf(1), UnitGroup.DATA_TRANSFER, R.string.unit_bit_per_second, R.string.unit_bit_per_second_short), - NormalUnit(UnitID.kibibit_per_second, BigDecimal.valueOf(1_024), UnitGroup.DATA_TRANSFER, R.string.unit_kibibit_per_second, R.string.unit_kibibit_per_second_short), - NormalUnit(UnitID.kilobit_per_second, BigDecimal.valueOf(1_000), UnitGroup.DATA_TRANSFER, R.string.unit_kilobit_per_second, R.string.unit_kilobit_per_second_short), - NormalUnit(UnitID.megabit_per_second, BigDecimal.valueOf(1_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_megabit_per_second, R.string.unit_megabit_per_second_short), - NormalUnit(UnitID.mebibit_per_second, BigDecimal.valueOf(1_048_576), UnitGroup.DATA_TRANSFER, R.string.unit_mebibit_per_second, R.string.unit_mebibit_per_second_short), - NormalUnit(UnitID.gigabit_per_second, BigDecimal.valueOf(1_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_gigabit_per_second, R.string.unit_gigabit_per_second_short), - NormalUnit(UnitID.gibibit_per_second, BigDecimal.valueOf(1_073_741_824), UnitGroup.DATA_TRANSFER, R.string.unit_gibibit_per_second, R.string.unit_gibibit_per_second_short), - NormalUnit(UnitID.terabit_per_second, BigDecimal.valueOf(1_000_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_terabit_per_second, R.string.unit_terabit_per_second_short), - NormalUnit(UnitID.petabit_per_second, BigDecimal.valueOf(1_000_000_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_petabit_per_second, R.string.unit_petabit_per_second_short), - NormalUnit(UnitID.exabit_per_second, BigDecimal.valueOf(1_000_000_000_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_exabit_per_second, R.string.unit_exabit_per_second_short), - NormalUnit(UnitID.byte_per_second, BigDecimal.valueOf(8), UnitGroup.DATA_TRANSFER, R.string.unit_byte_per_second, R.string.unit_byte_per_second_short), - NormalUnit(UnitID.kibibyte_per_second, BigDecimal.valueOf(8_192), UnitGroup.DATA_TRANSFER, R.string.unit_kibibyte_per_second, R.string.unit_kibibyte_per_second_short), - NormalUnit(UnitID.kilobyte_per_second, BigDecimal.valueOf(8_000), UnitGroup.DATA_TRANSFER, R.string.unit_kilobyte_per_second, R.string.unit_kilobyte_per_second_short), - NormalUnit(UnitID.megabyte_per_second, BigDecimal.valueOf(8_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_megabyte_per_second, R.string.unit_megabyte_per_second_short), - NormalUnit(UnitID.mebibyte_per_second, BigDecimal.valueOf(8_388_608), UnitGroup.DATA_TRANSFER, R.string.unit_mebibyte_per_second, R.string.unit_mebibyte_per_second_short), - NormalUnit(UnitID.gigabyte_per_second, BigDecimal.valueOf(8_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_gigabyte_per_second, R.string.unit_gigabyte_per_second_short), - NormalUnit(UnitID.gibibyte_per_second, BigDecimal.valueOf(8_589_934_592), UnitGroup.DATA_TRANSFER, R.string.unit_gibibyte_per_second, R.string.unit_gibibyte_per_second_short), - NormalUnit(UnitID.terabyte_per_second, BigDecimal.valueOf(8_000_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_terabyte_per_second, R.string.unit_terabyte_per_second_short), - NormalUnit(UnitID.petabyte_per_second, BigDecimal.valueOf(8_000_000_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_petabyte_per_second, R.string.unit_petabyte_per_second_short), - NormalUnit(UnitID.exabyte_per_second, BigDecimal.valueOf(8_000_000_000_000_000_000), UnitGroup.DATA_TRANSFER, R.string.unit_exabyte_per_second, R.string.unit_exabyte_per_second_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt deleted file mode 100644 index 2f1b3f9b..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val electrostaticCapacitance: List by lazy { - listOf( - NormalUnit(UnitID.attofarad, BigDecimal.valueOf(1), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_attofarad, R.string.unit_attofarad_short), - NormalUnit(UnitID.picofarad, BigDecimal.valueOf(1E+6), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_picofarad, R.string.unit_picofarad_short), - NormalUnit(UnitID.statfarad, BigDecimal.valueOf(1112650.0561), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_statfarad, R.string.unit_statfarad_short), - NormalUnit(UnitID.nanofarad, BigDecimal.valueOf(1E+9), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_nanofarad, R.string.unit_nanofarad_short), - NormalUnit(UnitID.microfarad, BigDecimal.valueOf(1E+12), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_microfarad, R.string.unit_microfarad_short), - NormalUnit(UnitID.millifarad, BigDecimal.valueOf(1E+15), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_millifarad, R.string.unit_millifarad_short), - NormalUnit(UnitID.farad, BigDecimal.valueOf(1E+18), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_farad, R.string.unit_farad_short), - NormalUnit(UnitID.kilofarad, BigDecimal.valueOf(1E+21), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_kilofarad, R.string.unit_kilofarad_short), - NormalUnit(UnitID.megafarad, BigDecimal.valueOf(1E+24), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_megafarad, R.string.unit_megafarad_short), - NormalUnit(UnitID.gigafarad, BigDecimal.valueOf(1E+27), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_gigafarad, R.string.unit_gigafarad_short), - NormalUnit(UnitID.petafarad, BigDecimal.valueOf(1E+33), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_petafarad, R.string.unit_petafarad_short), - NormalUnit(UnitID.exafarad, BigDecimal.valueOf(1E+36), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_exafarad, R.string.unit_exafarad_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt deleted file mode 100644 index 8101c72c..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val energyCollection: List by lazy { - listOf( - NormalUnit(UnitID.electron_volt, BigDecimal.valueOf(0.160217733), UnitGroup.ENERGY, R.string.unit_electron_volt, R.string.unit_electron_volt_short), - NormalUnit(UnitID.attojoule, BigDecimal.valueOf(1), UnitGroup.ENERGY, R.string.unit_attojoule, R.string.unit_attojoule_short), - NormalUnit(UnitID.joule, BigDecimal.valueOf(1E+18), UnitGroup.ENERGY, R.string.unit_joule, R.string.unit_joule_short), - NormalUnit(UnitID.kilojoule, BigDecimal.valueOf(1E+21), UnitGroup.ENERGY, R.string.unit_kilojoule, R.string.unit_kilojoule_short), - NormalUnit(UnitID.megajoule, BigDecimal.valueOf(1E+24), UnitGroup.ENERGY, R.string.unit_megajoule, R.string.unit_megajoule_short), - NormalUnit(UnitID.gigajoule, BigDecimal.valueOf(1E+27), UnitGroup.ENERGY, R.string.unit_gigajoule, R.string.unit_gigajoule_short), - NormalUnit(UnitID.energy_ton, BigDecimal.valueOf(4.184E+27), UnitGroup.ENERGY, R.string.unit_energy_ton, R.string.unit_energy_ton_short), - NormalUnit(UnitID.kiloton, BigDecimal.valueOf(4.184E+30), UnitGroup.ENERGY, R.string.unit_kiloton, R.string.unit_kiloton_short), - NormalUnit(UnitID.megaton, BigDecimal.valueOf(4.184E+33), UnitGroup.ENERGY, R.string.unit_megaton, R.string.unit_megaton_short), - NormalUnit(UnitID.gigaton, BigDecimal.valueOf(4.184E+36), UnitGroup.ENERGY, R.string.unit_gigaton, R.string.unit_gigaton_short), - NormalUnit(UnitID.energy_horse_power_metric, BigDecimal.valueOf(2.6477955E+24), UnitGroup.ENERGY, R.string.unit_energy_horse_power_metric, R.string.unit_energy_horse_power_metric_short), - NormalUnit(UnitID.calorie_th, BigDecimal.valueOf(4184E+15), UnitGroup.ENERGY, R.string.unit_calorie_th, R.string.unit_calorie_th_short), - NormalUnit(UnitID.kilocalorie_th, BigDecimal.valueOf(4184E+18), UnitGroup.ENERGY, R.string.unit_kilocalorie_th, R.string.unit_kilocalorie_th_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt deleted file mode 100644 index cfa7b6f7..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -val flowRateCollection: List by lazy { - listOf( - ReverseUnit(UnitID.liter_per_hour, BigDecimal.valueOf(3600000), UnitGroup.FLOW_RATE, R.string.unit_liter_per_hour, R.string.unit_liter_per_hour_short), - ReverseUnit(UnitID.liter_per_minute, BigDecimal.valueOf(60000), UnitGroup.FLOW_RATE, R.string.unit_liter_per_minute, R.string.unit_liter_per_minute_short), - ReverseUnit(UnitID.liter_per_second, BigDecimal.valueOf(1000), UnitGroup.FLOW_RATE, R.string.unit_liter_per_second, R.string.unit_liter_per_second_short), - ReverseUnit(UnitID.milliliter_per_hour, BigDecimal.valueOf(3600000000), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_hour, R.string.unit_milliliter_per_hour_short), - ReverseUnit(UnitID.milliliter_per_minute, BigDecimal.valueOf(60000000), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_minute, R.string.unit_milliliter_per_minute_short), - ReverseUnit(UnitID.milliliter_per_second, BigDecimal.valueOf(1000000), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_second, R.string.unit_milliliter_per_second_short), - ReverseUnit(UnitID.cubic_meter_per_hour, BigDecimal.valueOf(3600), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_hour, R.string.unit_cubic_meter_per_hour_short), - ReverseUnit(UnitID.cubic_meter_per_minute, BigDecimal.valueOf(60), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_minute, R.string.unit_cubic_meter_per_minute_short), - ReverseUnit(UnitID.cubic_meter_per_second, BigDecimal.valueOf(1), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_second, R.string.unit_cubic_meter_per_second_short), - ReverseUnit(UnitID.cubic_millimeter_per_hour, BigDecimal.valueOf(3600000000000), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_hour, R.string.unit_cubic_millimeter_per_hour_short), - ReverseUnit(UnitID.cubic_millimeter_per_minute, BigDecimal.valueOf(60000000000), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_minute, R.string.unit_cubic_millimeter_per_minute_short), - ReverseUnit(UnitID.cubic_millimeter_per_second, BigDecimal.valueOf(1000000000), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_second, R.string.unit_cubic_millimeter_per_second_short), - ReverseUnit(UnitID.cubic_foot_per_hour, BigDecimal.valueOf(127132.80019736), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_hour, R.string.unit_cubic_foot_per_hour_short), - ReverseUnit(UnitID.cubic_foot_per_minute, BigDecimal.valueOf(2118.8800032893), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_minute, R.string.unit_cubic_foot_per_minute_short), - ReverseUnit(UnitID.cubic_foot_per_second, BigDecimal.valueOf(35.314666721489), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_second, R.string.unit_cubic_foot_per_second_short), - ReverseUnit(UnitID.gallons_per_hour_us, BigDecimal.valueOf(951019.38848933), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_us, R.string.unit_gallon_per_hour_us_short), - ReverseUnit(UnitID.gallons_per_minute_us, BigDecimal.valueOf(15850.323141489), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_us, R.string.unit_gallon_per_minute_us_short), - ReverseUnit(UnitID.gallons_per_second_us, BigDecimal.valueOf(264.17205235815), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_us, R.string.unit_gallon_per_second_us_short), - ReverseUnit(UnitID.gallons_per_hour_imperial, BigDecimal.valueOf(791889.29387672), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_imperial, R.string.unit_gallon_per_hour_imperial_short), - ReverseUnit(UnitID.gallons_per_minute_imperial, BigDecimal.valueOf(13198.154897945), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_imperial, R.string.unit_gallon_per_minute_imperial_short), - ReverseUnit(UnitID.gallons_per_second_imperial, BigDecimal.valueOf(219.96924829909), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_imperial, R.string.unit_gallon_per_second_imperial_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt deleted file mode 100644 index 71bd5b38..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val fluxCollection: List by lazy { - listOf( - NormalUnit(UnitID.maxwell, BigDecimal.valueOf(1), UnitGroup.FLUX, R.string.unit_maxwell, R.string.unit_maxwell_short), - NormalUnit(UnitID.microweber, BigDecimal.valueOf(100), UnitGroup.FLUX, R.string.unit_microweber, R.string.unit_microweber_short), - NormalUnit(UnitID.milliweber, BigDecimal.valueOf(100000), UnitGroup.FLUX, R.string.unit_milliweber, R.string.unit_milliweber_short), - NormalUnit(UnitID.weber, BigDecimal.valueOf(100000000), UnitGroup.FLUX, R.string.unit_weber, R.string.unit_weber_short), - NormalUnit(UnitID.kiloweber, BigDecimal.valueOf(100000000000), UnitGroup.FLUX, R.string.unit_kiloweber, R.string.unit_kiloweber_short), - NormalUnit(UnitID.megaweber, BigDecimal.valueOf(100000000000000), UnitGroup.FLUX, R.string.unit_megaweber, R.string.unit_megaweber_short), - NormalUnit(UnitID.gigaweber, BigDecimal.valueOf(100000000000000000), UnitGroup.FLUX, R.string.unit_gigaweber, R.string.unit_gigaweber_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt deleted file mode 100644 index 183cb5b8..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -val forceCollection: List by lazy { - listOf( - NormalUnit(UnitID.attonewton, BigDecimal.valueOf(1), UnitGroup.FORCE, R.string.unit_attonewton, R.string.unit_attonewton_short), - NormalUnit(UnitID.dyne, BigDecimal.valueOf(1E+13), UnitGroup.FORCE, R.string.unit_dyne, R.string.unit_dyne_short), - NormalUnit(UnitID.millinewton, BigDecimal.valueOf(1E+15), UnitGroup.FORCE, R.string.unit_millinewton, R.string.unit_millinewton_short), - NormalUnit(UnitID.joule_per_centimeter, BigDecimal.valueOf(1E+16), UnitGroup.FORCE, R.string.unit_joule_per_centimeter, R.string.unit_joule_per_centimeter_short), - NormalUnit(UnitID.newton, BigDecimal.valueOf(1E+18), UnitGroup.FORCE, R.string.unit_newton, R.string.unit_newton_short), - NormalUnit(UnitID.joule_per_meter, BigDecimal.valueOf(1E+18), UnitGroup.FORCE, R.string.unit_joule_per_meter, R.string.unit_joule_per_meter_short), - NormalUnit(UnitID.kilonewton, BigDecimal.valueOf(1E+21), UnitGroup.FORCE, R.string.unit_kilonewton, R.string.unit_kilonewton_short), - NormalUnit(UnitID.gram_force, BigDecimal.valueOf(9.80665E+15), UnitGroup.FORCE, R.string.unit_gram_force, R.string.unit_gram_force_short), - NormalUnit(UnitID.kilogram_force, BigDecimal.valueOf(9.80665E+18), UnitGroup.FORCE, R.string.unit_kilogram_force, R.string.unit_kilogram_force_short), - NormalUnit(UnitID.ton_force, BigDecimal.valueOf(9.80665E+21), UnitGroup.FORCE, R.string.unit_ton_force, R.string.unit_ton_force_short), - NormalUnit(UnitID.ounce_force, BigDecimal.valueOf(2.78013850953423008E17), UnitGroup.FORCE, R.string.unit_ounce_force, R.string.unit_ounce_force_short), - NormalUnit(UnitID.pound_force, BigDecimal.valueOf(4.4482216152550001E18), UnitGroup.FORCE, R.string.unit_pound_force, R.string.unit_pound_force_short), - NormalUnit(UnitID.kilopound_force, BigDecimal.valueOf(4.448221615255E+21), UnitGroup.FORCE, R.string.unit_kilopound_force, R.string.unit_kilopound_force_short), - NormalUnit(UnitID.pond, BigDecimal.valueOf(9.80665E+15), UnitGroup.FORCE, R.string.unit_pond, R.string.unit_pond_short), - NormalUnit(UnitID.kilopond, BigDecimal.valueOf(9.80665E+18), UnitGroup.FORCE, R.string.unit_kilopond, R.string.unit_kilopond_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt deleted file mode 100644 index 9587fafc..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.BackwardUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -val fuelConsumptionCollection: List by lazy { - listOf( - NormalUnit( UnitID.kilometer_per_liter, BigDecimal.valueOf(1), UnitGroup.FUEL_CONSUMPTION, R.string.unit_km_per_l, R.string.unit_km_per_l_short), - BackwardUnit(UnitID.liter_per_kilometer, BigDecimal.valueOf(1), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_km, R.string.unit_l_per_km_short), - BackwardUnit(UnitID.liter_per_100_kilometer, BigDecimal.valueOf(100), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_100_km, R.string.unit_l_per_100_km_short), - NormalUnit( UnitID.mile_per_gallon_uk, BigDecimal.valueOf(0.35400619), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_uk, R.string.unit_mi_per_gallon_uk_short), - NormalUnit( UnitID.mile_per_gallon_us, BigDecimal.valueOf(0.4251437075), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_us, R.string.unit_mi_per_gallon_us_short), - NormalUnit( UnitID.mile_us_per_liter, BigDecimal.valueOf(1.609344), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_us_per_l, R.string.unit_mi_us_per_l_short), - BackwardUnit(UnitID.gallon_us_per_mile, BigDecimal.valueOf(0.4251437075), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_mile, R.string.unit_gallon_us_per_mile_short), - BackwardUnit(UnitID.gallon_uk_per_mile, BigDecimal.valueOf(0.35400619), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_mile, R.string.unit_gallon_uk_per_mile_short), - BackwardUnit(UnitID.gallon_us_per_100_mile, BigDecimal.valueOf(42.51437075), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_100_mile, R.string.unit_gallon_us_per_100_mile_short), - BackwardUnit(UnitID.gallon_uk_per_100_mile, BigDecimal.valueOf(35.400618996), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_100_mile, R.string.unit_gallon_uk_per_100_mile_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt deleted file mode 100644 index 9cdba506..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -internal val lengthCollection: List by lazy { - listOf( - NormalUnit(UnitID.attometer, BigDecimal.valueOf(1.0), UnitGroup.LENGTH, R.string.unit_attometer, R.string.unit_attometer_short), - NormalUnit(UnitID.nanometer, BigDecimal.valueOf(1.0E+9), UnitGroup.LENGTH, R.string.unit_nanometer, R.string.unit_nanometer_short), - NormalUnit(UnitID.micrometer, BigDecimal.valueOf(1.0E+12), UnitGroup.LENGTH, R.string.unit_micrometer, R.string.unit_micrometer_short), - NormalUnit(UnitID.millimeter, BigDecimal.valueOf(1.0E+15), UnitGroup.LENGTH, R.string.unit_millimeter, R.string.unit_millimeter_short), - NormalUnit(UnitID.centimeter, BigDecimal.valueOf(1.0E+16), UnitGroup.LENGTH, R.string.unit_centimeter, R.string.unit_centimeter_short), - NormalUnit(UnitID.decimeter, BigDecimal.valueOf(1.0E+17), UnitGroup.LENGTH, R.string.unit_decimeter, R.string.unit_decimeter_short), - NormalUnit(UnitID.meter, BigDecimal.valueOf(1.0E+18), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), - NormalUnit(UnitID.kilometer, BigDecimal.valueOf(1.0E+21), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), - NormalUnit(UnitID.nautical_mile, BigDecimal.valueOf(1.852E+21), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), - NormalUnit(UnitID.inch, BigDecimal.valueOf(25_400_000_000_000_000), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), - NormalUnit(UnitID.foot, BigDecimal.valueOf(304_800_000_000_000_000), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), - NormalUnit(UnitID.yard, BigDecimal.valueOf(914_400_000_000_006_400), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), - NormalUnit(UnitID.mile, BigDecimal.valueOf(1_609_344_000_000_010_500_000.0), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), - NormalUnit(UnitID.light_year, BigDecimal.valueOf(9.460730472E+33), UnitGroup.LENGTH, R.string.unit_light_year, R.string.unit_light_year_short), - NormalUnit(UnitID.parsec, BigDecimal.valueOf(3.08567758149136E+34), UnitGroup.LENGTH, R.string.unit_parsec, R.string.unit_parsec_short), - NormalUnit(UnitID.kiloparsec, BigDecimal.valueOf(3.08567758149136E+37), UnitGroup.LENGTH, R.string.unit_kiloparsec, R.string.unit_kiloparsec_short), - NormalUnit(UnitID.megaparsec, BigDecimal.valueOf(3.08567758149136E+40), UnitGroup.LENGTH, R.string.unit_megaparsec, R.string.unit_megaparsec_short), - NormalUnit(UnitID.mercury_equatorial_radius, BigDecimal.valueOf(2.4397E+24), UnitGroup.LENGTH, R.string.unit_mercury_equatorial_radius, R.string.unit_mercury_equatorial_radius_short), - NormalUnit(UnitID.venus_equatorial_radius, BigDecimal.valueOf(6.0518E+24), UnitGroup.LENGTH, R.string.unit_venus_equatorial_radius, R.string.unit_venus_equatorial_radius_short), - NormalUnit(UnitID.earth_equatorial_radius, BigDecimal.valueOf(6.371E+24), UnitGroup.LENGTH, R.string.unit_earth_equatorial_radius, R.string.unit_earth_equatorial_radius_short), - NormalUnit(UnitID.mars_equatorial_radius, BigDecimal.valueOf(3.3895E+24), UnitGroup.LENGTH, R.string.unit_mars_equatorial_radius, R.string.unit_mars_equatorial_radius_short), - NormalUnit(UnitID.jupiter_equatorial_radius, BigDecimal.valueOf(6.9911E+25), UnitGroup.LENGTH, R.string.unit_jupiter_equatorial_radius, R.string.unit_jupiter_equatorial_radius_short), - NormalUnit(UnitID.saturn_equatorial_radius, BigDecimal.valueOf(5.8232E+25), UnitGroup.LENGTH, R.string.unit_saturn_equatorial_radius, R.string.unit_saturn_equatorial_radius_short), - NormalUnit(UnitID.uranus_equatorial_radius, BigDecimal.valueOf(2.5362E+25), UnitGroup.LENGTH, R.string.unit_uranus_equatorial_radius, R.string.unit_uranus_equatorial_radius_short), - NormalUnit(UnitID.neptune_equatorial_radius, BigDecimal.valueOf(2.4622E+25), UnitGroup.LENGTH, R.string.unit_neptune_equatorial_radius, R.string.unit_neptune_equatorial_radius_short), - NormalUnit(UnitID.sun_equatorial_radius, BigDecimal.valueOf(6.95508E+26), UnitGroup.LENGTH, R.string.unit_sun_equatorial_radius, R.string.unit_sun_equatorial_radius_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt deleted file mode 100644 index e8e844e9..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -val luminanceCollection: List by lazy { - listOf( - NormalUnit(UnitID.candela_per_square_meter, BigDecimal.valueOf(31415926.5359), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_meter, R.string.unit_candela_per_square_meter_short), - NormalUnit(UnitID.candela_per_square_centimeter, BigDecimal.valueOf(314159265359), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_centimeter, R.string.unit_candela_per_square_centimeter_short), - NormalUnit(UnitID.candela_per_square_foot, BigDecimal.valueOf(338158218.89), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_foot, R.string.unit_candela_per_square_foot_short), - NormalUnit(UnitID.candela_per_square_inch, BigDecimal.valueOf(48694783520), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_inch, R.string.unit_candela_per_square_inch_short), - NormalUnit(UnitID.kilocandela_per_square_meter, BigDecimal.valueOf(31415926535.9), UnitGroup.LUMINANCE, R.string.unit_kilocandela_per_square_meter, R.string.unit_kilocandela_per_square_meter_short), - NormalUnit(UnitID.stilb, BigDecimal.valueOf(314159265359), UnitGroup.LUMINANCE, R.string.unit_stilb, R.string.unit_stilb_short), - NormalUnit(UnitID.lumen_per_square_meter_per_steradian, BigDecimal.valueOf(31415926.5359), UnitGroup.LUMINANCE, R.string.unit_lumen_per_square_meter_per_steradian, R.string.unit_lumen_per_square_meter_per_steradian_short), - NormalUnit(UnitID.lumen_per_square_centimeter_per_steradian, BigDecimal.valueOf(314159265359), UnitGroup.LUMINANCE, R.string.unit_lumen_per_square_centimeter_per_steradian, R.string.unit_lumen_per_square_centimeter_per_steradian_short), - NormalUnit(UnitID.lumen_per_square_foot_per_steradian, BigDecimal.valueOf(338158218.89), UnitGroup.LUMINANCE, R.string.unit_lumen_per_square_foot_per_steradian, R.string.unit_lumen_per_square_foot_per_steradian_short), - NormalUnit(UnitID.watt_per_square_centimeter_per_steradian, BigDecimal.valueOf(214570778240185), UnitGroup.LUMINANCE, R.string.unit_watt_per_square_centimeter_per_steradian, R.string.unit_watt_per_square_centimeter_per_steradian_short), - NormalUnit(UnitID.nit, BigDecimal.valueOf(31415926.5359), UnitGroup.LUMINANCE, R.string.unit_nit, R.string.unit_nit_short), - NormalUnit(UnitID.millinit, BigDecimal.valueOf(31415.9265359), UnitGroup.LUMINANCE, R.string.unit_millinit, R.string.unit_millinit_short), - NormalUnit(UnitID.lambert, BigDecimal.valueOf(100000000000), UnitGroup.LUMINANCE, R.string.unit_lambert, R.string.unit_lambert_short), - NormalUnit(UnitID.millilambert, BigDecimal.valueOf(100000000), UnitGroup.LUMINANCE, R.string.unit_millilambert, R.string.unit_millilambert_short), - NormalUnit(UnitID.foot_lambert, BigDecimal.valueOf(107639104.167), UnitGroup.LUMINANCE, R.string.unit_foot_lambert, R.string.unit_foot_lambert_short), - NormalUnit(UnitID.apostilb, BigDecimal.valueOf(10000000), UnitGroup.LUMINANCE, R.string.unit_apostilb, R.string.unit_apostilb_short), - NormalUnit(UnitID.blondel, BigDecimal.valueOf(10000000), UnitGroup.LUMINANCE, R.string.unit_blondel, R.string.unit_blondel_short), - NormalUnit(UnitID.skot, BigDecimal.valueOf(10000), UnitGroup.LUMINANCE, R.string.unit_skot, R.string.unit_skot_short), - NormalUnit(UnitID.bril, BigDecimal.valueOf(1), UnitGroup.LUMINANCE, R.string.unit_bril, R.string.unit_bril_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt deleted file mode 100644 index e406bd2a..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -internal val massCollection: List by lazy { - listOf( - NormalUnit(UnitID.electron_mass_rest, BigDecimal.valueOf(9.1093897E-28), UnitGroup.MASS, R.string.unit_electron_mass_rest, R.string.unit_electron_mass_rest_short), - NormalUnit(UnitID.atomic_mass_unit, BigDecimal.valueOf(1.6605402E-24), UnitGroup.MASS, R.string.unit_atomic_mass_unit, R.string.unit_atomic_mass_unit_short), - NormalUnit(UnitID.microgram, BigDecimal(1E-6), UnitGroup.MASS, R.string.unit_microgram, R.string.unit_microgram_short), - NormalUnit(UnitID.milligram, BigDecimal.valueOf(1E-3), UnitGroup.MASS, R.string.unit_milligram, R.string.unit_milligram_short), - NormalUnit(UnitID.grain, BigDecimal.valueOf(0.06479891), UnitGroup.MASS, R.string.unit_grain, R.string.unit_grain_short), - NormalUnit(UnitID.gram, BigDecimal.valueOf(1), UnitGroup.MASS, R.string.unit_gram, R.string.unit_gram_short), - NormalUnit(UnitID.kilogram, BigDecimal.valueOf(1E+3), UnitGroup.MASS, R.string.unit_kilogram, R.string.unit_kilogram_short), - NormalUnit(UnitID.metric_ton, BigDecimal.valueOf(1E+6), UnitGroup.MASS, R.string.unit_metric_ton, R.string.unit_metric_ton_short), - NormalUnit(UnitID.imperial_ton, BigDecimal.valueOf(1016046.9088), UnitGroup.MASS, R.string.unit_imperial_ton, R.string.unit_imperial_ton_short), - NormalUnit(UnitID.ounce, BigDecimal.valueOf(28.349523125), UnitGroup.MASS, R.string.unit_ounce, R.string.unit_ounce_short), - NormalUnit(UnitID.carat, BigDecimal.valueOf(0.2), UnitGroup.MASS, R.string.unit_carat, R.string.unit_carat_short), - NormalUnit(UnitID.pound, BigDecimal.valueOf(453.59237), UnitGroup.MASS, R.string.unit_pound, R.string.unit_pound_short), - NormalUnit(UnitID.mercury_mass, BigDecimal.valueOf(3.30104E+26), UnitGroup.MASS, R.string.unit_mercury_mass, R.string.unit_mercury_mass_short), - NormalUnit(UnitID.venus_mass, BigDecimal.valueOf(4.86732E+27), UnitGroup.MASS, R.string.unit_venus_mass, R.string.unit_venus_mass_short), - NormalUnit(UnitID.earth_mass, BigDecimal.valueOf(5.97219E+27), UnitGroup.MASS, R.string.unit_earth_mass, R.string.unit_earth_mass_short), - NormalUnit(UnitID.mars_mass, BigDecimal.valueOf(6.41693E+26), UnitGroup.MASS, R.string.unit_mars_mass, R.string.unit_mars_mass_short), - NormalUnit(UnitID.jupiter_mass, BigDecimal.valueOf(1.89813E+30), UnitGroup.MASS, R.string.unit_jupiter_mass, R.string.unit_jupiter_mass_short), - NormalUnit(UnitID.saturn_mass, BigDecimal.valueOf(5.68319E+29), UnitGroup.MASS, R.string.unit_saturn_mass, R.string.unit_saturn_mass_short), - NormalUnit(UnitID.uranus_mass, BigDecimal.valueOf(8.68103E+28), UnitGroup.MASS, R.string.unit_uranus_mass, R.string.unit_uranus_mass_short), - NormalUnit(UnitID.neptune_mass, BigDecimal.valueOf(1.0241E+29), UnitGroup.MASS, R.string.unit_neptune_mass, R.string.unit_neptune_mass_short), - NormalUnit(UnitID.sun_mass, BigDecimal.valueOf(1.9891E+33), UnitGroup.MASS, R.string.unit_sun_mass, R.string.unit_sun_mass_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt deleted file mode 100644 index 03b7466e..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val numberBaseCollection: List by lazy { - listOf( - NumberBaseUnit(UnitID.binary, BigDecimal.valueOf(2.0), UnitGroup.NUMBER_BASE, R.string.unit_binary, R.string.unit_binary_short), - NumberBaseUnit(UnitID.ternary, BigDecimal.valueOf(3.0), UnitGroup.NUMBER_BASE, R.string.unit_ternary, R.string.unit_ternary_short), - NumberBaseUnit(UnitID.quaternary, BigDecimal.valueOf(4.0), UnitGroup.NUMBER_BASE, R.string.unit_quaternary, R.string.unit_quaternary_short), - NumberBaseUnit(UnitID.quinary, BigDecimal.valueOf(5.0), UnitGroup.NUMBER_BASE, R.string.unit_quinary, R.string.unit_quinary_short), - NumberBaseUnit(UnitID.senary, BigDecimal.valueOf(6.0), UnitGroup.NUMBER_BASE, R.string.unit_senary, R.string.unit_senary_short), - NumberBaseUnit(UnitID.septenary, BigDecimal.valueOf(7.0), UnitGroup.NUMBER_BASE, R.string.unit_septenary, R.string.unit_septenary_short), - NumberBaseUnit(UnitID.octal, BigDecimal.valueOf(8.0), UnitGroup.NUMBER_BASE, R.string.unit_octal, R.string.unit_octal_short), - NumberBaseUnit(UnitID.nonary, BigDecimal.valueOf(9.0), UnitGroup.NUMBER_BASE, R.string.unit_nonary, R.string.unit_nonary_short), - NumberBaseUnit(UnitID.decimal, BigDecimal.valueOf(10.0), UnitGroup.NUMBER_BASE, R.string.unit_decimal, R.string.unit_decimal_short), - NumberBaseUnit(UnitID.undecimal, BigDecimal.valueOf(11.0), UnitGroup.NUMBER_BASE, R.string.unit_undecimal, R.string.unit_undecimal_short), - NumberBaseUnit(UnitID.duodecimal, BigDecimal.valueOf(12.0), UnitGroup.NUMBER_BASE, R.string.unit_duodecimal, R.string.unit_duodecimal_short), - NumberBaseUnit(UnitID.tridecimal, BigDecimal.valueOf(13.0), UnitGroup.NUMBER_BASE, R.string.unit_tridecimal, R.string.unit_tridecimal_short), - NumberBaseUnit(UnitID.tetradecimal, BigDecimal.valueOf(14.0), UnitGroup.NUMBER_BASE, R.string.unit_tetradecimal, R.string.unit_tetradecimal_short), - NumberBaseUnit(UnitID.pentadecimal, BigDecimal.valueOf(15.0), UnitGroup.NUMBER_BASE, R.string.unit_pentadecimal, R.string.unit_pentadecimal_short), - NumberBaseUnit(UnitID.hexadecimal, BigDecimal.valueOf(16.0), UnitGroup.NUMBER_BASE, R.string.unit_hexadecimal, R.string.unit_hexadecimal_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt deleted file mode 100644 index 5ed8b2b3..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val powerCollection: List by lazy { - listOf( - NormalUnit(UnitID.attowatt, BigDecimal.valueOf(1), UnitGroup.POWER, R.string.unit_attowatt, R.string.unit_attowatt_short), - NormalUnit(UnitID.watt, BigDecimal.valueOf(1_000_000_000_000_000_000), UnitGroup.POWER, R.string.unit_watt, R.string.unit_watt_short), - NormalUnit(UnitID.kilowatt, BigDecimal.valueOf(1.0E+21), UnitGroup.POWER, R.string.unit_kilowatt, R.string.unit_kilowatt_short), - NormalUnit(UnitID.megawatt, BigDecimal.valueOf(1.0E+24), UnitGroup.POWER, R.string.unit_megawatt, R.string.unit_megawatt_short), - NormalUnit(UnitID.horse_power_mechanical, BigDecimal.valueOf(745_699_871_582_285_700_000.0), UnitGroup.POWER, R.string.unit_horse_power_mechanical, R.string.unit_horse_power_mechanical_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt deleted file mode 100644 index 2b3fd3e6..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -val prefixCollection: List by lazy { - listOf( - NormalUnit(UnitID.prefix_quetta, BigDecimal.valueOf(1E+30), UnitGroup.PREFIX, R.string.unit_prefix_quetta, R.string.unit_prefix_quetta_short), - NormalUnit(UnitID.prefix_ronna, BigDecimal.valueOf(1E+27), UnitGroup.PREFIX, R.string.unit_prefix_ronna, R.string.unit_prefix_ronna_short), - NormalUnit(UnitID.prefix_yotta, BigDecimal.valueOf(1E+24), UnitGroup.PREFIX, R.string.unit_prefix_yotta, R.string.unit_prefix_yotta_short), - NormalUnit(UnitID.prefix_zetta, BigDecimal.valueOf(1E+21), UnitGroup.PREFIX, R.string.unit_prefix_zetta, R.string.unit_prefix_zetta_short), - NormalUnit(UnitID.prefix_exa, BigDecimal.valueOf(1E+18), UnitGroup.PREFIX, R.string.unit_prefix_exa, R.string.unit_prefix_exa_short), - NormalUnit(UnitID.prefix_peta, BigDecimal.valueOf(1E+15), UnitGroup.PREFIX, R.string.unit_prefix_peta, R.string.unit_prefix_peta_short), - NormalUnit(UnitID.prefix_tera, BigDecimal.valueOf(1E+12), UnitGroup.PREFIX, R.string.unit_prefix_tera, R.string.unit_prefix_tera_short), - NormalUnit(UnitID.prefix_giga, BigDecimal.valueOf(1E+9), UnitGroup.PREFIX, R.string.unit_prefix_giga, R.string.unit_prefix_giga_short), - NormalUnit(UnitID.prefix_mega, BigDecimal.valueOf(1E+6), UnitGroup.PREFIX, R.string.unit_prefix_mega, R.string.unit_prefix_mega_short), - NormalUnit(UnitID.prefix_kilo, BigDecimal.valueOf(1E+3), UnitGroup.PREFIX, R.string.unit_prefix_kilo, R.string.unit_prefix_kilo_short), - NormalUnit(UnitID.prefix_hecto, BigDecimal.valueOf(1E+2), UnitGroup.PREFIX, R.string.unit_prefix_hecto, R.string.unit_prefix_hecto_short), - NormalUnit(UnitID.prefix_deca, BigDecimal.valueOf(1E+1), UnitGroup.PREFIX, R.string.unit_prefix_deca, R.string.unit_prefix_deca_short), - NormalUnit(UnitID.prefix_base, BigDecimal.valueOf(1E+0), UnitGroup.PREFIX, R.string.unit_prefix_base, R.string.unit_prefix_base_short), - NormalUnit(UnitID.prefix_deci, BigDecimal.valueOf(1E-1), UnitGroup.PREFIX, R.string.unit_prefix_deci, R.string.unit_prefix_deci_short), - NormalUnit(UnitID.prefix_centi, BigDecimal.valueOf(1E-2), UnitGroup.PREFIX, R.string.unit_prefix_centi, R.string.unit_prefix_centi_short), - NormalUnit(UnitID.prefix_milli, BigDecimal.valueOf(1E-3), UnitGroup.PREFIX, R.string.unit_prefix_milli, R.string.unit_prefix_milli_short), - NormalUnit(UnitID.prefix_micro, BigDecimal.valueOf(1E-6), UnitGroup.PREFIX, R.string.unit_prefix_micro, R.string.unit_prefix_micro_short), - NormalUnit(UnitID.prefix_nano, BigDecimal.valueOf(1E-9), UnitGroup.PREFIX, R.string.unit_prefix_nano, R.string.unit_prefix_nano_short), - NormalUnit(UnitID.prefix_pico, BigDecimal.valueOf(1E-12), UnitGroup.PREFIX, R.string.unit_prefix_pico, R.string.unit_prefix_pico_short), - NormalUnit(UnitID.prefix_femto, BigDecimal.valueOf(1E-15), UnitGroup.PREFIX, R.string.unit_prefix_femto, R.string.unit_prefix_femto_short), - NormalUnit(UnitID.prefix_atto, BigDecimal.valueOf(1E-18), UnitGroup.PREFIX, R.string.unit_prefix_atto, R.string.unit_prefix_atto_short), - NormalUnit(UnitID.prefix_zepto, BigDecimal.valueOf(1E-21), UnitGroup.PREFIX, R.string.unit_prefix_zepto, R.string.unit_prefix_zepto_short), - NormalUnit(UnitID.prefix_yocto, BigDecimal.valueOf(1E-24), UnitGroup.PREFIX, R.string.unit_prefix_yocto, R.string.unit_prefix_yocto_short), - NormalUnit(UnitID.prefix_ronto, BigDecimal.valueOf(1E-27), UnitGroup.PREFIX, R.string.unit_prefix_ronto, R.string.unit_prefix_ronto_short), - NormalUnit(UnitID.prefix_quecto, BigDecimal.valueOf(1E-30), UnitGroup.PREFIX, R.string.unit_prefix_quecto, R.string.unit_prefix_quecto_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt deleted file mode 100644 index c2cca732..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -internal val pressureCollection: List by lazy { - listOf( - NormalUnit(UnitID.attopascal, BigDecimal.valueOf(1), UnitGroup.PRESSURE, R.string.unit_attopascal, R.string.unit_attopascal_short), - NormalUnit(UnitID.femtopascal, BigDecimal.valueOf(1E+3), UnitGroup.PRESSURE, R.string.unit_femtopascal, R.string.unit_femtopascal_short), - NormalUnit(UnitID.picopascal, BigDecimal.valueOf(1E+6), UnitGroup.PRESSURE, R.string.unit_picopascal, R.string.unit_picopascal_short), - NormalUnit(UnitID.nanopascal, BigDecimal.valueOf(1E+9), UnitGroup.PRESSURE, R.string.unit_nanopascal, R.string.unit_nanopascal_short), - NormalUnit(UnitID.micropascal, BigDecimal.valueOf(1E+12), UnitGroup.PRESSURE, R.string.unit_micropascal, R.string.unit_micropascal_short), - NormalUnit(UnitID.millipascal, BigDecimal.valueOf(1E+15), UnitGroup.PRESSURE, R.string.unit_millipascal, R.string.unit_millipascal_short), - NormalUnit(UnitID.centipascal, BigDecimal.valueOf(1E+16), UnitGroup.PRESSURE, R.string.unit_centipascal, R.string.unit_centipascal_short), - NormalUnit(UnitID.decipascal, BigDecimal.valueOf(1E+17), UnitGroup.PRESSURE, R.string.unit_decipascal, R.string.unit_decipascal_short), - NormalUnit(UnitID.pascal, BigDecimal.valueOf(1E+18), UnitGroup.PRESSURE, R.string.unit_pascal, R.string.unit_pascal_short), - NormalUnit(UnitID.dekapascal, BigDecimal.valueOf(1E+19), UnitGroup.PRESSURE, R.string.unit_dekapascal, R.string.unit_dekapascal_short), - NormalUnit(UnitID.hectopascal, BigDecimal.valueOf(1E+20), UnitGroup.PRESSURE, R.string.unit_hectopascal, R.string.unit_hectopascal_short), - NormalUnit(UnitID.millibar, BigDecimal.valueOf(1E+20), UnitGroup.PRESSURE, R.string.unit_millibar, R.string.unit_millibar_short), - NormalUnit(UnitID.bar, BigDecimal.valueOf(1E+23), UnitGroup.PRESSURE, R.string.unit_bar, R.string.unit_bar_short), - NormalUnit(UnitID.kilopascal, BigDecimal.valueOf(1E+21), UnitGroup.PRESSURE, R.string.unit_kilopascal, R.string.unit_kilopascal_short), - NormalUnit(UnitID.megapascal, BigDecimal.valueOf(1E+24), UnitGroup.PRESSURE, R.string.unit_megapascal, R.string.unit_megapascal_short), - NormalUnit(UnitID.gigapascal, BigDecimal.valueOf(1E+27), UnitGroup.PRESSURE, R.string.unit_gigapascal, R.string.unit_gigapascal_short), - NormalUnit(UnitID.terapascal, BigDecimal.valueOf(1E+30), UnitGroup.PRESSURE, R.string.unit_terapascal, R.string.unit_terapascal_short), - NormalUnit(UnitID.petapascal, BigDecimal.valueOf(1E+33), UnitGroup.PRESSURE, R.string.unit_petapascal, R.string.unit_petapascal_short), - NormalUnit(UnitID.exapascal, BigDecimal.valueOf(1E+36), UnitGroup.PRESSURE, R.string.unit_exapascal, R.string.unit_exapascal_short), - NormalUnit(UnitID.psi, BigDecimal.valueOf(6.8947572931783E+21), UnitGroup.PRESSURE, R.string.unit_psi, R.string.unit_psi_short), - NormalUnit(UnitID.ksi, BigDecimal.valueOf(6.8947572931783E+24), UnitGroup.PRESSURE, R.string.unit_ksi, R.string.unit_ksi_short), - NormalUnit(UnitID.standard_atmosphere, BigDecimal.valueOf(101.325E+21), UnitGroup.PRESSURE, R.string.unit_standard_atmosphere, R.string.unit_standard_atmosphere_short), - NormalUnit(UnitID.torr, BigDecimal.valueOf(1.3332236842108281E+20), UnitGroup.PRESSURE, R.string.unit_torr, R.string.unit_torr_short), - NormalUnit(UnitID.micron_of_mercury, BigDecimal.valueOf(1.3332236842108281E+17), UnitGroup.PRESSURE, R.string.unit_micron_of_mercury, R.string.unit_micron_of_mercury_short), - NormalUnit(UnitID.millimeter_of_mercury, BigDecimal.valueOf(1.3332236842108281E+20), UnitGroup.PRESSURE, R.string.unit_millimeter_of_mercury, R.string.unit_millimeter_of_mercury_short), - NormalUnit(UnitID.kilogram_force_per_square_meter, BigDecimal.valueOf(9.80665E+18), UnitGroup.PRESSURE, R.string.unit_kilogram_force_per_square_meter, R.string.unit_kilogram_force_per_square_meter_short), - NormalUnit(UnitID.kilogram_force_per_square_centimeter, BigDecimal.valueOf(9.80665E+22), UnitGroup.PRESSURE, R.string.unit_kilogram_force_per_square_centimeter, R.string.unit_kilogram_force_per_square_centimeter_short), - NormalUnit(UnitID.gram_force_per_square_centimeter, BigDecimal.valueOf(9.80665E+19), UnitGroup.PRESSURE, R.string.unit_gram_force_per_square_centimeter, R.string.unit_gram_force_per_square_centimeter_short), - NormalUnit(UnitID.pound_force_per_square_foot, BigDecimal.valueOf(4.788025898E+19), UnitGroup.PRESSURE, R.string.unit_pound_force_per_square_foot, R.string.unit_pound_force_per_square_foot_short), - NormalUnit(UnitID.pound_force_per_square_inch, BigDecimal.valueOf(6.8947572931783E+21), UnitGroup.PRESSURE, R.string.unit_pound_force_per_square_inch, R.string.unit_pound_force_per_square_inch_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt deleted file mode 100644 index f9c066d4..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.BackwardUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -internal val speedCollection: List by lazy { - listOf( - NormalUnit( UnitID.millimeter_per_hour, BigDecimal.valueOf(1), UnitGroup.SPEED, R.string.unit_millimeter_per_hour, R.string.unit_millimeter_per_hour_short), - NormalUnit( UnitID.millimeter_per_minute, BigDecimal.valueOf(60), UnitGroup.SPEED, R.string.unit_millimeter_per_minute, R.string.unit_millimeter_per_minute_short), - NormalUnit( UnitID.millimeter_per_second, BigDecimal.valueOf(3_600), UnitGroup.SPEED, R.string.unit_millimeter_per_second, R.string.unit_millimeter_per_second_short), - NormalUnit( UnitID.centimeter_per_hour, BigDecimal.valueOf(10), UnitGroup.SPEED, R.string.unit_centimeter_per_hour, R.string.unit_centimeter_per_hour_short), - NormalUnit( UnitID.centimeter_per_minute, BigDecimal.valueOf(600), UnitGroup.SPEED, R.string.unit_centimeter_per_minute, R.string.unit_centimeter_per_minute_short), - NormalUnit( UnitID.centimeter_per_second, BigDecimal.valueOf(36_000), UnitGroup.SPEED, R.string.unit_centimeter_per_second, R.string.unit_centimeter_per_second_short), - NormalUnit( UnitID.meter_per_hour, BigDecimal.valueOf(1_000), UnitGroup.SPEED, R.string.unit_meter_per_hour, R.string.unit_meter_per_hour_short), - NormalUnit( UnitID.meter_per_minute, BigDecimal.valueOf(60_000), UnitGroup.SPEED, R.string.unit_meter_per_minute, R.string.unit_meter_per_minute_short), - NormalUnit( UnitID.meter_per_second, BigDecimal.valueOf(3_600_000), UnitGroup.SPEED, R.string.unit_meter_per_second, R.string.unit_meter_per_second_short), - NormalUnit( UnitID.kilometer_per_hour, BigDecimal.valueOf(1_000_000), UnitGroup.SPEED, R.string.unit_kilometer_per_hour, R.string.unit_kilometer_per_hour_short), - NormalUnit( UnitID.kilometer_per_minute, BigDecimal.valueOf(60_000_000), UnitGroup.SPEED, R.string.unit_kilometer_per_minute, R.string.unit_kilometer_per_minute_short), - NormalUnit( UnitID.kilometer_per_second, BigDecimal.valueOf(3_600_000_000), UnitGroup.SPEED, R.string.unit_kilometer_per_second, R.string.unit_kilometer_per_second_short), - NormalUnit( UnitID.foot_per_hour, BigDecimal.valueOf(304.8), UnitGroup.SPEED, R.string.unit_foot_per_hour, R.string.unit_foot_per_hour_short), - NormalUnit( UnitID.foot_per_minute, BigDecimal.valueOf(18_288), UnitGroup.SPEED, R.string.unit_foot_per_minute, R.string.unit_foot_per_minute_short), - NormalUnit( UnitID.foot_per_second, BigDecimal.valueOf(1_097_280), UnitGroup.SPEED, R.string.unit_foot_per_second, R.string.unit_foot_per_second_short), - NormalUnit( UnitID.yard_per_hour, BigDecimal.valueOf(914.4), UnitGroup.SPEED, R.string.unit_yard_per_hour, R.string.unit_yard_per_hour_short), - NormalUnit( UnitID.yard_per_minute, BigDecimal.valueOf(54_864), UnitGroup.SPEED, R.string.unit_yard_per_minute, R.string.unit_yard_per_minute_short), - NormalUnit( UnitID.yard_per_second, BigDecimal.valueOf(3_291_840), UnitGroup.SPEED, R.string.unit_yard_per_second, R.string.unit_yard_per_second_short), - NormalUnit( UnitID.mile_per_hour, BigDecimal.valueOf(1_609_344), UnitGroup.SPEED, R.string.unit_mile_per_hour, R.string.unit_mile_per_hour_short), - NormalUnit( UnitID.mile_per_minute, BigDecimal.valueOf(96_560_640), UnitGroup.SPEED, R.string.unit_mile_per_minute, R.string.unit_mile_per_minute_short), - NormalUnit( UnitID.mile_per_second, BigDecimal.valueOf(5_793_638_400), UnitGroup.SPEED, R.string.unit_mile_per_second, R.string.unit_mile_per_second_short), - BackwardUnit(UnitID.minute_per_kilometer, BigDecimal.valueOf(60_000_000), UnitGroup.SPEED, R.string.unit_minute_per_kilometer, R.string.unit_minute_per_kilometer_short), - BackwardUnit(UnitID.minute_per_mile, BigDecimal.valueOf(96_560_640), UnitGroup.SPEED, R.string.unit_minute_per_mile, R.string.unit_minute_per_mile_short), - BackwardUnit(UnitID.hour_per_kilometer, BigDecimal.valueOf(1_000_000), UnitGroup.SPEED, R.string.unit_hour_per_kilometer, R.string.unit_hour_per_kilometer_short), - BackwardUnit(UnitID.hour_per_mile, BigDecimal.valueOf(1_609_344), UnitGroup.SPEED, R.string.unit_hour_per_mile, R.string.unit_hour_per_mile_short), - NormalUnit( UnitID.knot, BigDecimal.valueOf(1_852_000), UnitGroup.SPEED, R.string.unit_knot, R.string.unit_knot_short), - NormalUnit( UnitID.velocity_of_light_in_vacuum, BigDecimal.valueOf(1_079_252_848_799_998), UnitGroup.SPEED, R.string.unit_velocity_of_light_in_vacuum, R.string.unit_velocity_of_light_in_vacuum_short), - NormalUnit( UnitID.cosmic_velocity_first, BigDecimal.valueOf(28_440_000_000), UnitGroup.SPEED, R.string.unit_cosmic_velocity_first, R.string.unit_cosmic_velocity_first_short), - NormalUnit( UnitID.cosmic_velocity_second, BigDecimal.valueOf(40_320_000_000), UnitGroup.SPEED, R.string.unit_cosmic_velocity_second, R.string.unit_cosmic_velocity_second_short), - NormalUnit( UnitID.cosmic_velocity_third, BigDecimal.valueOf(60_012_000_000), UnitGroup.SPEED, R.string.unit_cosmic_velocity_third, R.string.unit_cosmic_velocity_third_short), - NormalUnit( UnitID.earths_orbital_speed, BigDecimal.valueOf(107_154_000_000), UnitGroup.SPEED, R.string.unit_earths_orbital_speed, R.string.unit_earths_orbital_speed_short), - NormalUnit( UnitID.mach, BigDecimal.valueOf(1_236_960_000), UnitGroup.SPEED, R.string.unit_mach, R.string.unit_mach_short), - NormalUnit( UnitID.mach_si_standard, BigDecimal.valueOf(1_062_167_040), UnitGroup.SPEED, R.string.unit_mach_si_standard, R.string.unit_mach_si_standard_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt deleted file mode 100644 index bdbef2b0..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.TemperatureUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal -import java.math.RoundingMode - -internal val temperatureCollection: List by lazy { - listOf( - TemperatureUnit( - id = UnitID.celsius, - basicUnit = BigDecimal.ONE, - group = UnitGroup.TEMPERATURE, - displayName = R.string.unit_celsius, - shortName = R.string.unit_celsius_short, - customConvert = { unitTo, value -> - when (unitTo.id) { - UnitID.fahrenheit -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .times(BigDecimal.valueOf(1.8)) - .plus(BigDecimal(32)) - } - - UnitID.kelvin -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .plus(BigDecimal.valueOf(273.15)) - } - - else -> value - } - } - ), - TemperatureUnit( - id = UnitID.fahrenheit, - basicUnit = BigDecimal.ONE, - group = UnitGroup.TEMPERATURE, - displayName = R.string.unit_fahrenheit, - shortName = R.string.unit_fahrenheit_short, - customConvert = { unitTo, value -> - when (unitTo.id) { - UnitID.celsius -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal(32)) - .times(BigDecimal(5)) - .div(BigDecimal(9)) - } - UnitID.kelvin -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal(32)) - .times(BigDecimal(5)) - .div(BigDecimal(9)) - .add(BigDecimal.valueOf(273.15)) - } - else -> value - } - } - ), - TemperatureUnit( - id = UnitID.kelvin, - basicUnit = BigDecimal.ONE, - group = UnitGroup.TEMPERATURE, - displayName = R.string.unit_kelvin, - shortName = R.string.unit_kelvin_short, - customConvert = { unitTo, value -> - when (unitTo.id) { - UnitID.celsius -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal(273.15)) - } - UnitID.fahrenheit -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal.valueOf(273.15)) - .times(BigDecimal.valueOf(1.8)) - .plus(BigDecimal(32)) - } - else -> value - } - } - ), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt deleted file mode 100644 index 3c9c4c13..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -internal val timeCollection: List by lazy { - listOf( - NormalUnit(UnitID.attosecond, BigDecimal.valueOf(1), UnitGroup.TIME, R.string.unit_attosecond, R.string.unit_attosecond_short), - NormalUnit(UnitID.nanosecond, BigDecimal.valueOf(1_000_000_000), UnitGroup.TIME, R.string.unit_nanosecond, R.string.unit_nanosecond_short), - NormalUnit(UnitID.microsecond, BigDecimal.valueOf(1_000_000_000_000), UnitGroup.TIME, R.string.unit_microsecond, R.string.unit_microsecond_short), - NormalUnit(UnitID.millisecond, BigDecimal.valueOf(1_000_000_000_000_000), UnitGroup.TIME, R.string.unit_millisecond, R.string.unit_millisecond_short), - NormalUnit(UnitID.jiffy, BigDecimal.valueOf(10_000_000_000_000_000), UnitGroup.TIME, R.string.unit_jiffy, R.string.unit_jiffy_short), - NormalUnit(UnitID.second, BigDecimal.valueOf(1_000_000_000_000_000_000), UnitGroup.TIME, R.string.unit_second, R.string.unit_second_short), - NormalUnit(UnitID.minute, BigDecimal.valueOf(60_000_000_000_000_000_000.0), UnitGroup.TIME, R.string.unit_minute, R.string.unit_minute_short), - NormalUnit(UnitID.hour, BigDecimal.valueOf(3_600_000_000_000_000_000_000.0), UnitGroup.TIME, R.string.unit_hour, R.string.unit_hour_short), - NormalUnit(UnitID.day, BigDecimal.valueOf(86_400_000_000_000_000_000_000.0), UnitGroup.TIME, R.string.unit_day, R.string.unit_day_short), - NormalUnit(UnitID.week, BigDecimal.valueOf(604_800_000_000_000_000_000_000.0), UnitGroup.TIME, R.string.unit_week, R.string.unit_week_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt deleted file mode 100644 index dc2bb25e..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.converter.UnitID -import java.math.BigDecimal - -val torqueCollection: List by lazy { - listOf( - NormalUnit(UnitID.dyne_millimeter, BigDecimal.valueOf(1), UnitGroup.TORQUE, R.string.unit_dyne_millimeter, R.string.unit_dyne_millimeter_short), - NormalUnit(UnitID.dyne_centimeter, BigDecimal.valueOf(10), UnitGroup.TORQUE, R.string.unit_dyne_centimeter, R.string.unit_dyne_centimeter_short), - NormalUnit(UnitID.dyne_meter, BigDecimal.valueOf(1000), UnitGroup.TORQUE, R.string.unit_dyne_meter, R.string.unit_dyne_meter_short), - NormalUnit(UnitID.newton_millimeter, BigDecimal.valueOf(100000), UnitGroup.TORQUE, R.string.unit_newton_millimeter, R.string.unit_newton_millimeter_short), - NormalUnit(UnitID.newton_centimeter, BigDecimal.valueOf(1000000), UnitGroup.TORQUE, R.string.unit_newton_centimeter, R.string.unit_newton_centimeter_short), - NormalUnit(UnitID.newton_meter, BigDecimal.valueOf(100000000), UnitGroup.TORQUE, R.string.unit_newton_meter, R.string.unit_newton_meter_short), - NormalUnit(UnitID.kilonewton_meter, BigDecimal.valueOf(100000000000), UnitGroup.TORQUE, R.string.unit_kilonewton_meter, R.string.unit_kilonewton_meter_short), - NormalUnit(UnitID.gram_force_millimeter, BigDecimal.valueOf(980.665), UnitGroup.TORQUE, R.string.unit_gram_force_millimeter, R.string.unit_gram_force_millimeter_short), - NormalUnit(UnitID.gram_force_centimeter, BigDecimal.valueOf(9806.65), UnitGroup.TORQUE, R.string.unit_gram_force_centimeter, R.string.unit_gram_force_centimeter_short), - NormalUnit(UnitID.kilogram_force_millimeter, BigDecimal.valueOf(980665), UnitGroup.TORQUE, R.string.unit_kilogram_force_millimeter, R.string.unit_kilogram_force_millimeter_short), - NormalUnit(UnitID.gram_force_meter, BigDecimal.valueOf(980665), UnitGroup.TORQUE, R.string.unit_gram_force_meter, R.string.unit_gram_force_meter_short), - NormalUnit(UnitID.kilogram_force_centimeter, BigDecimal.valueOf(9806650), UnitGroup.TORQUE, R.string.unit_kilogram_force_centimeter, R.string.unit_kilogram_force_centimeter_short), - NormalUnit(UnitID.kilogram_force_meter, BigDecimal.valueOf(980665000), UnitGroup.TORQUE, R.string.unit_kilogram_force_meter, R.string.unit_kilogram_force_meter_short), - NormalUnit(UnitID.ounce_force_foot, BigDecimal.valueOf(8473862.4), UnitGroup.TORQUE, R.string.unit_ounce_force_foot, R.string.unit_ounce_force_foot_short), - NormalUnit(UnitID.ounce_force_inch, BigDecimal.valueOf(706155.2), UnitGroup.TORQUE, R.string.unit_ounce_force_inch, R.string.unit_ounce_force_inch_short), - NormalUnit(UnitID.pound_force_foot, BigDecimal.valueOf(135581800), UnitGroup.TORQUE, R.string.unit_pound_force_foot, R.string.unit_pound_force_foot_short), - NormalUnit(UnitID.pound_force_inch, BigDecimal.valueOf(1.1298483333333334E7), UnitGroup.TORQUE, R.string.unit_pound_force_inch, R.string.unit_pound_force_inch_short), - ) -} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt deleted file mode 100644 index 894eb1ef..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter.collections - -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import java.math.BigDecimal - -internal val volumeCollection: List by lazy { - listOf( - NormalUnit(UnitID.attoliter, BigDecimal.valueOf(1), UnitGroup.VOLUME, R.string.unit_attoliter, R.string.unit_attoliter_short), - NormalUnit(UnitID.milliliter, BigDecimal.valueOf(1_000_000_000_000_000), UnitGroup.VOLUME, R.string.unit_milliliter, R.string.unit_milliliter_short), - NormalUnit(UnitID.liter, BigDecimal.valueOf(1_000_000_000_000_000_000), UnitGroup.VOLUME, R.string.unit_liter, R.string.unit_liter_short), - NormalUnit(UnitID.us_liquid_gallon, BigDecimal.valueOf(3_785_411_783_999_977_000), UnitGroup.VOLUME, R.string.unit_us_liquid_gallon, R.string.unit_us_liquid_gallon_short), - NormalUnit(UnitID.us_liquid_quart, BigDecimal.valueOf(946_352_945_999_994_200), UnitGroup.VOLUME, R.string.unit_us_liquid_quart, R.string.unit_us_liquid_quart_short), - NormalUnit(UnitID.us_liquid_pint, BigDecimal.valueOf(473_176_472_999_997_100), UnitGroup.VOLUME, R.string.unit_us_liquid_pint, R.string.unit_us_liquid_pint_short), - NormalUnit(UnitID.us_legal_cup, BigDecimal.valueOf(236_588_236_499_998_560), UnitGroup.VOLUME, R.string.unit_us_legal_cup, R.string.unit_us_legal_cup_short), - NormalUnit(UnitID.us_fluid_ounce, BigDecimal.valueOf(29_573_529_562_499_996), UnitGroup.VOLUME, R.string.unit_us_fluid_ounce, R.string.unit_us_fluid_ounce_short), - NormalUnit(UnitID.us_tablespoon, BigDecimal.valueOf(14_786_764_781_249_998), UnitGroup.VOLUME, R.string.unit_us_tablespoon, R.string.unit_us_tablespoon_short), - NormalUnit(UnitID.us_teaspoon, BigDecimal.valueOf(4_928_921_593_749_952), UnitGroup.VOLUME, R.string.unit_us_teaspoon, R.string.unit_us_teaspoon_short), - NormalUnit(UnitID.imperial_gallon, BigDecimal.valueOf(4_546_089_999_999_954_400), UnitGroup.VOLUME, R.string.unit_imperial_gallon, R.string.unit_imperial_gallon_short), - NormalUnit(UnitID.imperial_quart, BigDecimal.valueOf(1_136_522_500_000_001_400), UnitGroup.VOLUME, R.string.unit_imperial_quart, R.string.unit_imperial_quart_short), - NormalUnit(UnitID.imperial_pint, BigDecimal.valueOf(568_261_250_000_000_700), UnitGroup.VOLUME, R.string.unit_imperial_pint, R.string.unit_imperial_pint_short), - NormalUnit(UnitID.imperial_cup, BigDecimal.valueOf(284_130_625_000_000_350), UnitGroup.VOLUME, R.string.unit_imperial_cup, R.string.unit_imperial_cup_short), - NormalUnit(UnitID.imperial_fluid_ounce, BigDecimal.valueOf(28_413_062_500_000_036), UnitGroup.VOLUME, R.string.unit_imperial_fluid_ounce, R.string.unit_imperial_fluid_ounce_short), - NormalUnit(UnitID.imperial_tablespoon, BigDecimal.valueOf(17_758_164_062_500_148), UnitGroup.VOLUME, R.string.unit_imperial_tablespoon, R.string.unit_imperial_tablespoon_short), - NormalUnit(UnitID.imperial_teaspoon, BigDecimal.valueOf(5_919_388_020_833_314), UnitGroup.VOLUME, R.string.unit_imperial_teaspoon, R.string.unit_imperial_teaspoon_short), - NormalUnit(UnitID.cubic_millimeter, BigDecimal.valueOf(1_000_000_000_000), UnitGroup.VOLUME, R.string.unit_cubic_millimeter, R.string.unit_cubic_millimeter_short), - NormalUnit(UnitID.cubic_centimeter, BigDecimal.valueOf(1_000_000_000_000_000), UnitGroup.VOLUME, R.string.unit_cubic_centimeter, R.string.unit_cubic_centimeter_short), - NormalUnit(UnitID.cubic_meter, BigDecimal.valueOf(1.0E+21), UnitGroup.VOLUME, R.string.unit_cubic_meter, R.string.unit_cubic_meter_short), - NormalUnit(UnitID.cubic_kilometer, BigDecimal.valueOf(1.0E+30), UnitGroup.VOLUME, R.string.unit_cubic_kilometer, R.string.unit_cubic_kilometer_short), - NormalUnit(UnitID.cubic_inch, BigDecimal.valueOf(1.6387064E+16), UnitGroup.VOLUME, R.string.unit_cubic_inch, R.string.unit_cubic_inch_short), - NormalUnit(UnitID.cubic_foot, BigDecimal.valueOf(2.831684659E+19), UnitGroup.VOLUME, R.string.unit_cubic_foot, R.string.unit_cubic_foot_short), - NormalUnit(UnitID.cubic_yard, BigDecimal.valueOf(7.645548579839955E+20), UnitGroup.VOLUME, R.string.unit_cubic_yard, R.string.unit_cubic_yard_short), - NormalUnit(UnitID.cubic_mile, BigDecimal.valueOf(4.168181825440539E+30), UnitGroup.VOLUME, R.string.unit_cubic_mile, R.string.unit_cubic_mile_short), - ) -} diff --git a/data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt b/data/converter/src/test/java/app/myzel394/numberhub/data/converter/AllUnitsTest.kt similarity index 91% rename from data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt rename to data/converter/src/test/java/app/myzel394/numberhub/data/converter/AllUnitsTest.kt index 572d99f0..575a3b2f 100644 --- a/data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt +++ b/data/converter/src/test/java/app/myzel394/numberhub/data/converter/AllUnitsTest.kt @@ -16,38 +16,37 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.converter +package app.myzel394.numberhub.data.converter -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.converter.collections.accelerationCollection -import com.sadellie.unitto.data.converter.collections.angleCollection -import com.sadellie.unitto.data.converter.collections.areaCollection -import com.sadellie.unitto.data.converter.collections.currencyCollection -import com.sadellie.unitto.data.converter.collections.dataCollection -import com.sadellie.unitto.data.converter.collections.dataTransferCollection -import com.sadellie.unitto.data.converter.collections.electrostaticCapacitance -import com.sadellie.unitto.data.converter.collections.energyCollection -import com.sadellie.unitto.data.converter.collections.flowRateCollection -import com.sadellie.unitto.data.converter.collections.fluxCollection -import com.sadellie.unitto.data.converter.collections.forceCollection -import com.sadellie.unitto.data.converter.collections.fuelConsumptionCollection -import com.sadellie.unitto.data.converter.collections.lengthCollection -import com.sadellie.unitto.data.converter.collections.luminanceCollection -import com.sadellie.unitto.data.converter.collections.massCollection -import com.sadellie.unitto.data.converter.collections.numberBaseCollection -import com.sadellie.unitto.data.converter.collections.powerCollection -import com.sadellie.unitto.data.converter.collections.prefixCollection -import com.sadellie.unitto.data.converter.collections.pressureCollection -import com.sadellie.unitto.data.converter.collections.speedCollection -import com.sadellie.unitto.data.converter.collections.temperatureCollection -import com.sadellie.unitto.data.converter.collections.timeCollection -import com.sadellie.unitto.data.converter.collections.torqueCollection -import com.sadellie.unitto.data.converter.collections.volumeCollection -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.data.converter.collections.accelerationCollection +import app.myzel394.numberhub.data.converter.collections.angleCollection +import app.myzel394.numberhub.data.converter.collections.areaCollection +import app.myzel394.numberhub.data.converter.collections.currencyCollection +import app.myzel394.numberhub.data.converter.collections.dataCollection +import app.myzel394.numberhub.data.converter.collections.dataTransferCollection +import app.myzel394.numberhub.data.converter.collections.electrostaticCapacitance +import app.myzel394.numberhub.data.converter.collections.energyCollection +import app.myzel394.numberhub.data.converter.collections.flowRateCollection +import app.myzel394.numberhub.data.converter.collections.fluxCollection +import app.myzel394.numberhub.data.converter.collections.forceCollection +import app.myzel394.numberhub.data.converter.collections.fuelConsumptionCollection +import app.myzel394.numberhub.data.converter.collections.lengthCollection +import app.myzel394.numberhub.data.converter.collections.luminanceCollection +import app.myzel394.numberhub.data.converter.collections.massCollection +import app.myzel394.numberhub.data.converter.collections.numberBaseCollection +import app.myzel394.numberhub.data.converter.collections.powerCollection +import app.myzel394.numberhub.data.converter.collections.prefixCollection +import app.myzel394.numberhub.data.converter.collections.pressureCollection +import app.myzel394.numberhub.data.converter.collections.speedCollection +import app.myzel394.numberhub.data.converter.collections.temperatureCollection +import app.myzel394.numberhub.data.converter.collections.timeCollection +import app.myzel394.numberhub.data.converter.collections.torqueCollection +import app.myzel394.numberhub.data.converter.collections.volumeCollection +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.converter.unit.NumberBaseUnit import kotlinx.coroutines.runBlocking import org.junit.After import org.junit.Assert.assertEquals @@ -58,29 +57,29 @@ class AllUnitsTest { private var history: MutableMap> = mutableMapOf() private val allUnits = lengthCollection + - currencyCollection + - massCollection + - speedCollection + - temperatureCollection + - areaCollection + - timeCollection + - volumeCollection + - dataCollection + - pressureCollection + - accelerationCollection + - energyCollection + - powerCollection + - angleCollection + - dataTransferCollection + - fluxCollection + - numberBaseCollection + - electrostaticCapacitance + - prefixCollection + - forceCollection + - torqueCollection + - flowRateCollection + - luminanceCollection + - fuelConsumptionCollection + currencyCollection + + massCollection + + speedCollection + + temperatureCollection + + areaCollection + + timeCollection + + volumeCollection + + dataCollection + + pressureCollection + + accelerationCollection + + energyCollection + + powerCollection + + angleCollection + + dataTransferCollection + + fluxCollection + + numberBaseCollection + + electrostaticCapacitance + + prefixCollection + + forceCollection + + torqueCollection + + flowRateCollection + + luminanceCollection + + fuelConsumptionCollection @Test fun testAcceleration() = testWithUnits { @@ -595,13 +594,11 @@ class AllUnitsTest { val actual = when (unitFrom.group) { UnitGroup.NUMBER_BASE -> (unitFrom as NumberBaseUnit).convert((unitTo as NumberBaseUnit), value) - UnitGroup.FLOW_RATE -> (unitFrom as ReverseUnit) - .convert((unitTo as DefaultUnit), BigDecimal(value)) - .format(5, OutputFormat.PLAIN) - else -> (unitFrom as DefaultUnit) - .convert((unitTo as DefaultUnit), BigDecimal(value)) + else -> (unitFrom as BasicUnit.Default) + .convert((unitTo as BasicUnit.Default), BigDecimal(value)) .format(5, OutputFormat.PLAIN) } + assertEquals("Failed at $this to $checkingId", expected, actual) println("PASSED: $this -> $expected == $actual") val content: Set = history.getOrDefault(unitFrom.group, setOf()) diff --git a/data/converter/src/test/java/app/myzel394/numberhub/data/converter/ConverterUIStateKtTest.kt b/data/converter/src/test/java/app/myzel394/numberhub/data/converter/ConverterUIStateKtTest.kt new file mode 100644 index 00000000..25dd7448 --- /dev/null +++ b/data/converter/src/test/java/app/myzel394/numberhub/data/converter/ConverterUIStateKtTest.kt @@ -0,0 +1,247 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.converter + +import android.content.Context +import app.myzel394.numberhub.data.database.CurrencyRatesDao +import app.myzel394.numberhub.data.database.CurrencyRatesEntity +import app.myzel394.numberhub.data.database.UnitsDao +import app.myzel394.numberhub.data.database.UnitsEntity +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import java.math.BigDecimal + +@RunWith(RobolectricTestRunner::class) +class ConverterUIStateKtTest { + + @Test + fun convertTime() { + var basicValue = BigDecimal("1") + val mContext: Context = RuntimeEnvironment.getApplication().applicationContext + val repo = UnitsRepositoryImpl( + unitsDao = object : UnitsDao { + override fun getAllFlow(): Flow> = emptyFlow() + override suspend fun insertUnit(unit: UnitsEntity) {} + override suspend fun getById(unitId: String): UnitsEntity? = null + override suspend fun clear() {} + }, + currencyRatesDao = object : CurrencyRatesDao { + override suspend fun insertRates(currencyRates: List) {} + override suspend fun getLatestRateTimeStamp(baseId: String): Long? = null + override suspend fun getLatestRates(baseId: String): List = emptyList() + override suspend fun getLatestRate(baseId: String, pairId: String): CurrencyRatesEntity? = null + override fun size(): Flow = emptyFlow() + override suspend fun clear() {} + }, + mContext = mContext, + ) + + fun String.formatTime(): ConverterResult.Time { + val unitFrom = NormalUnit( + id = "", + factor = basicValue, + group = UnitGroup.TIME, + displayName = 0, + shortName = 0, + backward = false, + ) + + return repo.convertTime(unitFrom, BigDecimal(this)) + } + + // Edgy things (minus, decimals and zeros) + assertEquals( + ConverterResult.Time( + negative = true, + attosecond = BigDecimal("28"), + ), + "-28".formatTime(), + ) + + assertEquals( + ConverterResult.Time( + negative = true, + attosecond = BigDecimal("0.05"), + ), + "-0.05".formatTime(), + ) + + assertEquals( + ConverterResult.Time(), + "0".formatTime(), + ) + + basicValue = BigDecimal("86400000000000000000000") + assertEquals( + ConverterResult.Time( + negative = true, + day = BigDecimal("28"), + ), + "-28".formatTime(), + ) + assertEquals( + ConverterResult.Time( + negative = true, + hour = BigDecimal("1"), + minute = BigDecimal("12"), + ), + "-0.05".formatTime(), + ) + assertEquals( + ConverterResult.Time(), + "0".formatTime(), + ) + assertEquals( + ConverterResult.Time(), + "-0".formatTime(), + ) + + // DAYS + basicValue = BigDecimal("86400000000000000000000") + assertEquals( + ConverterResult.Time( + hour = BigDecimal("12"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + day = BigDecimal("90"), + minute = BigDecimal("7"), + second = BigDecimal("12"), + ), + "90.005".formatTime(), + ) + + // HOURS + basicValue = BigDecimal("3600000000000000000000") + assertEquals( + ConverterResult.Time( + minute = BigDecimal("30"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + day = BigDecimal("3"), + hour = BigDecimal("18"), + second = BigDecimal("18"), + ), + "90.005".formatTime(), + ) + + // MINUTES + basicValue = BigDecimal("60000000000000000000") + assertEquals( + ConverterResult.Time( + second = BigDecimal("30"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + hour = BigDecimal("1"), + minute = BigDecimal("30"), + millisecond = BigDecimal("300"), + ), + "90.005".formatTime(), + ) + + // SECONDS + basicValue = BigDecimal("1000000000000000000") + assertEquals( + ConverterResult.Time( + millisecond = BigDecimal("500"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + minute = BigDecimal("1"), + second = BigDecimal("30"), + millisecond = BigDecimal("5"), + ), + "90.005".formatTime(), + ) + + // MILLISECONDS + basicValue = BigDecimal("1000000000000000") + assertEquals( + ConverterResult.Time( + microsecond = BigDecimal("500"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + millisecond = BigDecimal("90"), + microsecond = BigDecimal("5"), + ), + "90.005".formatTime(), + ) + + // MICROSECONDS + basicValue = BigDecimal("1000000000000") + assertEquals( + ConverterResult.Time( + nanosecond = BigDecimal("500"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + microsecond = BigDecimal("90"), + nanosecond = BigDecimal("5"), + ), + "90.005".formatTime(), + ) + + // NANOSECONDS + basicValue = BigDecimal("1000000000") + assertEquals( + ConverterResult.Time( + nanosecond = BigDecimal("90"), + attosecond = BigDecimal("5000000"), + ), + "90.005".formatTime(), + ) + + // ATTOSECONDS + basicValue = BigDecimal("1") + assertEquals( + ConverterResult.Time( + attosecond = BigDecimal("0.5"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + attosecond = BigDecimal("90.005"), + ), + "90.005".formatTime(), + ) + } +} diff --git a/data/database/build.gradle.kts b/data/database/build.gradle.kts index 56bc11ee..9d87ab28 100644 --- a/data/database/build.gradle.kts +++ b/data/database/build.gradle.kts @@ -23,7 +23,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.database" +android.namespace = "app.myzel394.numberhub.data.database" android { room { diff --git a/data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/1.json b/data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/1.json similarity index 100% rename from data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/1.json rename to data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/1.json diff --git a/data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/2.json b/data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/2.json similarity index 100% rename from data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/2.json rename to data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/2.json diff --git a/data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/3.json b/data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/3.json similarity index 100% rename from data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/3.json rename to data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/3.json diff --git a/data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/4.json b/data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/4.json similarity index 100% rename from data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/4.json rename to data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/4.json diff --git a/data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/5.json b/data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/5.json similarity index 100% rename from data/database/schemas/com.sadellie.unitto.data.database.UnittoDatabase/5.json rename to data/database/schemas/app.myzel394.numberhub.data.database.UnittoDatabase/5.json diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/CalculatorHistoryDao.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/CalculatorHistoryDao.kt similarity index 89% rename from data/database/src/main/java/com/sadellie/unitto/data/database/CalculatorHistoryDao.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/CalculatorHistoryDao.kt index 6e83cc3e..e59ec290 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/CalculatorHistoryDao.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/CalculatorHistoryDao.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.Dao import androidx.room.Insert @@ -32,6 +32,9 @@ interface CalculatorHistoryDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(vararg historyEntity: CalculatorHistoryEntity) + @Query("DELETE FROM calculator_history WHERE entityId = :entityId") + suspend fun delete(entityId: Int) + @Query("DELETE FROM calculator_history") suspend fun clear() } diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/CalculatorHistoryEntity.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/CalculatorHistoryEntity.kt similarity index 91% rename from data/database/src/main/java/com/sadellie/unitto/data/database/CalculatorHistoryEntity.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/CalculatorHistoryEntity.kt index f27503f3..5e3d62a0 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/CalculatorHistoryEntity.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/CalculatorHistoryEntity.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.ColumnInfo import androidx.room.Entity @@ -27,5 +27,5 @@ class CalculatorHistoryEntity( @PrimaryKey(autoGenerate = true) val entityId: Int = 0, @ColumnInfo(name = "timestamp") val timestamp: Long, @ColumnInfo(name = "expression") val expression: String, - @ColumnInfo(name = "result") val result: String + @ColumnInfo(name = "result") val result: String, ) diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/CurrencyRatesDao.kt similarity index 75% rename from data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/CurrencyRatesDao.kt index 58ea3c4b..9dc01534 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/CurrencyRatesDao.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.Dao import androidx.room.Insert @@ -30,9 +30,15 @@ interface CurrencyRatesDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertRates(currencyRates: List) + @Query("SELECT DISTINCT timestamp FROM currency_rates WHERE base_unit_id = :baseId") + suspend fun getLatestRateTimeStamp(baseId: String): Long? + @Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId") suspend fun getLatestRates(baseId: String): List + @Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId AND pair_unit_id = :pairId") + suspend fun getLatestRate(baseId: String, pairId: String): CurrencyRatesEntity? + @Query("SELECT COUNT(*) from currency_rates") fun size(): Flow diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesEntity.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/CurrencyRatesEntity.kt similarity index 95% rename from data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesEntity.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/CurrencyRatesEntity.kt index e1594db0..150c02c7 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesEntity.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/CurrencyRatesEntity.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.ColumnInfo import androidx.room.Entity @@ -29,5 +29,5 @@ class CurrencyRatesEntity( @ColumnInfo(name = "base_unit_id") val baseUnitId: String, @ColumnInfo(name = "timestamp") val date: Long, @ColumnInfo(name = "pair_unit_id") val pairUnitId: String, - @ColumnInfo(name = "pair_unit_value") val pairUnitValue: BigDecimal? + @ColumnInfo(name = "pair_unit_value") val pairUnitValue: BigDecimal?, ) diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/RawDao.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/RawDao.kt similarity index 95% rename from data/database/src/main/java/com/sadellie/unitto/data/database/RawDao.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/RawDao.kt index 614c2980..ea2f252c 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/RawDao.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/RawDao.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.Dao import androidx.room.RawQuery diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/TimeZoneDao.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/TimeZoneDao.kt similarity index 97% rename from data/database/src/main/java/com/sadellie/unitto/data/database/TimeZoneDao.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/TimeZoneDao.kt index 2153ba7c..9a6ccbf1 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/TimeZoneDao.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/TimeZoneDao.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.Dao import androidx.room.Insert @@ -43,7 +43,7 @@ interface TimeZoneDao { TimeZoneEntity( id = id, position = getMaxPosition() + 1, - ) + ), ) } diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/TimeZoneEntity.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/TimeZoneEntity.kt similarity index 95% rename from data/database/src/main/java/com/sadellie/unitto/data/database/TimeZoneEntity.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/TimeZoneEntity.kt index c7f59814..dd3a6c83 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/TimeZoneEntity.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/TimeZoneEntity.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.ColumnInfo import androidx.room.Entity diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsDao.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnitsDao.kt similarity index 96% rename from data/database/src/main/java/com/sadellie/unitto/data/database/UnitsDao.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/UnitsDao.kt index e0ec2f45..9bd7ee11 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsDao.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnitsDao.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.Dao import androidx.room.Insert diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnitsEntity.kt similarity index 95% rename from data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/UnitsEntity.kt index 22b9c5cb..74425834 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnitsEntity.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.ColumnInfo import androidx.room.Entity @@ -30,7 +30,7 @@ import androidx.room.PrimaryKey * @param frequency Show the amount of time this unit was used */ @Entity(tableName = "units") -class UnitsEntity( +data class UnitsEntity( @PrimaryKey val unitId: String, @ColumnInfo(name = "is_favorite") val isFavorite: Boolean = false, @ColumnInfo(name = "paired_unit_id") val pairedUnitId: String? = null, diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/UnittoDatabase.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnittoDatabase.kt similarity index 84% rename from data/database/src/main/java/com/sadellie/unitto/data/database/UnittoDatabase.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/UnittoDatabase.kt index 42ccc300..7ade09fa 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/UnittoDatabase.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnittoDatabase.kt @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import androidx.room.AutoMigration import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters -import com.sadellie.unitto.data.database.converters.Converters +import app.myzel394.numberhub.data.database.converters.Converters @Database( version = 5, @@ -34,11 +34,11 @@ import com.sadellie.unitto.data.database.converters.Converters CurrencyRatesEntity::class, ], autoMigrations = [ - AutoMigration (from = 1, to = 2), - AutoMigration (from = 2, to = 3), - AutoMigration (from = 3, to = 4), - AutoMigration (from = 4, to = 5), - ] + AutoMigration(from = 1, to = 2), + AutoMigration(from = 2, to = 3), + AutoMigration(from = 3, to = 4), + AutoMigration(from = 4, to = 5), + ], ) @TypeConverters(Converters::class) abstract class UnittoDatabase : RoomDatabase() { diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/UnittoDatabaseModule.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnittoDatabaseModule.kt similarity index 97% rename from data/database/src/main/java/com/sadellie/unitto/data/database/UnittoDatabaseModule.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/UnittoDatabaseModule.kt index 420fecc8..74b40b48 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/UnittoDatabaseModule.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/UnittoDatabaseModule.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database +package app.myzel394.numberhub.data.database import android.content.Context import androidx.room.Room @@ -79,7 +79,7 @@ class UnittoDatabaseModule { return Room.databaseBuilder( appContext.applicationContext, UnittoDatabase::class.java, - DATABASE_NAME + DATABASE_NAME, ).build() } -} \ No newline at end of file +} diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/converters/Converters.kt b/data/database/src/main/java/app/myzel394/numberhub/data/database/converters/Converters.kt similarity index 95% rename from data/database/src/main/java/com/sadellie/unitto/data/database/converters/Converters.kt rename to data/database/src/main/java/app/myzel394/numberhub/data/database/converters/Converters.kt index 8fcacf2a..b147c81a 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/converters/Converters.kt +++ b/data/database/src/main/java/app/myzel394/numberhub/data/database/converters/Converters.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.database.converters +package app.myzel394.numberhub.data.database.converters import androidx.room.TypeConverter import java.math.BigDecimal @@ -36,5 +36,4 @@ class Converters { } catch (e: Exception) { null } - } diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt index c0553397..ad35f5cb 100644 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt +++ b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/BigDecimalMath.kt @@ -78,12 +78,13 @@ internal fun BigDecimal.pow(n: BigDecimal): BigDecimal { val n2IntPart = right.subtract(remainderOfRight) val intPow = pow(n2IntPart.intValueExact(), mathContext) val doublePow = BigDecimal( - toDouble().pow(remainderOfRight.toDouble()) + toDouble().pow(remainderOfRight.toDouble()), ) var result = intPow.multiply(doublePow, mathContext) - if (signOfRight == -1) result = - BigDecimal.ONE.divide(result, mathContext.precision, RoundingMode.HALF_UP) + if (signOfRight == -1) { + result = BigDecimal.ONE.divide(result, mathContext.precision, RoundingMode.HALF_UP) + } return result } @@ -93,6 +94,8 @@ internal fun BigDecimal.factorial(): BigDecimal { if (this < BigDecimal.ZERO) throw ExpressionException.FactorialCalculation() if (this > maxFactorial) throw ExpressionException.TooBig() + if (this.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ONE + var expr = this for (i in 1 until this.toInt()) { expr *= BigDecimal(i) diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt index c86b0ce1..37d0f224 100644 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt +++ b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Expression.kt @@ -18,12 +18,12 @@ package io.github.sadellie.evaluatto -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.core.base.Token +import app.myzel394.numberhub.core.base.MAX_PRECISION +import app.myzel394.numberhub.core.base.Token import java.math.BigDecimal import java.math.RoundingMode -sealed class ExpressionException(override val message: String): Exception(message) { +sealed class ExpressionException(override val message: String) : Exception(message) { class DivideByZero : ExpressionException("Can't divide by zero") class FactorialCalculation : ExpressionException("Can calculate factorial of non-negative real numbers only") class BadExpression : ExpressionException("Invalid expression. Probably some operator lacks argument") @@ -33,9 +33,9 @@ sealed class ExpressionException(override val message: String): Exception(messag class Expression( input: String, private val radianMode: Boolean = true, - private val roundingMode: RoundingMode = RoundingMode.HALF_EVEN + private val roundingMode: RoundingMode = RoundingMode.HALF_EVEN, ) { - private val tokens = Tokenizer(input).tokenize() + private val tokens = input.tokenize() private var cursorPosition = 0 /** @@ -88,8 +88,9 @@ class Expression( while (peek() in listOf(Token.Operator.multiply, Token.Operator.divide)) { when { - moveIfMatched(Token.Operator.multiply) -> expression = - expression.multiply(parseFactor()) + moveIfMatched(Token.Operator.multiply) -> { + expression = expression.multiply(parseFactor()) + } moveIfMatched(Token.Operator.divide) -> { val divisor = parseFactor() diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNCalculation.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNCalculation.kt deleted file mode 100644 index ea6603cc..00000000 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNCalculation.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package io.github.sadellie.evaluatto - -sealed class RPNCalculation { - data object Negate : RPNCalculation() - - data object Clear : RPNCalculation() - data object Enter : RPNCalculation() - data object RotateUp : RPNCalculation() - data object RotateDown : RPNCalculation() - data object Swap : RPNCalculation() - data object Pop : RPNCalculation() - - data object Plus : RPNCalculation() - data object Minus : RPNCalculation() - data object Multiply : RPNCalculation() - data object Divide : RPNCalculation() - data object Percent : RPNCalculation() - data object Power : RPNCalculation() // unused -} diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNEngine.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNEngine.kt deleted file mode 100644 index 40f531eb..00000000 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/RPNEngine.kt +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package io.github.sadellie.evaluatto - -import com.sadellie.unitto.core.base.MAX_PRECISION -import java.math.BigDecimal -import java.math.RoundingMode - -sealed class RPNResult { - - /** - * Both input and stack were changed. - * - * @property input New input. Empty when `null`. - * @property stack New stack. - */ - data class Result( - val input: BigDecimal?, - val stack: List, - ) : RPNResult() - - /** - * Only input has been changed. - * - * @property input New input. - */ - data class NewInput( - val input: BigDecimal, - ) : RPNResult() - - /** - * Only stack has been changed. - * - * @property stack New stack. - */ - data class NewStack( - val stack: List, - ) : RPNResult() - - /** - * Something is wrong. Input/stack is empty or there ane not enough stack objects. - */ - data object BadInput : RPNResult() - - /** - * Dividing by zero, duh - */ - data object DivideByZero : RPNResult() -} - -// vroom vroom mfs -// overdose on early returns -fun RPNCalculation.perform( - input: String, - stack: List, -): RPNResult { - when (this) { - RPNCalculation.Clear -> { - return RPNResult.Result(null, emptyList()) - } - - RPNCalculation.Enter -> { - val inputBD = input.toBigDecimalOrNull() ?: return RPNResult.BadInput - return RPNResult.Result(null, stack + inputBD) - } - - RPNCalculation.Negate -> { - val inputBD = input.toBigDecimalOrNull() ?: return RPNResult.BadInput - val result = inputBD.negate() - return RPNResult.NewInput(result) - } - - RPNCalculation.RotateUp -> { - if (stack.size < 2) return RPNResult.BadInput - return RPNResult.NewStack(stack.rotateUp()) - } - - RPNCalculation.RotateDown -> { - if (stack.size < 2) return RPNResult.BadInput - return RPNResult.NewStack(stack.rotateDown()) - } - - RPNCalculation.Swap -> { - if (stack.isEmpty()) return RPNResult.BadInput - if (input.isEmpty()) { - // Swap last 2 in stack - if (stack.size < 2) return RPNResult.BadInput - return RPNResult.NewStack(stack.swapLastTwo()) - } - - // Swap last and input - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - return RPNResult.Result(lastFromStack, stack.dropLast(1) + inputBD) - } - - RPNCalculation.Pop -> { - val lastStacked = stack.lastOrNull() ?: return RPNResult.BadInput - return RPNResult.Result(lastStacked, stack.dropLast(1)) - } - - RPNCalculation.Plus -> { - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - val result = lastFromStack.plus(inputBD) - return RPNResult.Result(result, stack.dropLast(1)) - } - - RPNCalculation.Minus -> { - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - val result = lastFromStack.minus(inputBD) - return RPNResult.Result(result, stack.dropLast(1)) - } - - RPNCalculation.Multiply -> { - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - val result = lastFromStack.multiply(inputBD) - return RPNResult.Result(result, stack.dropLast(1)) - } - - RPNCalculation.Divide -> { - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - if (inputBD.compareTo(BigDecimal.ZERO) == 0) return RPNResult.DivideByZero - - val result = lastFromStack.divide(inputBD, MAX_PRECISION, RoundingMode.HALF_EVEN) - return RPNResult.Result(result, stack.dropLast(1)) - } - - RPNCalculation.Percent -> { - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - // 100 * 24 / 100 = - val result = lastFromStack - .multiply(inputBD) - .divide(bigDecimalHundred, MAX_PRECISION, RoundingMode.HALF_EVEN) - return RPNResult.Result(result, stack.dropLast(1)) - } - - RPNCalculation.Power -> { - val (lastFromStack, inputBD) = operands(stack, input) ?: return RPNResult.BadInput - val result = lastFromStack.pow(inputBD) - return RPNResult.Result(result, stack.dropLast(1)) - } - } -} - -private val bigDecimalHundred by lazy { BigDecimal("100") } - -private fun operands( - stack: List, - input: String, -): Pair? { - val first = stack.lastOrNull() ?: return null - val second = input.toBigDecimalOrNull() ?: return null - - return first to second -} - -private fun List.swapLastTwo(): List { - if (size < 2) return this - return this - .dropLast(2) - .plus(get(lastIndex)) - .plus(get(lastIndex - 1)) -} - -private fun List.rotateUp(): List { - if (size < 2) return this - return this - .drop(1) - .plus(first()) -} - -private fun List.rotateDown(): List { - if (size < 2) return this - return listOf(last()) - .plus(this.dropLast(1)) -} diff --git a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Tokenizer.kt b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Tokenizer.kt index 129ba237..4c33d2b8 100644 --- a/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Tokenizer.kt +++ b/data/evaluatto/src/main/java/io/github/sadellie/evaluatto/Tokenizer.kt @@ -18,7 +18,7 @@ package io.github.sadellie.evaluatto -import com.sadellie.unitto.core.base.Token +import app.myzel394.numberhub.core.base.Token sealed class TokenizerException(message: String) : Exception(message) { class TooManyFractionSymbols : TokenizerException("Number has multiple commas in it") @@ -26,261 +26,254 @@ sealed class TokenizerException(message: String) : Exception(message) { class BadScientificNotation : TokenizerException("Expected plus or minus symbol after \"E\"") } -class Tokenizer(private val streamOfTokens: String) { - // Don't create object at all? - fun tokenize(): List { - var cursor = 0 - val tokens: MutableList = mutableListOf() +fun String.tokenize(): List { + var cursor = 0 + val tokens: MutableList = mutableListOf() - while (cursor != streamOfTokens.length) { - val nextToken = peekTokenAfter(cursor) + while (cursor != this.length) { + val nextToken = peekTokenAfter(this, cursor) - if (nextToken != null) { - tokens.add(nextToken) - cursor += nextToken.length - } else { - // Didn't find any token, move left slowly (by 1 symbol) - cursor++ - } + if (nextToken != null) { + tokens.add(nextToken) + cursor += nextToken.length + } else { + // Didn't find any token, move left slowly (by 1 symbol) + cursor++ } - - return tokens.repairLexicon() } - private fun peekTokenAfter(cursor: Int): String? { - Token.expressionTokens.forEach { token -> - val subs = streamOfTokens - .substring( - cursor, - (cursor + token.length).coerceAtMost(streamOfTokens.length) - ) - if (subs == token) { - // Got a digit, see if there are other digits coming after - if (token in Token.Digit.allWithDot) { - val number = streamOfTokens - .substring(cursor) - .takeWhile { Token.Digit.allWithDot.contains(it.toString()) } + return tokens.repairLexicon() +} - if (number.count { it.toString() == Token.Digit.dot } > 1) { - throw TokenizerException.TooManyFractionSymbols() - } +private fun peekTokenAfter( + streamOfTokens: String, + cursor: Int, +): String? { + Token.expressionTokens.forEach { token -> + val subs = streamOfTokens + .substring( + cursor, + (cursor + token.length).coerceAtMost(streamOfTokens.length), + ) + if (subs == token) { + // Got a digit, see if there are other digits coming after + if (token in Token.Digit.allWithDot) { + val number = streamOfTokens + .substring(cursor) + .takeWhile { Token.Digit.allWithDot.contains(it.toString()) } - return number - } - return token - } - } - return null - } - - private fun List.repairLexicon(): List { - return this - .missingClosingBrackets() - .unpackNotation() - .missingMultiply() - .unpackAllPercents() - // input like 80%80% should be treated as 80%*80%. - // After unpacking we get (80/100)(80/100), the multiply is missing (!!!) - // No, we can't unpack before fixing missing multiply. - // Ideally we we need to add missing multiply for 80%80% - // In that case unpackAllPercents gets input with all operators 80%*80% in this case - // Can't be done right now since missingMultiply checks for tokens in front only - .missingMultiply() - } - - private fun List.missingClosingBrackets(): List { - val leftBracket = this.count { it == Token.Operator.leftBracket } - val rightBrackets = this.count { it == Token.Operator.rightBracket } - val neededBrackets = leftBracket - rightBrackets - - if (neededBrackets <= 0) return this - - var fixed = this - repeat(neededBrackets) { - fixed = fixed + Token.Operator.rightBracket - } - return fixed - } - - private fun List.missingMultiply(): List { - val result = this.toMutableList() - val original = this - var offset = 0 - - fun addTokenAfter(index: Int) { - result.add(index + 1 + offset, Token.Operator.multiply) - offset += 1 - } - - original.forEachIndexed { index, token -> - when { - // This will not insert multiply between digits because they are grouped into a - // single token. It's not possible to get separate digit tokens near each other - // Things like ["123", "456"] are impossible, will be ["123456"] - token.isDigitToken() || - token in Token.Const.all || - token == Token.Operator.rightBracket -> { - val tokenInFront = original.tokenInFront(index) ?: return@forEachIndexed - - when { - tokenInFront == Token.Operator.leftBracket || - tokenInFront in Token.Func.all || - tokenInFront in Token.Const.all || - tokenInFront == Token.Operator.sqrt || - tokenInFront.isDigitToken() -> { - addTokenAfter(index) - } - } - } - } - } - - return result - } - - private fun List.unpackAllPercents(): List { - var result = this - while (result.contains(Token.Operator.percent)) { - val percIndex = result.indexOf(Token.Operator.percent) - result = result.unpackPercentAt(percIndex) - } - return result - } - - private fun List.unpackNotation(): List { - // Transform 1E+7 ==> 1*10^7 - // Transform 1E-7 ==> 1/10^7 - val result = this.toMutableList() - val listIterator = result.listIterator() - - while (listIterator.hasNext()) { - if (listIterator.next() == Token.DisplayOnly.engineeringE) { - listIterator.remove() - - val tokenAfterE = try { - listIterator.next() - } catch (e: Exception) { - throw TokenizerException.BadScientificNotation() + if (number.count { it.toString() == Token.Digit.dot } > 1) { + throw TokenizerException.TooManyFractionSymbols() } - listIterator.remove() + return number + } + return token + } + } + return null +} - when (tokenAfterE) { - Token.Operator.minus -> listIterator.add(Token.Operator.divide) - Token.Operator.plus -> listIterator.add(Token.Operator.multiply) - else -> throw TokenizerException.BadScientificNotation() - } +private fun MutableList.repairLexicon(): List { + return this + .missingClosingBrackets() + .unpackNotation() + .missingMultiply() + .unpackAllPercents() + // input like 80%80% should be treated as 80%*80%. + // After unpacking we get (80/100)(80/100), the multiply is missing (!!!) + // No, we can't unpack before fixing missing multiply. + // Ideally we we need to add missing multiply for 80%80% + // In that case unpackAllPercents gets input with all operators 80%*80% in this case + // Can't be done right now since missingMultiply checks for tokens in front only + .missingMultiply() +} - listIterator.add("10") - listIterator.add(Token.Operator.power) +private fun MutableList.missingClosingBrackets(): MutableList { + val leftBracket = this.count { it == Token.Operator.leftBracket } + val rightBrackets = this.count { it == Token.Operator.rightBracket } + val neededBrackets = leftBracket - rightBrackets + + if (neededBrackets <= 0) return this + + repeat(neededBrackets) { + this.add(Token.Operator.rightBracket) + } + return this +} + +private fun MutableList.missingMultiply(): MutableList { + val iterator = this.listIterator() + + while (iterator.hasNext()) { + val currentToken = iterator.next() + + // Need two token for checks + if (!iterator.hasNext()) break + + val isDigit = currentToken.isDigitToken() + val isConst = currentToken in Token.Const.all + val isRightBracket = currentToken == Token.Operator.rightBracket + + // may need a multiplication after + if (isDigit || isConst || isRightBracket) { + // Peek next, but then go back + val tokenAfter = iterator.next() + iterator.previous() + + if (tokenAfter == Token.Operator.leftBracket || + tokenAfter in Token.Func.all || + tokenAfter in Token.Const.all || + tokenAfter == Token.Operator.sqrt || + tokenAfter.isDigitToken() + ) { + iterator.add(Token.Operator.multiply) } } - - return result } - private fun List.unpackPercentAt(percentIndex: Int): List { - var cursor = percentIndex + return this +} - // get whatever is the percentage - val percentage = this.getNumberOrExpressionBefore(percentIndex) - // Move cursor - cursor -= percentage.size +private fun MutableList.unpackNotation(): MutableList { + // Transform 1E+7 ==> 1*10^7 + // Transform 1E-7 ==> 1/10^7 + val iterator = this.listIterator() - // get the operator in front - cursor -= 1 - val operator = this.getOrNull(cursor) + while (iterator.hasNext()) { + if (iterator.next() == Token.DisplayOnly.engineeringE) { + iterator.remove() - // Don't go further - if ((operator == null) or (operator !in listOf(Token.Operator.plus, Token.Operator.minus))) { - val mutList = this.toMutableList() + val tokenAfterE = try { + iterator.next() + } catch (e: Exception) { + throw TokenizerException.BadScientificNotation() + } - // Remove percentage - mutList.removeAt(percentIndex) + iterator.remove() - //Add opening bracket before percentage - mutList.add(percentIndex - percentage.size, Token.Operator.leftBracket) + when (tokenAfterE) { + Token.Operator.minus -> iterator.add(Token.Operator.divide) + Token.Operator.plus -> iterator.add(Token.Operator.multiply) + else -> throw TokenizerException.BadScientificNotation() + } - // Add "/ 100" and closing bracket - mutList.addAll(percentIndex + 1, listOf(Token.Operator.divide, "100", Token.Operator.rightBracket)) - - return mutList + iterator.add("10") + iterator.add(Token.Operator.power) } - // Get the base - val base = this.getBaseBefore(cursor) + } + + return this +} + +private fun MutableList.unpackAllPercents(): MutableList { + var result = this + while (result.contains(Token.Operator.percent)) { + val percIndex = result.indexOf(Token.Operator.percent) + result = result.unpackPercentAt(percIndex) + } + return result +} + +private fun MutableList.unpackPercentAt(percentIndex: Int): MutableList { + var cursor = percentIndex + + // get whatever is the percentage + val percentage = this.getNumberOrExpressionBefore(percentIndex) + // Move cursor + cursor -= percentage.size + + // get the operator in front + cursor -= 1 + val operator = this.getOrNull(cursor) + + // Don't go further + if ((operator == null) or (operator !in listOf(Token.Operator.plus, Token.Operator.minus))) { val mutList = this.toMutableList() // Remove percentage mutList.removeAt(percentIndex) - //Add opening bracket before percentage + // Add opening bracket before percentage mutList.add(percentIndex - percentage.size, Token.Operator.leftBracket) - // Add "/ 100" and other stuff - mutList.addAll( - percentIndex + 1, - listOf( - Token.Operator.divide, - "100", - Token.Operator.multiply, - Token.Operator.leftBracket, - *base.toTypedArray(), - Token.Operator.rightBracket, - Token.Operator.rightBracket - ) - ) + // Add "/ 100" and closing bracket + mutList.addAll(percentIndex + 1, listOf(Token.Operator.divide, "100", Token.Operator.rightBracket)) return mutList } + // Get the base + val base = this.getBaseBefore(cursor) + val mutList = this.toMutableList() - private fun List.getNumberOrExpressionBefore(pos: Int): List { - val digits = Token.Digit.allWithDot.map { it[0] } + // Remove percentage + mutList.removeAt(percentIndex) - val tokenInFront = this[pos - 1] + // Add opening bracket before percentage + mutList.add(percentIndex - percentage.size, Token.Operator.leftBracket) - // Just number - if (tokenInFront.all { it in digits }) return listOf(tokenInFront) + // Add "/ 100" and other stuff + mutList.addAll( + percentIndex + 1, + listOf( + Token.Operator.divide, + "100", + Token.Operator.multiply, + Token.Operator.leftBracket, + *base.toTypedArray(), + Token.Operator.rightBracket, + Token.Operator.rightBracket, + ), + ) - // For cases like "100+(2+5)|%". The check above won't pass, so the next expected thing is - // a number in brackets. Anything else is not expected. - if (tokenInFront != Token.Operator.rightBracket) throw TokenizerException.FailedToUnpackNumber() - - // Start walking left until we get balanced brackets - var cursor = pos - 1 - var leftBrackets = 0 - var rightBrackets = 1 // We set 1 because we start with closing bracket - - while (leftBrackets != rightBrackets) { - cursor-- - val currentToken = this[cursor] - if (currentToken == Token.Operator.leftBracket) leftBrackets++ - if (currentToken == Token.Operator.rightBracket) rightBrackets++ - } - - return this.subList(cursor, pos) - } - - private fun List.getBaseBefore(pos: Int): List { - var cursor = pos - var leftBrackets = 0 - var rightBrackets = 0 - - while ((--cursor >= 0)) { - val currentToken = this[cursor] - - if (currentToken == Token.Operator.leftBracket) leftBrackets++ - if (currentToken == Token.Operator.rightBracket) rightBrackets++ - - if (leftBrackets > rightBrackets) break - } - - // Return cursor back to last token - cursor += 1 - - return this.subList(cursor, pos) - } - - private fun String.isDigitToken(): Boolean = first().toString() in Token.Digit.allWithDot - - private fun List.tokenInFront(index: Int): String? = getOrNull(index + 1) + return mutList } + +private fun MutableList.getNumberOrExpressionBefore(pos: Int): List { + val digits = Token.Digit.allWithDot.map { it[0] } + + val tokenInFront = this[pos - 1] + + // Just number + if (tokenInFront.all { it in digits }) return listOf(tokenInFront) + + // For cases like "100+(2+5)|%". The check above won't pass, so the next expected thing is + // a number in brackets. Anything else is not expected. + if (tokenInFront != Token.Operator.rightBracket) throw TokenizerException.FailedToUnpackNumber() + + // Start walking left until we get balanced brackets + var cursor = pos - 1 + var leftBrackets = 0 + var rightBrackets = 1 // We set 1 because we start with closing bracket + + while (leftBrackets != rightBrackets) { + cursor-- + val currentToken = this[cursor] + if (currentToken == Token.Operator.leftBracket) leftBrackets++ + if (currentToken == Token.Operator.rightBracket) rightBrackets++ + } + + return this.subList(cursor, pos) +} + +private fun List.getBaseBefore(pos: Int): List { + var cursor = pos + var leftBrackets = 0 + var rightBrackets = 0 + + while ((--cursor >= 0)) { + val currentToken = this[cursor] + + if (currentToken == Token.Operator.leftBracket) leftBrackets++ + if (currentToken == Token.Operator.rightBracket) rightBrackets++ + + if (leftBrackets > rightBrackets) break + } + + // Return cursor back to last token + cursor += 1 + + return this.subList(cursor, pos) +} + +private fun String.isDigitToken(): Boolean = first().toString() in Token.Digit.allWithDot diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt index e394f36b..03419438 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/ExpressionSimpleTest.kt @@ -108,4 +108,7 @@ class ExpressionSimpleTest { @Test fun expression28() = assertExpr("e", "2.7182818285") + + @Test + fun expression29() = assertExpr("0!", "1") } diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt index de4df510..365ac221 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/FixLexiconTest.kt @@ -25,59 +25,71 @@ class FixLexiconTest { @Test fun `missing multiply`() { assertLex( - "2×(69−420)", "2(69−420)" + "2×(69−420)", + "2(69−420)", ) assertLex( - "0.×(69−420)", "0.(69−420)" + "0.×(69−420)", + "0.(69−420)", ) assertLex( - ".0×(69−420)", ".0(69−420)" + ".0×(69−420)", + ".0(69−420)", ) assertLex( - ".×(69−420)", ".(69−420)" + ".×(69−420)", + ".(69−420)", ) assertLex( "2×(69−420)×(23−4)×cos(9)×tan((sin⁻¹(.9)))", - "2(69−420)(23−4)cos(9)tan((sin⁻¹(.9)))" + "2(69−420)(23−4)cos(9)tan((sin⁻¹(.9)))", ) assertLex( - "e×e+π", "ee+π" + "e×e+π", + "ee+π", ) assertLex( - "(69)×420", "(69)420" + "(69)×420", + "(69)420", ) } @Test fun `balanced brackets`() { assertLex( - "123×(12+4)", "123(12+4" + "123×(12+4)", + "123(12+4", ) assertLex( - "12312+4", "12312+4" + "12312+4", + "12312+4", ) assertLex( - "123)))×12+4", "123)))12+4" + "123)))×12+4", + "123)))12+4", ) assertLex( - "sin(cos(tan(3)))", "sin(cos(tan(3" + "sin(cos(tan(3)))", + "sin(cos(tan(3", ) assertLex( - "sin(cos(tan(3)))", "sin(cos(tan(3)" + "sin(cos(tan(3)))", + "sin(cos(tan(3)", ) assertLex( - "sin(cos(tan(3)))", "sin(cos(tan(3))" + "sin(cos(tan(3)))", + "sin(cos(tan(3))", ) } @@ -85,43 +97,52 @@ class FixLexiconTest { fun `unpack percentage`() { // 132.5+14% −> 132.5+132.5*0.14 assertLex( - "132.5+(14÷100×(132.5))", "132.5+14%" + "132.5+(14÷100×(132.5))", + "132.5+14%", ) // 132.5+(14)% −> 132.5+(14)/100*132.5 assertLex( - "132.5+((14)÷100×(132.5))" , "132.5+(14)%" + "132.5+((14)÷100×(132.5))", + "132.5+(14)%", ) // 132.5+(15+4)% −> 132.5+(15+4)*132.5/100 assertLex( - "132.5+((15+4)÷100×(132.5))", "132.5+(15+4)%" + "132.5+((15+4)÷100×(132.5))", + "132.5+(15+4)%", ) // (132.5+12%)+(15+4)% −> (132.5+12/100*132.5)+(15+4)/100*(132.5+12/100*132.5) assertLex( - "(132.5+(12÷100×(132.5)))+((15+4)÷100×((132.5+(12÷100×(132.5)))))", "(132.5+12%)+(15+4)%" + "(132.5+(12÷100×(132.5)))+((15+4)÷100×((132.5+(12÷100×(132.5)))))", + "(132.5+12%)+(15+4)%", ) // 2% −> 2/100 assertLex( - "(2÷100)", "2%" + "(2÷100)", + "2%", ) assertLex( - "((2)÷100)", "(2)%" + "((2)÷100)", + "(2)%", ) assertLex( - "(132.5+5)+(90÷100×((132.5+5)))", "(132.5+5)+90%" + "(132.5+5)+(90÷100×((132.5+5)))", + "(132.5+5)+90%", ) assertLex( - "((90÷100)+(90÷100×((90÷100))))", "(90%+90%)" + "((90÷100)+(90÷100×((90÷100))))", + "(90%+90%)", ) assertLex( - "((90÷100)÷(90÷100))+((90÷100)−(90÷100×((90÷100))))", "(90%÷90%)+(90%−90%)" + "((90÷100)÷(90÷100))+((90÷100)−(90÷100×((90÷100))))", + "(90%÷90%)+(90%−90%)", ) assertLex("(80÷100)×(80÷100)", "80%80%") diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt index 55861c01..aeb244df 100644 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt +++ b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/Helpers.kt @@ -26,13 +26,13 @@ import java.math.RoundingMode fun assertExpr(expr: String, result: String, radianMode: Boolean = true) = assertEquals( BigDecimal(result).setScale(10, RoundingMode.HALF_EVEN), - Expression(expr, radianMode).calculate().setScale(10, RoundingMode.HALF_EVEN) + Expression(expr, radianMode).calculate().setScale(10, RoundingMode.HALF_EVEN), ) fun assertExprFail( expectedThrowable: Class?, expr: String, - radianMode: Boolean = true + radianMode: Boolean = true, ) { assertThrows(expectedThrowable) { Expression(expr, radianMode = radianMode).calculate() @@ -40,7 +40,7 @@ fun assertExprFail( } fun assertLex(expected: List, actual: String) = - assertEquals(expected, Tokenizer(actual).tokenize()) + assertEquals(expected, actual.tokenize()) fun assertLex(expected: String, actual: String) = - assertEquals(expected, Tokenizer(actual).tokenize().joinToString("")) + assertEquals(expected, actual.tokenize().joinToString("")) diff --git a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/RPNEngineKtTest.kt b/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/RPNEngineKtTest.kt deleted file mode 100644 index 7d3a2e60..00000000 --- a/data/evaluatto/src/test/java/io/github/sadellie/evaluatto/RPNEngineKtTest.kt +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package io.github.sadellie.evaluatto - -import com.sadellie.unitto.core.base.MAX_PRECISION -import org.junit.Assert.assertEquals -import org.junit.Test -import java.math.BigDecimal - -class RPNEngineKtTest { - - @Test - fun testBadOperands() { - // no funny business if input and/or stack is empty - val actual = RPNCalculation.Divide.perform( - input = "", - stack = emptyList() - ) - - assertEquals(RPNResult.BadInput, actual) - } - - @Test - fun testDivide() { - val actual = RPNCalculation.Divide.perform( - input = "2", - stack = listOf(BigDecimal("5")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("2.5").setScale(MAX_PRECISION), actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testDivideByZero() { - val actual = RPNCalculation.Divide.perform( - input = "0", - stack = listOf(BigDecimal("5")) - ) - - assertEquals(RPNResult.DivideByZero, actual) - } - - @Test - fun testMinus() { - val actual = RPNCalculation.Minus.perform( - input = "2", - stack = listOf(BigDecimal("5")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("3"), actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testMultiply() { - val actual = RPNCalculation.Multiply.perform( - input = "2", - stack = listOf(BigDecimal("5")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("10"), actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testNegate() { - val actual = RPNCalculation.Negate.perform( - input = "2", - stack = listOf(BigDecimal("5")) - ) - - if (actual !is RPNResult.NewInput) throw Exception("Wrong return") - - assertEquals(BigDecimal("-2"), actual.input) - } - - @Test - fun testPercent() { - val actual = RPNCalculation.Percent.perform( - input = "150", - stack = listOf(BigDecimal("69")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("103.5").setScale(MAX_PRECISION), actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testPlus() { - val actual = RPNCalculation.Plus.perform( - input = "150", - stack = listOf(BigDecimal("69")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("219"), actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testPower() { - val actual = RPNCalculation.Power.perform( - input = "3", - stack = listOf(BigDecimal("2")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("8"), actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testRotateUp() { - val actual = RPNCalculation.RotateUp.perform( - input = "", - stack = listOf(BigDecimal("1"), BigDecimal("2"), BigDecimal("3")) - ) - - if (actual !is RPNResult.NewStack) throw Exception("Wrong return") - - assertEquals(listOf(BigDecimal("2"), BigDecimal("3"), BigDecimal("1")), actual.stack) - } - - @Test - fun testRotateDown() { - val actual = RPNCalculation.RotateDown.perform( - input = "", - stack = listOf(BigDecimal("1"), BigDecimal("2"), BigDecimal("3")) - ) - - if (actual !is RPNResult.NewStack) throw Exception("Wrong return") - - assertEquals(listOf(BigDecimal("3"), BigDecimal("1"), BigDecimal("2")), actual.stack) - } - - @Test - fun testPop() { - val actual = RPNCalculation.Pop.perform( - input = "", - stack = listOf(BigDecimal("1"), BigDecimal("2"), BigDecimal("3")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("3"), actual.input) - assertEquals(listOf(BigDecimal("1"), BigDecimal("2")), actual.stack) - } - - @Test - fun testClear() { - val actual = RPNCalculation.Clear.perform( - input = "3", - stack = listOf(BigDecimal("2")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(null, actual.input) - assertEquals(emptyList(), actual.stack) - } - - @Test - fun testEnter() { - val actual = RPNCalculation.Enter.perform( - input = "3", - stack = listOf(BigDecimal("2")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(null, actual.input) - assertEquals(listOf(BigDecimal("2"), BigDecimal("3")), actual.stack) - } - - @Test - fun testSwap() { - val actual = RPNCalculation.Swap.perform( - input = "3", - stack = listOf(BigDecimal("2")) - ) - - if (actual !is RPNResult.Result) throw Exception("Wrong return") - - assertEquals(BigDecimal("2"), actual.input) - assertEquals(listOf(BigDecimal("3")), actual.stack) - } - - @Test - fun testSwapEmptyInput() { - val actual = RPNCalculation.Swap.perform( - input = "", - stack = listOf(BigDecimal("1"), BigDecimal("2")) - ) - - if (actual !is RPNResult.NewStack) throw Exception("Wrong return") - - assertEquals(listOf(BigDecimal("2"), BigDecimal("1")), actual.stack) - } - - @Test - fun testSwapEmptyInputNotEnoughInStack() { - val actual = RPNCalculation.Swap.perform( - input = "", - stack = listOf(BigDecimal("1")) - ) - - assertEquals(RPNResult.BadInput, actual) - } - - @Test - fun testSwapEmptyStack() { - val actual = RPNCalculation.Swap.perform( - input = "123", - stack = emptyList() - ) - - assertEquals(RPNResult.BadInput, actual) - } - - @Test - fun testSwapEmptyBoth() { - val actual = RPNCalculation.Swap.perform( - input = "", - stack = emptyList() - ) - - assertEquals(RPNResult.BadInput, actual) - } -} diff --git a/data/licenses/build.gradle.kts b/data/licenses/build.gradle.kts index 2e6c5b1a..de0866b6 100644 --- a/data/licenses/build.gradle.kts +++ b/data/licenses/build.gradle.kts @@ -22,4 +22,4 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.licenses" +android.namespace = "app.myzel394.numberhub.data.licenses" diff --git a/data/licenses/src/main/java/com/sadellie/unitto/data/licenses/ThirdParty.kt b/data/licenses/src/main/java/app/myzel394/numberhub/data/licenses/ThirdParty.kt similarity index 90% rename from data/licenses/src/main/java/com/sadellie/unitto/data/licenses/ThirdParty.kt rename to data/licenses/src/main/java/app/myzel394/numberhub/data/licenses/ThirdParty.kt index 4832d4f6..6dd141c5 100644 --- a/data/licenses/src/main/java/com/sadellie/unitto/data/licenses/ThirdParty.kt +++ b/data/licenses/src/main/java/app/myzel394/numberhub/data/licenses/ThirdParty.kt @@ -16,14 +16,14 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.licenses +package app.myzel394.numberhub.data.licenses data class ThirdParty( val name: String, val dev: String?, val website: String?, val license: String?, - val description: String? + val description: String?, ) val ALL_THIRD_PARTY by lazy { @@ -33,91 +33,91 @@ val ALL_THIRD_PARTY by lazy { dev = "Fawaz Ahmed (fawazahmed0)", website = "https://github.com/fawazahmed0/currency-api", license = "The Unlicense", - description = "Free Currency Rates API" + description = "Free Currency Rates API", ), ThirdParty( name = "Lato", dev = "Łukasz Dziedzic", website = "https://fonts.google.com/specimen/Lato/about", license = "Open Font License", - description = "Lato is a sans serif typeface family started in the summer of 2010 by Warsaw-based designer Łukasz Dziedzic (“Lato” means “Summer” in Polish). In December 2010 the Lato family was published under the Open Font License by his foundry tyPoland, with support from Google." + description = "Lato is a sans serif typeface family started in the summer of 2010 by Warsaw-based designer Łukasz Dziedzic (“Lato” means “Summer” in Polish). In December 2010 the Lato family was published under the Open Font License by his foundry tyPoland, with support from Google.", ), ThirdParty( name = "Core Kotlin Extensions", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/core", license = "Apache-2.0", - description = "Kotlin extensions for 'core' artifact" + description = "Kotlin extensions for 'core' artifact", ), ThirdParty( name = "Material Components for Android", dev = "The Android Open Source Project", website = "https://github.com/material-components/material-components-android", license = "Apache-2.0", - description = "Material Components for Android is a static library that you can add to your Android application in order to use APIs that provide implementations of the Material Design specification. Compatible on devices running API 14 or later." + description = "Material Components for Android is a static library that you can add to your Android application in order to use APIs that provide implementations of the Material Design specification. Compatible on devices running API 14 or later.", ), ThirdParty( name = "Compose UI primitives", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/compose-ui", license = "Apache-2.0", - description = "Compose UI primitives. This library contains the primitives that form the Compose UI Toolkit, such as drawing, measurement and layout." + description = "Compose UI primitives. This library contains the primitives that form the Compose UI Toolkit, such as drawing, measurement and layout.", ), ThirdParty( name = "Compose Navigation", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/navigation", license = "Apache-2.0", - description = "Compose integration with Navigation" + description = "Compose integration with Navigation", ), ThirdParty( name = "Compose Material3 Components", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/compose-material3", license = "Apache-2.0", - description = "Compose Material You Design Components library" + description = "Compose Material You Design Components library", ), ThirdParty( name = "Navigation Compose Hilt Integration", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/hilt", license = "Apache-2.0", - description = "Navigation Compose Hilt Integration" + description = "Navigation Compose Hilt Integration", ), ThirdParty( name = "Hilt Android", dev = "The Android Open Source Project", website = "https://github.com/google/dagger", license = "Apache-2.0", - description = "A fast dependency injector for Android and Java." + description = "A fast dependency injector for Android and Java.", ), ThirdParty( name = "Compose Material Icons Extended", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/compose-material", license = "Apache-2.0", - description = "Compose Material Design extended icons. This module contains all Material icons. It is a very large dependency and should not be included directly." + description = "Compose Material Design extended icons. This module contains all Material icons. It is a very large dependency and should not be included directly.", ), ThirdParty( name = "Android Preferences DataStore", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/datastore", license = "Apache-2.0", - description = "Android Preferences DataStore" + description = "Android Preferences DataStore", ), ThirdParty( name = "Accompanist System UI Controller library", dev = "Google", website = "https://github.com/google/accompanist/", license = "Apache-2.0", - description = "Utilities for Jetpack Compose" + description = "Utilities for Jetpack Compose", ), ThirdParty( name = "Compose Tooling API", dev = "The Android Open Source Project", website = "https://developer.android.com/jetpack/androidx/releases/compose-ui", license = "Apache-2.0", - description = "Compose tooling library API. This library provides the API required to declare @Preview composables in user apps." - ) + description = "Compose tooling library API. This library provides the API required to declare @Preview composables in user apps.", + ), ) } diff --git a/data/model/build.gradle.kts b/data/model/build.gradle.kts index f3cf74a7..52843c0d 100644 --- a/data/model/build.gradle.kts +++ b/data/model/build.gradle.kts @@ -21,7 +21,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.model" +android.namespace = "app.myzel394.numberhub.data.model" dependencies { implementation(libs.com.github.sadellie.themmo.core) diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/HistoryItem.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/HistoryItem.kt similarity index 92% rename from data/model/src/main/java/com/sadellie/unitto/data/model/HistoryItem.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/HistoryItem.kt index 6bbc18a6..7b4a638e 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/HistoryItem.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/HistoryItem.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model +package app.myzel394.numberhub.data.model import java.util.Date @@ -24,5 +24,5 @@ data class HistoryItem( val id: Int, val date: Date, val expression: String, - val result: String + val result: String, ) diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitGroup.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/UnitGroup.kt similarity index 85% rename from data/model/src/main/java/com/sadellie/unitto/data/model/UnitGroup.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/converter/UnitGroup.kt index 03510dab..706a65b0 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitGroup.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/UnitGroup.kt @@ -16,22 +16,15 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model +package app.myzel394.numberhub.data.model.converter import androidx.annotation.StringRes -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R -val ALL_UNIT_GROUPS: List by lazy { - UnitGroup.entries -} - -/** - * As not all measurements can be converted between each other, we separate them into groups. - * Within one group all measurements can be converted - */ enum class UnitGroup( - @StringRes val res: Int + @StringRes val res: Int, ) { + // NOTE: This order is used as default for new users LENGTH(res = R.string.unit_group_length), CURRENCY(res = R.string.unit_group_currency), MASS(res = R.string.unit_group_mass), @@ -55,5 +48,5 @@ enum class UnitGroup( TORQUE(res = R.string.unit_group_torque), FLOW_RATE(res = R.string.unit_group_flow_rate), LUMINANCE(res = R.string.unit_group_luminance), - FUEL_CONSUMPTION(res = R.string.unit_group_fuel_consumption) + FUEL_CONSUMPTION(res = R.string.unit_group_fuel_consumption), } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitsListSorting.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/UnitsListSorting.kt similarity index 93% rename from data/model/src/main/java/com/sadellie/unitto/data/model/UnitsListSorting.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/converter/UnitsListSorting.kt index b688182f..ade9439e 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitsListSorting.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/UnitsListSorting.kt @@ -16,6 +16,6 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model +package app.myzel394.numberhub.data.model.converter enum class UnitsListSorting { USAGE, ALPHABETICAL, SCALE_DESC, SCALE_ASC } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorUIState.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/BasicUnit.kt similarity index 56% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorUIState.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/BasicUnit.kt index 4db3230d..1b697d5f 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorUIState.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/BasicUnit.kt @@ -16,21 +16,32 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.data.model.converter.unit -import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import androidx.annotation.StringRes +import app.myzel394.numberhub.data.model.converter.UnitGroup import java.math.BigDecimal -internal sealed class RPNCalculatorUIState { - data object Loading : RPNCalculatorUIState() +sealed interface BasicUnit { - data class Ready( - val input: TextFieldValue, - val stack: List, - val precision: Int, - val outputFormat: Int, - val formatterSymbols: FormatterSymbols, - val middleZero: Boolean, - ) : RPNCalculatorUIState() + val id: String + + val group: UnitGroup + + @get:StringRes + val displayName: Int + + @get:StringRes val shortName: Int + + val factor: BigDecimal + + interface NumberBase : BasicUnit { + fun convert(unitTo: NumberBase, value: String): String + } + + interface Default : BasicUnit { + val backward: Boolean + + fun convert(unitTo: Default, value: BigDecimal): BigDecimal + } } diff --git a/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/NormalUnit.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/NormalUnit.kt new file mode 100644 index 00000000..cf3dc601 --- /dev/null +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/NormalUnit.kt @@ -0,0 +1,71 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.model.converter.unit + +import app.myzel394.numberhub.core.base.MAX_PRECISION +import app.myzel394.numberhub.data.common.isEqualTo +import app.myzel394.numberhub.data.model.converter.UnitGroup +import java.math.BigDecimal +import java.math.RoundingMode + +data class NormalUnit( + override val id: String, + override val factor: BigDecimal, + override val group: UnitGroup, + override val displayName: Int, + override val shortName: Int, + override val backward: Boolean = false, +) : BasicUnit.Default { + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal { + if (value.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO + return when { + // BACKWARD -> BACKWARD + backward and unitTo.backward -> + unitTo + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .multiply(value) + .div(this.factor) + + // BACKWARD -> FORWARD + backward and !unitTo.backward -> + this + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .div(unitTo.factor) + .div(value) + + // FORWARD -> BACKWARD + !backward and unitTo.backward -> + unitTo + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .div(this.factor) + .div(value) + + // FORWARD -> FORWARD + else -> + this + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .multiply(value) + .div(unitTo.factor) + } + } +} diff --git a/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/NumberBaseUnit.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/NumberBaseUnit.kt new file mode 100644 index 00000000..ee3318cb --- /dev/null +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/converter/unit/NumberBaseUnit.kt @@ -0,0 +1,34 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.model.converter.unit + +import app.myzel394.numberhub.data.model.converter.UnitGroup +import java.math.BigDecimal + +data class NumberBaseUnit( + override val id: String, + override val factor: BigDecimal, + override val group: UnitGroup, + override val displayName: Int, + override val shortName: Int, +) : BasicUnit.NumberBase { + override fun convert(unitTo: BasicUnit.NumberBase, value: String): String = value + .toBigInteger(factor.intValueExact()) + .toString(unitTo.factor.intValueExact()) +} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/CalculatorHistoryRepository.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/repository/CalculatorHistoryRepository.kt similarity index 83% rename from data/model/src/main/java/com/sadellie/unitto/data/model/repository/CalculatorHistoryRepository.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/repository/CalculatorHistoryRepository.kt index ce10de75..417e18db 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/CalculatorHistoryRepository.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/repository/CalculatorHistoryRepository.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.repository +package app.myzel394.numberhub.data.model.repository -import com.sadellie.unitto.data.model.HistoryItem +import app.myzel394.numberhub.data.model.HistoryItem import kotlinx.coroutines.flow.Flow interface CalculatorHistoryRepository { @@ -26,7 +26,11 @@ interface CalculatorHistoryRepository { suspend fun add( expression: String, - result: String + result: String, + ) + + suspend fun delete( + item: HistoryItem, ) suspend fun clear() diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/repository/UserPreferencesRepository.kt similarity index 65% rename from data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/repository/UserPreferencesRepository.kt index 36c65d62..084f5428 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/repository/UserPreferencesRepository.kt @@ -16,22 +16,21 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.repository +package app.myzel394.numberhub.data.model.repository -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.userprefs.AboutPreferences -import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences -import com.sadellie.unitto.data.model.userprefs.AppPreferences -import com.sadellie.unitto.data.model.userprefs.BodyMassPreferences -import com.sadellie.unitto.data.model.userprefs.CalculatorPreferences -import com.sadellie.unitto.data.model.userprefs.ConverterPreferences -import com.sadellie.unitto.data.model.userprefs.DisplayPreferences -import com.sadellie.unitto.data.model.userprefs.FormattingPreferences -import com.sadellie.unitto.data.model.userprefs.GeneralPreferences -import com.sadellie.unitto.data.model.userprefs.StartingScreenPreferences -import com.sadellie.unitto.data.model.userprefs.UnitGroupsPreferences +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.userprefs.AboutPreferences +import app.myzel394.numberhub.data.model.userprefs.AddSubtractPreferences +import app.myzel394.numberhub.data.model.userprefs.AppPreferences +import app.myzel394.numberhub.data.model.userprefs.BodyMassPreferences +import app.myzel394.numberhub.data.model.userprefs.CalculatorPreferences +import app.myzel394.numberhub.data.model.userprefs.ConverterPreferences +import app.myzel394.numberhub.data.model.userprefs.DisplayPreferences +import app.myzel394.numberhub.data.model.userprefs.FormattingPreferences +import app.myzel394.numberhub.data.model.userprefs.GeneralPreferences +import app.myzel394.numberhub.data.model.userprefs.StartingScreenPreferences +import app.myzel394.numberhub.data.model.userprefs.UnitGroupsPreferences import io.github.sadellie.themmo.core.MonetMode import io.github.sadellie.themmo.core.ThemingMode import kotlinx.coroutines.flow.Flow @@ -51,11 +50,11 @@ interface UserPreferencesRepository { suspend fun updateDigitsPrecision(precision: Int) - suspend fun updateSeparator(separator: Int) + suspend fun updateFormatterSymbols(grouping: String, fractional: String) suspend fun updateOutputFormat(outputFormat: Int) - suspend fun updateLatestPairOfUnits(unitFrom: AbstractUnit, unitTo: AbstractUnit) + suspend fun updateLatestPairOfUnits(unitFrom: String, unitTo: String) suspend fun updateThemingMode(themingMode: ThemingMode) @@ -71,6 +70,10 @@ interface UserPreferencesRepository { suspend fun updateShownUnitGroups(shownUnitGroups: List) + suspend fun addShownUnitGroup(unitGroup: UnitGroup) + + suspend fun removeShownUnitGroup(unitGroup: UnitGroup) + suspend fun updateLastReadChangelog(value: String) suspend fun updateVibrations(enabled: Boolean) @@ -93,5 +96,9 @@ interface UserPreferencesRepository { suspend fun updateAcButton(enabled: Boolean) - suspend fun updateRpnMode(enabled: Boolean) + suspend fun updateAdditionalButtons(enabled: Boolean) + + suspend fun updateInverseMode(enabled: Boolean) + + suspend fun updateHasSeenNewAppAnnouncement(value: Boolean) } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/timezone/FavoriteZone.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/timezone/FavoriteZone.kt similarity index 92% rename from data/model/src/main/java/com/sadellie/unitto/data/model/timezone/FavoriteZone.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/timezone/FavoriteZone.kt index 00d4d734..e85d3973 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/timezone/FavoriteZone.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/timezone/FavoriteZone.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.timezone +package app.myzel394.numberhub.data.model.timezone import android.icu.util.TimeZone import android.os.Build @@ -26,5 +26,5 @@ import androidx.annotation.RequiresApi data class FavoriteZone( val timeZone: TimeZone, val position: Int, - val label: String + val label: String, ) diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/timezone/SearchResultZone.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/timezone/SearchResultZone.kt similarity index 95% rename from data/model/src/main/java/com/sadellie/unitto/data/model/timezone/SearchResultZone.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/timezone/SearchResultZone.kt index f387637c..89843194 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/timezone/SearchResultZone.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/timezone/SearchResultZone.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.timezone +package app.myzel394.numberhub.data.model.timezone import android.icu.util.TimeZone diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AboutPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AboutPreferences.kt similarity index 90% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AboutPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AboutPreferences.kt index 75741993..c2e77c52 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AboutPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AboutPreferences.kt @@ -16,8 +16,8 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -interface AboutPreferences{ +interface AboutPreferences { val enableToolsExperiment: Boolean } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AddSubtractPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AddSubtractPreferences.kt similarity index 79% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AddSubtractPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AddSubtractPreferences.kt index 4a86b10f..57fc62f7 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AddSubtractPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AddSubtractPreferences.kt @@ -16,8 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -interface AddSubtractPreferences{ - val separator: Int +import app.myzel394.numberhub.core.base.FormatterSymbols + +interface AddSubtractPreferences { + val formatterSymbols: FormatterSymbols } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AppPreferences.kt similarity index 93% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AppPreferences.kt index 7de30184..d699fb4e 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/AppPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/AppPreferences.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs import io.github.sadellie.themmo.core.MonetMode import io.github.sadellie.themmo.core.ThemingMode @@ -30,6 +30,5 @@ interface AppPreferences { val startingScreen: String val enableToolsExperiment: Boolean val systemFont: Boolean - val rpnMode: Boolean val enableVibrations: Boolean } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/BodyMassPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/BodyMassPreferences.kt similarity index 79% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/BodyMassPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/BodyMassPreferences.kt index 8a389033..724de194 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/BodyMassPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/BodyMassPreferences.kt @@ -16,8 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -interface BodyMassPreferences{ - val separator: Int +import app.myzel394.numberhub.core.base.FormatterSymbols + +interface BodyMassPreferences { + val formatterSymbols: FormatterSymbols } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/CalculatorPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/CalculatorPreferences.kt similarity index 81% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/CalculatorPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/CalculatorPreferences.kt index c4aa4611..d62da20a 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/CalculatorPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/CalculatorPreferences.kt @@ -16,13 +16,17 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs + +import app.myzel394.numberhub.core.base.FormatterSymbols interface CalculatorPreferences { val radianMode: Boolean - val separator: Int + val formatterSymbols: FormatterSymbols val middleZero: Boolean val acButton: Boolean + val additionalButtons: Boolean + val inverseMode: Boolean val partialHistoryView: Boolean val precision: Int val outputFormat: Int diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/ConverterPreferences.kt similarity index 80% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/ConverterPreferences.kt index b4526f6d..bc7fb03a 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/ConverterPreferences.kt @@ -16,13 +16,14 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting interface ConverterPreferences { - val separator: Int + val formatterSymbols: FormatterSymbols val middleZero: Boolean val acButton: Boolean val precision: Int diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/DisplayPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/DisplayPreferences.kt similarity index 94% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/DisplayPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/DisplayPreferences.kt index 9c300c6e..313e14da 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/DisplayPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/DisplayPreferences.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs interface DisplayPreferences { val systemFont: Boolean diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/FormattingPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/FormattingPreferences.kt similarity index 80% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/FormattingPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/FormattingPreferences.kt index b39dce0f..ba415cd6 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/FormattingPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/FormattingPreferences.kt @@ -16,10 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -interface FormattingPreferences{ +import app.myzel394.numberhub.core.base.FormatterSymbols + +interface FormattingPreferences { val digitsPrecision: Int - val separator: Int + val formatterSymbols: FormatterSymbols val outputFormat: Int } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/GeneralPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/GeneralPreferences.kt similarity index 89% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/GeneralPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/GeneralPreferences.kt index e59916dc..eedcb342 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/GeneralPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/GeneralPreferences.kt @@ -16,9 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs interface GeneralPreferences { val lastReadChangelog: String val enableVibrations: Boolean + val hasSeenNewAppAnnouncement: Boolean } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/StartingScreenPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/StartingScreenPreferences.kt similarity index 89% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/StartingScreenPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/StartingScreenPreferences.kt index cff6385a..d34a3742 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/StartingScreenPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/StartingScreenPreferences.kt @@ -16,8 +16,8 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -interface StartingScreenPreferences{ +interface StartingScreenPreferences { val startingScreen: String } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/UnitGroupsPreferences.kt similarity index 84% rename from data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt rename to data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/UnitGroupsPreferences.kt index 175d2b8a..59f91fd3 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt +++ b/data/model/src/main/java/app/myzel394/numberhub/data/model/userprefs/UnitGroupsPreferences.kt @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.userprefs +package app.myzel394.numberhub.data.model.userprefs -import com.sadellie.unitto.data.model.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitGroup -interface UnitGroupsPreferences{ +interface UnitGroupsPreferences { val shownUnitGroups: List } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt deleted file mode 100644 index 3dd07e63..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.repository - -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate - -interface UnitsRepository { - val units: Flow> - - suspend fun getById(id: String): AbstractUnit - - suspend fun getCollection(group: UnitGroup): List - - suspend fun favorite(unit: AbstractUnit) - - suspend fun incrementCounter(unit: AbstractUnit) - - suspend fun setPair(unit: AbstractUnit, pair: AbstractUnit) - - suspend fun updateRates(unit: AbstractUnit): LocalDate? - - suspend fun filterUnits( - query: String, - unitGroup: UnitGroup?, - favoritesOnly: Boolean, - hideBrokenUnits: Boolean, - sorting: UnitsListSorting, - shownUnitGroups: List = emptyList(), - ): Map> -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/BackwardUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/BackwardUnit.kt deleted file mode 100644 index 7630cb45..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/BackwardUnit.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.data.common.isEqualTo -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal -import java.math.RoundingMode - -data class BackwardUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { - // Avoid division by zero - if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO - - return when (unitTo) { - is NormalUnit -> this - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .div(unitTo.basicUnit) - .div(value) - - is BackwardUnit -> unitTo - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .multiply(value) - .div(this.basicUnit) - - else -> BigDecimal.ZERO - } - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): BackwardUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt deleted file mode 100644 index a915cab6..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.data.common.isEqualTo -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal -import java.math.RoundingMode - -data class NormalUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { - // Avoid division by zero - if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO - - return when (unitTo) { - is NormalUnit -> this - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .multiply(value) - .div(unitTo.basicUnit) - - is BackwardUnit -> unitTo - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .div(this.basicUnit) - .div(value) - - else -> BigDecimal.ZERO - } - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): NormalUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt deleted file mode 100644 index f34dc90a..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal - -data class NumberBaseUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : AbstractUnit { - fun convert(toBase: NumberBaseUnit, input: String): String { - return input.toBigInteger(basicUnit.intValueExact()).toString(toBase.basicUnit.intValueExact()) - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): NumberBaseUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt deleted file mode 100644 index d4f56cfc..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal -import java.math.RoundingMode - -data class ReverseUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { - - return unitTo - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .div(this.basicUnit) - .multiply(value) - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): ReverseUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt deleted file mode 100644 index e52af2a6..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal - -data class TemperatureUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, - val customConvert: (unitTo: DefaultUnit, value: BigDecimal) -> BigDecimal -): DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal = customConvert(unitTo, value) - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): TemperatureUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/timezone/build.gradle.kts b/data/timezone/build.gradle.kts index 9a4f531b..1f1e8f05 100644 --- a/data/timezone/build.gradle.kts +++ b/data/timezone/build.gradle.kts @@ -22,7 +22,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.timezone" +android.namespace = "app.myzel394.numberhub.data.timezone" dependencies { implementation(project(":core:base")) diff --git a/data/timezone/src/main/java/com/sadellie/unitto/data/timezone/TimeZonesRepository.kt b/data/timezone/src/main/java/app/myzel394/numberhub/data/timezone/TimeZonesRepository.kt similarity index 90% rename from data/timezone/src/main/java/com/sadellie/unitto/data/timezone/TimeZonesRepository.kt rename to data/timezone/src/main/java/app/myzel394/numberhub/data/timezone/TimeZonesRepository.kt index 30082f36..5df1375d 100644 --- a/data/timezone/src/main/java/com/sadellie/unitto/data/timezone/TimeZonesRepository.kt +++ b/data/timezone/src/main/java/app/myzel394/numberhub/data/timezone/TimeZonesRepository.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.timezone +package app.myzel394.numberhub.data.timezone import android.icu.text.LocaleDisplayNames import android.icu.text.TimeZoneNames @@ -24,12 +24,12 @@ import android.icu.util.TimeZone import android.icu.util.ULocale import android.os.Build import androidx.annotation.RequiresApi -import com.sadellie.unitto.data.common.displayName -import com.sadellie.unitto.data.common.lev -import com.sadellie.unitto.data.common.regionName -import com.sadellie.unitto.data.database.TimeZoneDao -import com.sadellie.unitto.data.model.timezone.FavoriteZone -import com.sadellie.unitto.data.model.timezone.SearchResultZone +import app.myzel394.numberhub.data.common.displayName +import app.myzel394.numberhub.data.common.lev +import app.myzel394.numberhub.data.common.regionName +import app.myzel394.numberhub.data.database.TimeZoneDao +import app.myzel394.numberhub.data.model.timezone.FavoriteZone +import app.myzel394.numberhub.data.model.timezone.SearchResultZone import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first @@ -59,8 +59,8 @@ class TimeZonesRepository @Inject constructor( FavoriteZone( timeZone = tz, position = entity.position, - label = entity.label - ) + label = entity.label, + ), ) } @@ -146,8 +146,8 @@ class TimeZonesRepository @Inject constructor( timeZone = it, name = displayName, region = regionName, - rank = nameMatch - ) + rank = nameMatch, + ), ) return@forEach } @@ -159,8 +159,8 @@ class TimeZonesRepository @Inject constructor( timeZone = it, name = displayName, region = regionName, - rank = regionMatch - ) + rank = regionMatch, + ), ) return@forEach } diff --git a/data/userprefs/build.gradle.kts b/data/userprefs/build.gradle.kts index 85c79516..530cc911 100644 --- a/data/userprefs/build.gradle.kts +++ b/data/userprefs/build.gradle.kts @@ -22,7 +22,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.data.userprefs" +android.namespace = "app.myzel394.numberhub.data.userprefs" dependencies { implementation(libs.androidx.datastore.datastore.preferences) diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/DataStoreModule.kt b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/DataStoreModule.kt similarity index 93% rename from data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/DataStoreModule.kt rename to data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/DataStoreModule.kt index bfa93e0a..30ca8ede 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/DataStoreModule.kt +++ b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/DataStoreModule.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.userprefs +package app.myzel394.numberhub.data.userprefs import android.content.Context import androidx.datastore.core.DataStore @@ -25,7 +25,7 @@ import androidx.datastore.preferences.core.PreferenceDataStoreFactory import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.emptyPreferences import androidx.datastore.preferences.preferencesDataStoreFile -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -53,7 +53,7 @@ class DataStoreModule { fun provideUserPreferencesDataStore(@ApplicationContext appContext: Context): DataStore { return PreferenceDataStoreFactory.create( corruptionHandler = ReplaceFileCorruptionHandler { emptyPreferences() }, - produceFile = { appContext.preferencesDataStoreFile(USER_PREFERENCES) } + produceFile = { appContext.preferencesDataStoreFile(USER_PREFERENCES) }, ) } diff --git a/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PreferenceExt.kt b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PreferenceExt.kt new file mode 100644 index 00000000..8fc3e046 --- /dev/null +++ b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PreferenceExt.kt @@ -0,0 +1,168 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.data.userprefs + +import androidx.datastore.preferences.core.Preferences +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.base.TopLevelDestinations +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import io.github.sadellie.themmo.core.MonetMode +import io.github.sadellie.themmo.core.ThemingMode + +internal fun Preferences.getEnableDynamicTheme(): Boolean { + return this[PrefsKeys.ENABLE_DYNAMIC_THEME] ?: true +} + +internal fun Preferences.getThemingMode(): ThemingMode { + return this[PrefsKeys.THEMING_MODE] + ?.letTryOrNull { ThemingMode.valueOf(it) } + ?: ThemingMode.AUTO +} + +internal fun Preferences.getEnableAmoledTheme(): Boolean { + return this[PrefsKeys.ENABLE_AMOLED_THEME] ?: false +} + +internal fun Preferences.getCustomColor(): Long { + return this[PrefsKeys.CUSTOM_COLOR] ?: 16L // From Color.Unspecified +} + +internal fun Preferences.getMonetMode(): MonetMode { + return this[PrefsKeys.MONET_MODE] + ?.letTryOrNull { MonetMode.valueOf(it) } + ?: MonetMode.TonalSpot +} + +internal fun Preferences.getStartingScreen(): String { + return this[PrefsKeys.STARTING_SCREEN] ?: TopLevelDestinations.CALCULATOR_GRAPH +} + +internal fun Preferences.getEnableToolsExperiment(): Boolean { + return this[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false +} + +internal fun Preferences.getSystemFont(): Boolean { + return this[PrefsKeys.SYSTEM_FONT] ?: false +} + +internal fun Preferences.getLastReadChangelog(): String { + return this[PrefsKeys.LAST_READ_CHANGELOG] ?: "" +} + +internal fun Preferences.getEnableVibrations(): Boolean { + return this[PrefsKeys.ENABLE_VIBRATIONS] ?: true +} + +internal fun Preferences.getRadianMode(): Boolean { + return this[PrefsKeys.RADIAN_MODE] ?: true +} + +internal fun Preferences.getHasSeenNewAppAnnouncement(): Boolean { + return this[PrefsKeys.HAS_SEEN_NEW_APP_ANNOUNCEMENT] ?: false +} + +internal fun Preferences.getFormatterSymbols(): FormatterSymbols { + val grouping = this[PrefsKeys.FORMATTER_GROUPING] + val fractional = this[PrefsKeys.FORMATTER_FRACTIONAL] + + // Updating from older version or fresh install + // TODO Remove in the future + if ((grouping == null) or (fractional == null)) { + return when (this[PrefsKeys.SEPARATOR] ?: 0) { + 0 -> FormatterSymbols(Token.SPACE, Token.PERIOD) + 1 -> FormatterSymbols(Token.PERIOD, Token.COMMA) + else -> FormatterSymbols(Token.COMMA, Token.PERIOD) + } + } + + return FormatterSymbols(grouping ?: Token.SPACE, fractional ?: Token.PERIOD) +} + +internal fun Preferences.getMiddleZero(): Boolean { + return this[PrefsKeys.MIDDLE_ZERO] ?: true +} + +internal fun Preferences.getPartialHistoryView(): Boolean { + return this[PrefsKeys.PARTIAL_HISTORY_VIEW] ?: true +} + +internal fun Preferences.getDigitsPrecision(): Int { + return this[PrefsKeys.DIGITS_PRECISION] ?: 3 +} + +internal fun Preferences.getOutputFormat(): Int { + return this[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN +} + +internal fun Preferences.getUnitConverterFormatTime(): Boolean { + return this[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false +} + +internal fun Preferences.getUnitConverterSorting(): UnitsListSorting { + return this[PrefsKeys.UNIT_CONVERTER_SORTING] + ?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE +} + +internal fun Preferences.getShownUnitGroups(): List { + return this[PrefsKeys.SHOWN_UNIT_GROUPS] + ?.letTryOrNull { list -> + list + .ifEmpty { return@letTryOrNull listOf() } + .split(",") + .map { UnitGroup.valueOf(it) } + } + ?: UnitGroup.entries +} + +internal fun Preferences.getUnitConverterFavoritesOnly(): Boolean { + return this[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] + ?: false +} + +internal fun Preferences.getLatestLeftSide(): String { + return this[PrefsKeys.LATEST_LEFT_SIDE] ?: UnitID.kilometer +} + +internal fun Preferences.getLatestRightSide(): String { + return this[PrefsKeys.LATEST_RIGHT_SIDE] ?: UnitID.mile +} + +internal fun Preferences.getAcButton(): Boolean { + return this[PrefsKeys.AC_BUTTON] ?: true +} + +internal fun Preferences.getAdditionalButtons(): Boolean { + return this[PrefsKeys.ADDITIONAL_BUTTONS] ?: false +} + +internal fun Preferences.getInverseMode(): Boolean { + return this[PrefsKeys.INVERSE_MODE] ?: false +} + +internal fun List.packToString(): String = this.joinToString(",") + +private inline fun T.letTryOrNull(block: (T) -> R): R? = try { + this?.let(block) +} catch (e: Exception) { + null +} diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PreferenceModels.kt similarity index 67% rename from data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt rename to data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PreferenceModels.kt index 2a60d1d9..0fafec83 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt +++ b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PreferenceModels.kt @@ -16,22 +16,22 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.userprefs +package app.myzel394.numberhub.data.userprefs -import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.userprefs.AboutPreferences -import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences -import com.sadellie.unitto.data.model.userprefs.AppPreferences -import com.sadellie.unitto.data.model.userprefs.BodyMassPreferences -import com.sadellie.unitto.data.model.userprefs.CalculatorPreferences -import com.sadellie.unitto.data.model.userprefs.ConverterPreferences -import com.sadellie.unitto.data.model.userprefs.DisplayPreferences -import com.sadellie.unitto.data.model.userprefs.FormattingPreferences -import com.sadellie.unitto.data.model.userprefs.GeneralPreferences -import com.sadellie.unitto.data.model.userprefs.StartingScreenPreferences -import com.sadellie.unitto.data.model.userprefs.UnitGroupsPreferences +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.userprefs.AboutPreferences +import app.myzel394.numberhub.data.model.userprefs.AddSubtractPreferences +import app.myzel394.numberhub.data.model.userprefs.AppPreferences +import app.myzel394.numberhub.data.model.userprefs.BodyMassPreferences +import app.myzel394.numberhub.data.model.userprefs.CalculatorPreferences +import app.myzel394.numberhub.data.model.userprefs.ConverterPreferences +import app.myzel394.numberhub.data.model.userprefs.DisplayPreferences +import app.myzel394.numberhub.data.model.userprefs.FormattingPreferences +import app.myzel394.numberhub.data.model.userprefs.GeneralPreferences +import app.myzel394.numberhub.data.model.userprefs.StartingScreenPreferences +import app.myzel394.numberhub.data.model.userprefs.UnitGroupsPreferences import io.github.sadellie.themmo.core.MonetMode import io.github.sadellie.themmo.core.ThemingMode @@ -44,27 +44,29 @@ data class AppPreferencesImpl( override val startingScreen: String, override val enableToolsExperiment: Boolean, override val systemFont: Boolean, - override val rpnMode: Boolean, override val enableVibrations: Boolean, ) : AppPreferences data class GeneralPreferencesImpl( override val lastReadChangelog: String, override val enableVibrations: Boolean, + override val hasSeenNewAppAnnouncement: Boolean, ) : GeneralPreferences data class CalculatorPreferencesImpl( override val radianMode: Boolean, - override val separator: Int, + override val formatterSymbols: FormatterSymbols, override val middleZero: Boolean, override val acButton: Boolean, + override val additionalButtons: Boolean, + override val inverseMode: Boolean, override val partialHistoryView: Boolean, override val precision: Int, override val outputFormat: Int, ) : CalculatorPreferences data class ConverterPreferencesImpl( - override val separator: Int, + override val formatterSymbols: FormatterSymbols, override val middleZero: Boolean, override val acButton: Boolean, override val precision: Int, @@ -86,20 +88,20 @@ data class DisplayPreferencesImpl( data class FormattingPreferencesImpl( override val digitsPrecision: Int, - override val separator: Int, + override val formatterSymbols: FormatterSymbols, override val outputFormat: Int, ) : FormattingPreferences data class UnitGroupsPreferencesImpl( - override val shownUnitGroups: List = ALL_UNIT_GROUPS, + override val shownUnitGroups: List = UnitGroup.entries, ) : UnitGroupsPreferences data class AddSubtractPreferencesImpl( - override val separator: Int, + override val formatterSymbols: FormatterSymbols, ) : AddSubtractPreferences data class BodyMassPreferencesImpl( - override val separator: Int, + override val formatterSymbols: FormatterSymbols, ) : BodyMassPreferences data class AboutPreferencesImpl( diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PrefsKeys.kt similarity index 84% rename from data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt rename to data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PrefsKeys.kt index c3c23cb1..a97ef803 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PrefsKeys.kt +++ b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/PrefsKeys.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.userprefs +package app.myzel394.numberhub.data.userprefs import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey @@ -37,16 +37,21 @@ object PrefsKeys { val ENABLE_VIBRATIONS = booleanPreferencesKey("ENABLE_VIBRATIONS_PREF_KEY") val MIDDLE_ZERO = booleanPreferencesKey("MIDDLE_ZERO_PREF_KEY") val AC_BUTTON = booleanPreferencesKey("AC_BUTTON_PREF_KEY") - val RPN_MODE = booleanPreferencesKey("RPN_MODE_PREF_KEY") + val HAS_SEEN_NEW_APP_ANNOUNCEMENT = booleanPreferencesKey("HAS_SEEN_NEW_APP_ANNOUNCEMENT_PREF_KEY") + // val RPN_MODE = booleanPreferencesKey("RPN_MODE_PREF_KEY") // FORMATTER val DIGITS_PRECISION = intPreferencesKey("DIGITS_PRECISION_PREF_KEY") val SEPARATOR = intPreferencesKey("SEPARATOR_PREF_KEY") + val FORMATTER_GROUPING = stringPreferencesKey("FORMATTER_GROUPING_PREF_KEY") + val FORMATTER_FRACTIONAL = stringPreferencesKey("FORMATTER_FRACTIONAL_PREF_KEY") val OUTPUT_FORMAT = intPreferencesKey("OUTPUT_FORMAT_PREF_KEY") // CALCULATOR val RADIAN_MODE = booleanPreferencesKey("RADIAN_MODE_PREF_KEY") val PARTIAL_HISTORY_VIEW = booleanPreferencesKey("PARTIAL_HISTORY_VIEW_PREF_KEY") + val ADDITIONAL_BUTTONS = booleanPreferencesKey("ADDITIONAL_BUTTONS_PREF_KEY") + val INVERSE_MODE = booleanPreferencesKey("INVERSE_MODE_PREF_KEY") // UNIT CONVERTER val LATEST_LEFT_SIDE = stringPreferencesKey("LATEST_LEFT_SIDE_PREF_KEY") diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/UserPreferencesRepositoryImpl.kt similarity index 74% rename from data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt rename to data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/UserPreferencesRepositoryImpl.kt index 57d3e616..c047af42 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt +++ b/data/userprefs/src/main/java/app/myzel394/numberhub/data/userprefs/UserPreferencesRepositoryImpl.kt @@ -16,27 +16,26 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.userprefs +package app.myzel394.numberhub.data.userprefs import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.emptyPreferences -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.userprefs.AboutPreferences -import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences -import com.sadellie.unitto.data.model.userprefs.AppPreferences -import com.sadellie.unitto.data.model.userprefs.BodyMassPreferences -import com.sadellie.unitto.data.model.userprefs.CalculatorPreferences -import com.sadellie.unitto.data.model.userprefs.ConverterPreferences -import com.sadellie.unitto.data.model.userprefs.DisplayPreferences -import com.sadellie.unitto.data.model.userprefs.FormattingPreferences -import com.sadellie.unitto.data.model.userprefs.GeneralPreferences -import com.sadellie.unitto.data.model.userprefs.StartingScreenPreferences -import com.sadellie.unitto.data.model.userprefs.UnitGroupsPreferences +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.model.userprefs.AboutPreferences +import app.myzel394.numberhub.data.model.userprefs.AddSubtractPreferences +import app.myzel394.numberhub.data.model.userprefs.AppPreferences +import app.myzel394.numberhub.data.model.userprefs.BodyMassPreferences +import app.myzel394.numberhub.data.model.userprefs.CalculatorPreferences +import app.myzel394.numberhub.data.model.userprefs.ConverterPreferences +import app.myzel394.numberhub.data.model.userprefs.DisplayPreferences +import app.myzel394.numberhub.data.model.userprefs.FormattingPreferences +import app.myzel394.numberhub.data.model.userprefs.GeneralPreferences +import app.myzel394.numberhub.data.model.userprefs.StartingScreenPreferences +import app.myzel394.numberhub.data.model.userprefs.UnitGroupsPreferences import io.github.sadellie.themmo.core.MonetMode import io.github.sadellie.themmo.core.ThemingMode import kotlinx.coroutines.flow.Flow @@ -62,7 +61,6 @@ class UserPreferencesRepositoryImpl @Inject constructor( startingScreen = preferences.getStartingScreen(), enableToolsExperiment = preferences.getEnableToolsExperiment(), systemFont = preferences.getSystemFont(), - rpnMode = preferences.getRpnMode(), enableVibrations = preferences.getEnableVibrations(), ) } @@ -72,6 +70,7 @@ class UserPreferencesRepositoryImpl @Inject constructor( GeneralPreferencesImpl( lastReadChangelog = preferences.getLastReadChangelog(), enableVibrations = preferences.getEnableVibrations(), + hasSeenNewAppAnnouncement = preferences.getHasSeenNewAppAnnouncement(), ) } @@ -79,19 +78,21 @@ class UserPreferencesRepositoryImpl @Inject constructor( .map { preferences -> CalculatorPreferencesImpl( radianMode = preferences.getRadianMode(), - separator = preferences.getSeparator(), + formatterSymbols = preferences.getFormatterSymbols(), middleZero = preferences.getMiddleZero(), partialHistoryView = preferences.getPartialHistoryView(), precision = preferences.getDigitsPrecision(), outputFormat = preferences.getOutputFormat(), acButton = preferences.getAcButton(), + additionalButtons = preferences.getAdditionalButtons(), + inverseMode = preferences.getInverseMode(), ) } override val converterPrefs: Flow = data .map { preferences -> ConverterPreferencesImpl( - separator = preferences.getSeparator(), + formatterSymbols = preferences.getFormatterSymbols(), middleZero = preferences.getMiddleZero(), precision = preferences.getDigitsPrecision(), outputFormat = preferences.getOutputFormat(), @@ -119,7 +120,7 @@ class UserPreferencesRepositoryImpl @Inject constructor( .map { preferences -> FormattingPreferencesImpl( digitsPrecision = preferences.getDigitsPrecision(), - separator = preferences.getSeparator(), + formatterSymbols = preferences.getFormatterSymbols(), outputFormat = preferences.getOutputFormat(), ) } @@ -134,21 +135,21 @@ class UserPreferencesRepositoryImpl @Inject constructor( override val addSubtractPrefs: Flow = data .map { preferences -> AddSubtractPreferencesImpl( - separator = preferences.getSeparator(), + formatterSymbols = preferences.getFormatterSymbols(), ) } override val bodyMassPrefs: Flow = data .map { preferences -> BodyMassPreferencesImpl( - separator = preferences.getSeparator(), + formatterSymbols = preferences.getFormatterSymbols(), ) } override val aboutPrefs: Flow = data .map { preferences -> AboutPreferencesImpl( - enableToolsExperiment = preferences.getEnableToolsExperiment() + enableToolsExperiment = preferences.getEnableToolsExperiment(), ) } @@ -165,9 +166,13 @@ class UserPreferencesRepositoryImpl @Inject constructor( } } - override suspend fun updateSeparator(separator: Int) { + override suspend fun updateFormatterSymbols(grouping: String, fractional: String) { + // Grouping and fractional symbols are always different + if (grouping == fractional) return + dataStore.edit { preferences -> - preferences[PrefsKeys.SEPARATOR] = separator + preferences[PrefsKeys.FORMATTER_GROUPING] = grouping + preferences[PrefsKeys.FORMATTER_FRACTIONAL] = fractional } } @@ -177,10 +182,10 @@ class UserPreferencesRepositoryImpl @Inject constructor( } } - override suspend fun updateLatestPairOfUnits(unitFrom: AbstractUnit, unitTo: AbstractUnit) { + override suspend fun updateLatestPairOfUnits(unitFrom: String, unitTo: String) { dataStore.edit { preferences -> - preferences[PrefsKeys.LATEST_LEFT_SIDE] = unitFrom.id - preferences[PrefsKeys.LATEST_RIGHT_SIDE] = unitTo.id + preferences[PrefsKeys.LATEST_LEFT_SIDE] = unitFrom + preferences[PrefsKeys.LATEST_RIGHT_SIDE] = unitTo } } @@ -222,7 +227,25 @@ class UserPreferencesRepositoryImpl @Inject constructor( override suspend fun updateShownUnitGroups(shownUnitGroups: List) { dataStore.edit { preferences -> - preferences[PrefsKeys.SHOWN_UNIT_GROUPS] = shownUnitGroups.joinToString(",") + preferences[PrefsKeys.SHOWN_UNIT_GROUPS] = shownUnitGroups.packToString() + } + } + + override suspend fun addShownUnitGroup(unitGroup: UnitGroup) { + dataStore.edit { preferences -> + preferences[PrefsKeys.SHOWN_UNIT_GROUPS] = preferences + .getShownUnitGroups() + .plus(unitGroup) + .packToString() + } + } + + override suspend fun removeShownUnitGroup(unitGroup: UnitGroup) { + dataStore.edit { preferences -> + preferences[PrefsKeys.SHOWN_UNIT_GROUPS] = preferences + .getShownUnitGroups() + .minus(unitGroup) + .packToString() } } @@ -292,9 +315,21 @@ class UserPreferencesRepositoryImpl @Inject constructor( } } - override suspend fun updateRpnMode(enabled: Boolean) { + override suspend fun updateAdditionalButtons(enabled: Boolean) { dataStore.edit { preferences -> - preferences[PrefsKeys.RPN_MODE] = enabled + preferences[PrefsKeys.ADDITIONAL_BUTTONS] = enabled + } + } + + override suspend fun updateInverseMode(enabled: Boolean) { + dataStore.edit { preferences -> + preferences[PrefsKeys.INVERSE_MODE] = enabled + } + } + + override suspend fun updateHasSeenNewAppAnnouncement(value: Boolean) { + dataStore.edit { preferences -> + preferences[PrefsKeys.HAS_SEEN_NEW_APP_ANNOUNCEMENT] = value } } } diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt deleted file mode 100644 index c0e6336a..00000000 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.userprefs - -import androidx.datastore.preferences.core.Preferences -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.Separator -import com.sadellie.unitto.core.base.TopLevelDestinations -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import io.github.sadellie.themmo.core.MonetMode -import io.github.sadellie.themmo.core.ThemingMode - -fun Preferences.getEnableDynamicTheme(): Boolean { - return this[PrefsKeys.ENABLE_DYNAMIC_THEME] ?: true -} - -fun Preferences.getThemingMode(): ThemingMode { - return this[PrefsKeys.THEMING_MODE] - ?.letTryOrNull { ThemingMode.valueOf(it) } - ?: ThemingMode.AUTO -} - -fun Preferences.getEnableAmoledTheme(): Boolean { - return this[PrefsKeys.ENABLE_AMOLED_THEME] ?: false -} - -fun Preferences.getCustomColor(): Long { - return this[PrefsKeys.CUSTOM_COLOR] ?: 16L // From Color.Unspecified -} - -fun Preferences.getMonetMode(): MonetMode { - return this[PrefsKeys.MONET_MODE] - ?.letTryOrNull { MonetMode.valueOf(it) } - ?: MonetMode.TonalSpot -} - -fun Preferences.getStartingScreen(): String { - return this[PrefsKeys.STARTING_SCREEN] ?: TopLevelDestinations.CALCULATOR_GRAPH -} - -fun Preferences.getEnableToolsExperiment(): Boolean { - return this[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false -} - -fun Preferences.getSystemFont(): Boolean { - return this[PrefsKeys.SYSTEM_FONT] ?: false -} - -fun Preferences.getLastReadChangelog(): String { - return this[PrefsKeys.LAST_READ_CHANGELOG] ?: "" -} - -fun Preferences.getEnableVibrations(): Boolean { - return this[PrefsKeys.ENABLE_VIBRATIONS] ?: true -} - -fun Preferences.getRadianMode(): Boolean { - return this[PrefsKeys.RADIAN_MODE] ?: true -} - -fun Preferences.getSeparator(): Int { - return this[PrefsKeys.SEPARATOR] ?: Separator.SPACE -} - -fun Preferences.getMiddleZero(): Boolean { - return this[PrefsKeys.MIDDLE_ZERO] ?: true -} - -fun Preferences.getPartialHistoryView(): Boolean { - return this[PrefsKeys.PARTIAL_HISTORY_VIEW] ?: true -} - -fun Preferences.getDigitsPrecision(): Int { - return this[PrefsKeys.DIGITS_PRECISION] ?: 3 -} - -fun Preferences.getOutputFormat(): Int { - return this[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN -} - -fun Preferences.getUnitConverterFormatTime(): Boolean { - return this[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false -} - -fun Preferences.getUnitConverterSorting(): UnitsListSorting { - return this[PrefsKeys.UNIT_CONVERTER_SORTING] - ?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE -} - -fun Preferences.getShownUnitGroups(): List { - return this[PrefsKeys.SHOWN_UNIT_GROUPS] - ?.letTryOrNull { list -> - list - .ifEmpty { return@letTryOrNull listOf() } - .split(",") - .map { UnitGroup.valueOf(it) } - } - ?: ALL_UNIT_GROUPS -} - -fun Preferences.getUnitConverterFavoritesOnly(): Boolean { - return this[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] - ?: false -} - -fun Preferences.getLatestLeftSide(): String { - return this[PrefsKeys.LATEST_LEFT_SIDE] ?: UnitID.kilometer -} - -fun Preferences.getLatestRightSide(): String { - return this[PrefsKeys.LATEST_RIGHT_SIDE] ?: UnitID.mile -} - -fun Preferences.getAcButton(): Boolean { - return this[PrefsKeys.AC_BUTTON] ?: true -} - -fun Preferences.getRpnMode(): Boolean { - return this[PrefsKeys.RPN_MODE] ?: false -} - -private inline fun T.letTryOrNull(block: (T) -> R): R? = try { - this?.let(block) -} catch (e: Exception) { - null -} \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/10.txt b/fastlane/metadata/android/en-US/changelogs/10.txt deleted file mode 100644 index 141dba98..00000000 --- a/fastlane/metadata/android/en-US/changelogs/10.txt +++ /dev/null @@ -1,7 +0,0 @@ -"Electric purple" update: -1. You can now control which unit groups will be seen in your app -2. Updated visuals for unit selection screens -3. Application stability and performance improvements -4. Visual tweaks - -Roadmap: https://trello.com/b/cxAbRlvu/unitto \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/11.txt b/fastlane/metadata/android/en-US/changelogs/11.txt deleted file mode 100644 index fe75a393..00000000 --- a/fastlane/metadata/android/en-US/changelogs/11.txt +++ /dev/null @@ -1,8 +0,0 @@ -Wee-Woo, "Fire engine red" update is here! - -1. Calculator. No need to switch between apps, calculate and convert in one-go. Quick note about calculator – it's smart, like really. -2. Settings screen. Added icons and rearranged screen. It's now way easier to customize your experience. -3. Green is now greener. Now using a more saturated green. -4. Some tiny little barely visible UI tweaks. - -Thank you for using Unitto! \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/12.txt b/fastlane/metadata/android/en-US/changelogs/12.txt deleted file mode 100644 index fe75a393..00000000 --- a/fastlane/metadata/android/en-US/changelogs/12.txt +++ /dev/null @@ -1,8 +0,0 @@ -Wee-Woo, "Fire engine red" update is here! - -1. Calculator. No need to switch between apps, calculate and convert in one-go. Quick note about calculator – it's smart, like really. -2. Settings screen. Added icons and rearranged screen. It's now way easier to customize your experience. -3. Green is now greener. Now using a more saturated green. -4. Some tiny little barely visible UI tweaks. - -Thank you for using Unitto! \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/13.txt b/fastlane/metadata/android/en-US/changelogs/13.txt deleted file mode 100644 index 28ef1a68..00000000 --- a/fastlane/metadata/android/en-US/changelogs/13.txt +++ /dev/null @@ -1,5 +0,0 @@ -Fixed crashes and Dynamic Colors. - -Tip: Setting > Themes > Dynamic colors. - -Thank you for using Unitto! \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/14.txt b/fastlane/metadata/android/en-US/changelogs/14.txt deleted file mode 100644 index 357c3bd2..00000000 --- a/fastlane/metadata/android/en-US/changelogs/14.txt +++ /dev/null @@ -1,8 +0,0 @@ -Amazing new features: -1. Number base converter. Enable it: Settings > Unit groups -2. Flux converter -3. New font -4. Search by unit short names -5. French and German translations - -https://sadellie.github.io/unitto \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/16.txt b/fastlane/metadata/android/en-US/changelogs/16.txt deleted file mode 100644 index 56e9da56..00000000 --- a/fastlane/metadata/android/en-US/changelogs/16.txt +++ /dev/null @@ -1,7 +0,0 @@ -Hot magenta update: -1. Added more Pressure units -2. Better formatting for time. Tap the output to switch formatting. -3. Button vibrations. dzzz-dzzz… -4. Improved animations - -https://sadellie.github.io/unitto \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/17.txt b/fastlane/metadata/android/en-US/changelogs/17.txt deleted file mode 100644 index eac54800..00000000 --- a/fastlane/metadata/android/en-US/changelogs/17.txt +++ /dev/null @@ -1,5 +0,0 @@ -"Illuminating emerald" update is here: -• Calculator -• Nautical mile - -That's it, thanks \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/18.txt b/fastlane/metadata/android/en-US/changelogs/18.txt deleted file mode 100644 index cb278c5f..00000000 --- a/fastlane/metadata/android/en-US/changelogs/18.txt +++ /dev/null @@ -1 +0,0 @@ -Fixed crashes in calculator. \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/19.txt b/fastlane/metadata/android/en-US/changelogs/19.txt deleted file mode 100644 index 73305852..00000000 --- a/fastlane/metadata/android/en-US/changelogs/19.txt +++ /dev/null @@ -1,7 +0,0 @@ -"Jazzberry jam" update: - -- Units list sorting option -- New units: Electrostatic capacitance, Force, Torque, Flow rate, Luminance, Prefix -- Improved adaptive design -- Special formatter for time conversion -- Microscopic bug fixes diff --git a/fastlane/metadata/android/en-US/changelogs/20.txt b/fastlane/metadata/android/en-US/changelogs/20.txt deleted file mode 100644 index ac298f73..00000000 --- a/fastlane/metadata/android/en-US/changelogs/20.txt +++ /dev/null @@ -1,6 +0,0 @@ -"Kobicha" update: - -- Unitto is now called Calculator and has a *new icon -- Quick Settings Tile -- Better app themes -- Better button icons diff --git a/fastlane/metadata/android/en-US/changelogs/21.txt b/fastlane/metadata/android/en-US/changelogs/21.txt deleted file mode 100644 index a1fb0e4e..00000000 --- a/fastlane/metadata/android/en-US/changelogs/21.txt +++ /dev/null @@ -1,7 +0,0 @@ -"Lilac Luster" update: - -- Non-mathematical percentage support -- New interactive Formatting settings -- Date difference tool -- Improved performance and UI/UX -- Added Italian localization diff --git a/fastlane/metadata/android/en-US/changelogs/22.txt b/fastlane/metadata/android/en-US/changelogs/22.txt deleted file mode 100644 index d1f86cf0..00000000 --- a/fastlane/metadata/android/en-US/changelogs/22.txt +++ /dev/null @@ -1,9 +0,0 @@ -"Lilac Luster" update: - -- Non-mathematical percentage support -- New interactive Formatting settings -- Date difference tool -- Improved performance and UI/UX -- Added Italian localization - -Sorry for crashes! \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/23.txt b/fastlane/metadata/android/en-US/changelogs/23.txt deleted file mode 100644 index 30360a96..00000000 --- a/fastlane/metadata/android/en-US/changelogs/23.txt +++ /dev/null @@ -1,8 +0,0 @@ -"Mikado Yellow" update: - -- Date calculator -- Shortcuts -- Option to swap zero and decimal buttons -- Decimal percentages support -- Manually update currency rates -- Fix gestures diff --git a/fastlane/metadata/android/en-US/changelogs/24.txt b/fastlane/metadata/android/en-US/changelogs/24.txt deleted file mode 100644 index 2d4458c9..00000000 --- a/fastlane/metadata/android/en-US/changelogs/24.txt +++ /dev/null @@ -1 +0,0 @@ -Small fix in Unit Converter diff --git a/fastlane/metadata/android/en-US/changelogs/26.txt b/fastlane/metadata/android/en-US/changelogs/26.txt deleted file mode 100644 index f0112352..00000000 --- a/fastlane/metadata/android/en-US/changelogs/26.txt +++ /dev/null @@ -1,7 +0,0 @@ -"Nadeshiko Pink" update: - -- Language picker -- System font option -- Improved currency converter -- Added new translations -- Very small quality of life improvements diff --git a/fastlane/metadata/android/en-US/changelogs/29.txt b/fastlane/metadata/android/en-US/changelogs/29.txt deleted file mode 100644 index 1f9f4b7d..00000000 --- a/fastlane/metadata/android/en-US/changelogs/29.txt +++ /dev/null @@ -1,7 +0,0 @@ -"Olive Green" update: - -- Time zone converter -- AC Button -- New search experience -- No more Montserrat, only Lato and system font -- Removed Herobrine diff --git a/fastlane/metadata/android/en-US/changelogs/32.txt b/fastlane/metadata/android/en-US/changelogs/32.txt deleted file mode 100644 index 52168691..00000000 --- a/fastlane/metadata/android/en-US/changelogs/32.txt +++ /dev/null @@ -1,8 +0,0 @@ -"Popstar" update: - -- Input is now not cleared by default (see calculator settings) -- Fractional output -- Chrome OS, tablets and foldables support -- Improved landscape and split screen layout -- Added more units -- Date difference improvements diff --git a/fastlane/metadata/android/en-US/changelogs/33.txt b/fastlane/metadata/android/en-US/changelogs/33.txt deleted file mode 100644 index 52168691..00000000 --- a/fastlane/metadata/android/en-US/changelogs/33.txt +++ /dev/null @@ -1,8 +0,0 @@ -"Popstar" update: - -- Input is now not cleared by default (see calculator settings) -- Fractional output -- Chrome OS, tablets and foldables support -- Improved landscape and split screen layout -- Added more units -- Date difference improvements diff --git a/fastlane/metadata/android/en-US/changelogs/35.txt b/fastlane/metadata/android/en-US/changelogs/35.txt deleted file mode 100644 index e615f923..00000000 --- a/fastlane/metadata/android/en-US/changelogs/35.txt +++ /dev/null @@ -1,8 +0,0 @@ -"Quick Silver" update: - -- Calculator widget -- Body mass calculator -- Back up and restore data -- Feet and inches input and output -- Pace units -- Chinese (Simplified) language diff --git a/fastlane/metadata/android/en-US/changelogs/36.txt b/fastlane/metadata/android/en-US/changelogs/36.txt deleted file mode 100644 index 4c6b7cda..00000000 --- a/fastlane/metadata/android/en-US/changelogs/36.txt +++ /dev/null @@ -1,4 +0,0 @@ -- Fixed calculator formatting issues -- Fixed feet and inches formatting - -Thank you for reporting this issues diff --git a/fastlane/metadata/android/en-US/changelogs/8.txt b/fastlane/metadata/android/en-US/changelogs/8.txt deleted file mode 100644 index a94af201..00000000 --- a/fastlane/metadata/android/en-US/changelogs/8.txt +++ /dev/null @@ -1,11 +0,0 @@ -"Cornsilk" update: -1. Added new units and unit groups. -2. You can control whether or not usage statistics is sent. -3. Rechecked every single unit to make sure that the accuracy is still as high as possible. -4. App now takes even less time to load. -5. Fixed performance during list scrolling. -6. Theme generation bug fixes. -7. Added UK English localisation. - -Next update "Dark sea green" will focus on improving user experience. -Roadmap: https://trello.com/b/cxAbRlvu/unitto \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/9.txt b/fastlane/metadata/android/en-US/changelogs/9.txt deleted file mode 100644 index fe0a7e53..00000000 --- a/fastlane/metadata/android/en-US/changelogs/9.txt +++ /dev/null @@ -1,11 +0,0 @@ -"Dark sea green" update is here: -1. Brand new screen for Themes -2. Increased keyboard button text size -3. Animated TopBar text on app launch -4. Animated long press on keyboard buttons -5. Animated "swap units" button -6. Animated theme change -7. App loads even faster now -8. Tiny fixes - -Roadmap: https://trello.com/b/cxAbRlvu/unitto \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 78eb463a..c718a6d3 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -31,7 +31,7 @@ Look for Calculator on your home screen after installing the app. Permissions -com.sadellie.unitto.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION +app.myzel394.numberhub.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION Read (boring): https://developer.android.com/about/versions/14/behavior-changes-14#runtime-receivers-exported android.permission.INTERNET diff --git a/feature/bodymass/build.gradle.kts b/feature/bodymass/build.gradle.kts index a7b9924f..9a44e303 100644 --- a/feature/bodymass/build.gradle.kts +++ b/feature/bodymass/build.gradle.kts @@ -24,7 +24,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.bodymass" +android.namespace = "app.myzel394.numberhub.feature.bodymass" dependencies { implementation(project(":data:common")) diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassScreen.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassScreen.kt similarity index 82% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassScreen.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassScreen.kt index de0f3ce0..d1b48193 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassScreen.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass +package app.myzel394.numberhub.feature.bodymass import androidx.compose.animation.AnimatedContent import androidx.compose.animation.Crossfade @@ -49,26 +49,25 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.MenuButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar -import com.sadellie.unitto.core.ui.common.SegmentedButton -import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow -import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.data.common.isEqualTo -import com.sadellie.unitto.feature.bodymass.components.BodyMassResult -import com.sadellie.unitto.feature.bodymass.components.BodyMassTextField +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.DrawerButton +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ScaffoldWithTopBar +import app.myzel394.numberhub.core.ui.common.SegmentedButton +import app.myzel394.numberhub.core.ui.common.SegmentedButtonsRow +import app.myzel394.numberhub.core.ui.common.textfield.ExpressionTransformer +import app.myzel394.numberhub.core.ui.openLink +import app.myzel394.numberhub.data.common.isEqualTo +import app.myzel394.numberhub.feature.bodymass.components.BodyMassResult +import app.myzel394.numberhub.feature.bodymass.components.BodyMassTextField import java.math.BigDecimal @Composable internal fun BodyMassRoute( openDrawer: () -> Unit, - navigateToSettings: () -> Unit, - viewModel: BodyMassViewModel = hiltViewModel() + viewModel: BodyMassViewModel = hiltViewModel(), ) { when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { UIState.Loading -> EmptyScreen() @@ -79,7 +78,6 @@ internal fun BodyMassRoute( updateWeight = viewModel::updateWeight, updateIsMetric = viewModel::updateIsMetric, openDrawer = openDrawer, - navigateToSettings = navigateToSettings ) } } @@ -92,7 +90,6 @@ private fun BodyMassScreen( updateWeight: (TextFieldValue) -> Unit, updateIsMetric: (Boolean) -> Unit, openDrawer: () -> Unit, - navigateToSettings: () -> Unit, ) { val mContext = LocalContext.current val expressionTransformer = remember(uiState.formatterSymbols) { @@ -100,14 +97,13 @@ private fun BodyMassScreen( } val weightShortLabel = remember(uiState.isMetric) { mContext.resources.getString( - if (uiState.isMetric) R.string.unit_kilogram_short else R.string.unit_pound_short + if (uiState.isMetric) R.string.unit_kilogram_short else R.string.unit_pound_short, ) } ScaffoldWithTopBar( title = { Text(stringResource(R.string.body_mass_title)) }, - navigationIcon = { MenuButton(openDrawer) }, - actions = { SettingsButton(navigateToSettings) } + navigationIcon = { DrawerButton(openDrawer) }, ) { paddingValues -> Column( modifier = Modifier @@ -116,22 +112,22 @@ private fun BodyMassScreen( .padding(16.dp) .fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { SegmentedButtonsRow( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { SegmentedButton( label = stringResource(R.string.body_mass_metric), onClick = { updateIsMetric(true) }, selected = uiState.isMetric, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) SegmentedButton( label = stringResource(R.string.body_mass_imperial), onClick = { updateIsMetric(false) }, selected = !uiState.isMetric, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(1f), ) } @@ -140,14 +136,14 @@ private fun BodyMassScreen( .fillMaxWidth() .background( MaterialTheme.colorScheme.secondaryContainer, - RoundedCornerShape(32.dp) + RoundedCornerShape(32.dp), ) .padding(16.dp, 24.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), ) { Crossfade( targetState = uiState.isMetric, - label = "Measurement system change" + label = "Measurement system change", ) { isMetric -> if (isMetric) { BodyMassTextField( @@ -159,7 +155,7 @@ private fun BodyMassScreen( ) } else { Row( - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { BodyMassTextField( modifier = Modifier.weight(1f), @@ -184,7 +180,7 @@ private fun BodyMassScreen( onValueChange = updateWeight, label = "${stringResource(R.string.body_mass_weight)}, $weightShortLabel", expressionFormatter = expressionTransformer, - imeAction = ImeAction.Done + imeAction = ImeAction.Done, ) } @@ -194,7 +190,7 @@ private fun BodyMassScreen( transitionSpec = { (fadeIn() togetherWith fadeOut()) using SizeTransform(false) }, - label = "Body mass value visibility" + label = "Body mass value visibility", ) { targetState -> if (targetState.isEqualTo(BigDecimal.ZERO)) return@AnimatedContent @@ -202,14 +198,14 @@ private fun BodyMassScreen( value = targetState, range = uiState.normalWeightRange, rangeSuffix = weightShortLabel, - formatterSymbols = uiState.formatterSymbols + formatterSymbols = uiState.formatterSymbols, ) } ElevatedButton( onClick = { openLink(mContext, "https://sadellie.github.io/unitto/help#body-mass-index") - } + }, ) { Text(text = stringResource(R.string.time_zone_no_results_button)) // TODO Rename } @@ -228,13 +224,12 @@ fun PreviewBodyMassScreen() { weight = TextFieldValue(), normalWeightRange = BigDecimal(30) to BigDecimal(50), result = BigDecimal(18.5), - formatterSymbols = FormatterSymbols.Spaces + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), ), updateHeight1 = {}, updateHeight2 = {}, updateWeight = {}, updateIsMetric = {}, openDrawer = {}, - navigateToSettings = {} ) } diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassUtils.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassUtils.kt similarity index 95% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassUtils.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassUtils.kt index 22429dab..85dfb457 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassUtils.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassUtils.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass +package app.myzel394.numberhub.feature.bodymass -import com.sadellie.unitto.core.base.MAX_PRECISION +import app.myzel394.numberhub.core.base.MAX_PRECISION import java.math.BigDecimal import java.math.RoundingMode @@ -51,7 +51,7 @@ internal fun calculateMetric( internal fun calculateImperial( heightFt: BigDecimal, heightIn: BigDecimal, - weightLbs: BigDecimal + weightLbs: BigDecimal, ): BigDecimal { val heightInches = heightFt .multiply(footToInchFactor) @@ -69,7 +69,7 @@ internal fun calculateImperial( * @return [Pair] of [BigDecimal]. First value is lowest weight. Second value is highest value. */ internal fun calculateNormalWeightMetric( - heightCm: BigDecimal + heightCm: BigDecimal, ): Pair { val heightMetres2 = heightCm .divide(cmToMFactor, MAX_PRECISION, RoundingMode.HALF_EVEN) diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassViewModel.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassViewModel.kt similarity index 57% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassViewModel.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassViewModel.kt index a0a9e93d..1d253282 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/BodyMassViewModel.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/BodyMassViewModel.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass +package app.myzel394.numberhub.feature.bodymass import android.icu.util.LocaleData import android.icu.util.ULocale @@ -24,10 +24,9 @@ import android.os.Build import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.data.common.combine -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.common.combine +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -39,23 +38,23 @@ import javax.inject.Inject @HiltViewModel internal class BodyMassViewModel @Inject constructor( - userPreferencesRepository: UserPreferencesRepository -): ViewModel() { - private val _isMetric = MutableStateFlow(getInitialIsMetric()) - private val _height1 = MutableStateFlow(TextFieldValue()) - private val _height2 = MutableStateFlow(TextFieldValue()) - private val _weight = MutableStateFlow(TextFieldValue()) - private val _result = MutableStateFlow(BigDecimal.ZERO) - private val _normalWeightRange = MutableStateFlow>(BigDecimal.ZERO to BigDecimal.ZERO) + userPreferencesRepository: UserPreferencesRepository, +) : ViewModel() { + private val isMetric = MutableStateFlow(getInitialIsMetric()) + private val height1 = MutableStateFlow(TextFieldValue()) + private val height2 = MutableStateFlow(TextFieldValue()) + private val weight = MutableStateFlow(TextFieldValue()) + private val result = MutableStateFlow(BigDecimal.ZERO) + private val normalWeightRange = MutableStateFlow>(BigDecimal.ZERO to BigDecimal.ZERO) val uiState = combine( userPreferencesRepository.bodyMassPrefs, - _isMetric, - _height1, - _height2, - _weight, - _result, - _normalWeightRange + isMetric, + height1, + height2, + weight, + result, + normalWeightRange, ) { userPrefs, isMetric, height1, height2, weight, result, normalWeightRange -> UIState.Ready( isMetric = isMetric, @@ -64,7 +63,7 @@ internal class BodyMassViewModel @Inject constructor( weight = weight, result = result, normalWeightRange = normalWeightRange, - formatterSymbols = AllFormatterSymbols.getById(userPrefs.separator) + formatterSymbols = userPrefs.formatterSymbols, ) } .mapLatest { ui -> @@ -74,17 +73,17 @@ internal class BodyMassViewModel @Inject constructor( val weight = BigDecimal(ui.weight.text.ifEmpty { "0" }) if (ui.isMetric) { - _result.update { calculateMetric(height1, weight) } - _normalWeightRange.update { calculateNormalWeightMetric(height1) } + result.update { calculateMetric(height1, weight) } + normalWeightRange.update { calculateNormalWeightMetric(height1) } } else { val height2 = BigDecimal(ui.height2.text.ifEmpty { "0" }) - _result.update { calculateImperial(height1, height2, weight) } - _normalWeightRange.update { calculateNormalWeightImperial(height1, height2) } + result.update { calculateImperial(height1, height2, weight) } + normalWeightRange.update { calculateNormalWeightImperial(height1, height2) } } } catch (e: Exception) { - _result.update { BigDecimal.ZERO } - _normalWeightRange.update { BigDecimal.ZERO to BigDecimal.ZERO } + result.update { BigDecimal.ZERO } + normalWeightRange.update { BigDecimal.ZERO to BigDecimal.ZERO } } } @@ -92,10 +91,10 @@ internal class BodyMassViewModel @Inject constructor( } .stateIn(viewModelScope, UIState.Loading) - fun updateHeight1(textFieldValue: TextFieldValue) = _height1.update { textFieldValue } - fun updateHeight2(textFieldValue: TextFieldValue) = _height2.update { textFieldValue } - fun updateWeight(textFieldValue: TextFieldValue) = _weight.update { textFieldValue } - fun updateIsMetric(isMetric: Boolean) = _isMetric.update { isMetric } + fun updateHeight1(textFieldValue: TextFieldValue) = height1.update { textFieldValue } + fun updateHeight2(textFieldValue: TextFieldValue) = height2.update { textFieldValue } + fun updateWeight(textFieldValue: TextFieldValue) = weight.update { textFieldValue } + fun updateIsMetric(isMetric: Boolean) = this.isMetric.update { isMetric } private fun getInitialIsMetric(): Boolean { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return true diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/UIState.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/UIState.kt similarity index 91% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/UIState.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/UIState.kt index 997c9339..f4ad22a2 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/UIState.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/UIState.kt @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass +package app.myzel394.numberhub.feature.bodymass import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.FormatterSymbols import java.math.BigDecimal internal sealed class UIState { diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/components/BodyMassResult.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/components/BodyMassResult.kt similarity index 84% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/components/BodyMassResult.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/components/BodyMassResult.kt index fbdba599..bed7a454 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/components/BodyMassResult.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/components/BodyMassResult.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass.components +package app.myzel394.numberhub.feature.bodymass.components import androidx.annotation.StringRes import androidx.compose.foundation.background @@ -37,11 +37,12 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.data.common.format +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.data.common.format import java.math.BigDecimal @Composable @@ -76,7 +77,7 @@ internal fun BodyMassResult( Column( modifier = modifier, - verticalArrangement = Arrangement.spacedBy(16.dp) + verticalArrangement = Arrangement.spacedBy(16.dp), ) { Column( modifier = Modifier @@ -88,12 +89,12 @@ internal fun BodyMassResult( Text( text = stringResource(classification.classification), style = MaterialTheme.typography.displaySmall, - color = MaterialTheme.colorScheme.onSecondaryContainer + color = MaterialTheme.colorScheme.onSecondaryContainer, ) Text( text = formattedValue, style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSecondaryContainer + color = MaterialTheme.colorScheme.onSecondaryContainer, ) } @@ -107,12 +108,12 @@ internal fun BodyMassResult( Text( text = formattedRange, style = MaterialTheme.typography.displaySmall, - color = MaterialTheme.colorScheme.onSecondaryContainer + color = MaterialTheme.colorScheme.onSecondaryContainer, ) Text( text = stringResource(R.string.body_mass_normal_weight), style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSecondaryContainer + color = MaterialTheme.colorScheme.onSecondaryContainer, ) } } @@ -122,7 +123,7 @@ internal fun BodyMassResult( private data class BodyMassData( val minValue: BigDecimal, val color: Color, - @StringRes val classification: Int + @StringRes val classification: Int, ) @Stable @@ -134,32 +135,32 @@ private val indexes by lazy { BodyMassData( minValue = BigDecimal("40"), color = Color(0x80FF2323), - classification = R.string.body_mass_obese_3 + classification = R.string.body_mass_obese_3, ), BodyMassData( minValue = BigDecimal("35"), color = Color(0x80F85F31), - classification = R.string.body_mass_obese_2 + classification = R.string.body_mass_obese_2, ), BodyMassData( minValue = BigDecimal("30"), color = Color(0x80FF9634), - classification = R.string.body_mass_obese_1 + classification = R.string.body_mass_obese_1, ), BodyMassData( minValue = BigDecimal("25"), color = Color(0x80DBEC18), - classification = R.string.body_mass_overweight + classification = R.string.body_mass_overweight, ), BodyMassData( minValue = BigDecimal("18.5"), color = Color(0x805BF724), - classification = R.string.body_mass_normal + classification = R.string.body_mass_normal, ), BodyMassData( minValue = BigDecimal("0"), color = Color(0x800EACDD), - classification = R.string.body_mass_underweight + classification = R.string.body_mass_underweight, ), ) } @@ -171,6 +172,6 @@ fun PreviewBodyMassResult() { value = BigDecimal(18.5), range = BigDecimal(50) to BigDecimal(80), rangeSuffix = "kg", - formatterSymbols = FormatterSymbols.Spaces, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), ) } diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/components/BodyMassTextField.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/components/BodyMassTextField.kt similarity index 89% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/components/BodyMassTextField.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/components/BodyMassTextField.kt index fb660bd1..a7f00179 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/components/BodyMassTextField.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/components/BodyMassTextField.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass.components +package app.myzel394.numberhub.feature.bodymass.components import androidx.compose.animation.AnimatedContent import androidx.compose.material3.MaterialTheme @@ -27,8 +27,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.VisualTransformation -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.OutlinedDecimalTextField +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.OutlinedDecimalTextField @Composable internal fun BodyMassTextField( @@ -37,7 +37,7 @@ internal fun BodyMassTextField( label: String, onValueChange: (TextFieldValue) -> Unit, expressionFormatter: VisualTransformation, - imeAction: ImeAction = ImeAction.Next + imeAction: ImeAction = ImeAction.Next, ) { OutlinedDecimalTextField( modifier = modifier, @@ -57,6 +57,6 @@ internal fun BodyMassTextField( unfocusedTextColor = MaterialTheme.colorScheme.onSecondaryContainer, ), expressionFormatter = expressionFormatter, - imeAction = imeAction + imeAction = imeAction, ) } diff --git a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/navigation/Navigation.kt b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/navigation/Navigation.kt similarity index 73% rename from feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/navigation/Navigation.kt rename to feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/navigation/Navigation.kt index e0496054..0b7d0e42 100644 --- a/feature/bodymass/src/main/java/com/sadellie/unitto/feature/bodymass/navigation/Navigation.kt +++ b/feature/bodymass/src/main/java/app/myzel394/numberhub/feature/bodymass/navigation/Navigation.kt @@ -16,33 +16,31 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass.navigation +package app.myzel394.numberhub.feature.bodymass.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.navDeepLink -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.unittoComposable -import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.feature.bodymass.BodyMassRoute +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.unittoComposable +import app.myzel394.numberhub.core.ui.unittoNavigation +import app.myzel394.numberhub.feature.bodymass.BodyMassRoute private val graph = DrawerItem.BodyMass.graph private val start = DrawerItem.BodyMass.start fun NavGraphBuilder.bodyMassGraph( openDrawer: () -> Unit, - navigateToSettings: () -> Unit ) { unittoNavigation( startDestination = start, route = graph, deepLinks = listOf( - navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" } - ) + navDeepLink { uriPattern = "app://app.myzel394.numberhub/$graph" }, + ), ) { unittoComposable(start) { BodyMassRoute( openDrawer = openDrawer, - navigateToSettings = navigateToSettings ) } } diff --git a/feature/bodymass/src/test/java/com/sadellie/unitto/feature/bodymass/BodyMassTest.kt b/feature/bodymass/src/test/java/app/myzel394/numberhub/feature/bodymass/BodyMassTest.kt similarity index 98% rename from feature/bodymass/src/test/java/com/sadellie/unitto/feature/bodymass/BodyMassTest.kt rename to feature/bodymass/src/test/java/app/myzel394/numberhub/feature/bodymass/BodyMassTest.kt index bd35fae0..84ff1fce 100644 --- a/feature/bodymass/src/test/java/com/sadellie/unitto/feature/bodymass/BodyMassTest.kt +++ b/feature/bodymass/src/test/java/app/myzel394/numberhub/feature/bodymass/BodyMassTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.bodymass +package app.myzel394.numberhub.feature.bodymass import org.junit.Assert.assertEquals import org.junit.Test diff --git a/feature/calculator/build.gradle.kts b/feature/calculator/build.gradle.kts index 6fa0b2f3..fa8e10e6 100644 --- a/feature/calculator/build.gradle.kts +++ b/feature/calculator/build.gradle.kts @@ -24,17 +24,13 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.calculator" +android.namespace = "app.myzel394.numberhub.feature.calculator" android.testOptions.unitTests.isIncludeAndroidResources = true dependencies { testImplementation(libs.org.robolectric.robolectric) testImplementation(libs.org.jetbrains.kotlinx.kotlinx.coroutines.test) - implementation(libs.androidx.glance.glance) - implementation(libs.androidx.glance.glance.appwidget) - implementation(libs.androidx.glance.glance.material3) - implementation(project(":data:calculator")) implementation(project(":data:common")) implementation(project(":data:database")) diff --git a/feature/calculator/src/androidTest/java/com/sadellie/unitto/feature/calculator/CalculatorScreenTest.kt b/feature/calculator/src/androidTest/java/app/myzel394/numberhub/feature/calculator/CalculatorScreenTest.kt similarity index 57% rename from feature/calculator/src/androidTest/java/com/sadellie/unitto/feature/calculator/CalculatorScreenTest.kt rename to feature/calculator/src/androidTest/java/app/myzel394/numberhub/feature/calculator/CalculatorScreenTest.kt index 653c3253..f0403068 100644 --- a/feature/calculator/src/androidTest/java/com/sadellie/unitto/feature/calculator/CalculatorScreenTest.kt +++ b/feature/calculator/src/androidTest/java/app/myzel394/numberhub/feature/calculator/CalculatorScreenTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.feature.calculator import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.createAndroidComposeRule @@ -26,9 +26,10 @@ import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput import androidx.compose.ui.test.swipeDown import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token import org.junit.Rule import org.junit.Test @@ -37,53 +38,35 @@ class CalculatorScreenTest { val composeTestRule = createAndroidComposeRule() @Test - fun loading_showLoadingKeyboard(): Unit = with(composeTestRule) { + fun ready(): Unit = with(composeTestRule) { setContent { - CalculatorScreen( - uiState = CalculatorUIState.Loading, - navigateToMenu = {}, - navigateToSettings = {}, - addTokens = {}, - clearInput = {}, - deleteTokens = {}, - onCursorChange = {}, - toggleCalculatorMode = {}, - equal = {}, - clearHistory = {}, - addBracket = {} - ) - } - - onNodeWithTag("loading").assertExists() - } - - @Test - fun ready_showRealKeyboard(): Unit = with(composeTestRule) { - setContent { - CalculatorScreen( + Ready( uiState = CalculatorUIState.Ready( input = TextFieldValue(), output = CalculationResult.Empty, radianMode = false, precision = 3, outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), history = emptyList(), - allowVibration = false, middleZero = false, acButton = true, - partialHistoryView = true + additionalButtons = false, + inverseMode = false, + partialHistoryView = true, ), - navigateToMenu = {}, - navigateToSettings = {}, - addTokens = {}, - clearInput = {}, - deleteTokens = {}, - onCursorChange = {}, - toggleCalculatorMode = {}, - equal = {}, - clearHistory = {}, - addBracket = {} + openDrawer = {}, + onInputChange = {}, + onAddTokenClick = {}, + onBracketsClick = {}, + onDeleteClick = {}, + onClearClick = {}, + onEqualClick = {}, + onRadianModeClick = {}, + onAdditionalButtonsClick = {}, + onInverseModeClick = {}, + onClearHistoryClick = {}, + onDeleteHistoryItemClick = {}, ) } @@ -94,30 +77,33 @@ class CalculatorScreenTest { @Test fun ready_swipeForHistory(): Unit = with(composeTestRule) { setContent { - CalculatorScreen( + Ready( uiState = CalculatorUIState.Ready( input = TextFieldValue(), output = CalculationResult.Empty, radianMode = false, precision = 3, outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), history = emptyList(), - allowVibration = false, middleZero = false, acButton = true, - partialHistoryView = true + additionalButtons = false, + inverseMode = false, + partialHistoryView = true, ), - navigateToMenu = {}, - navigateToSettings = {}, - addTokens = {}, - clearInput = {}, - deleteTokens = {}, - onCursorChange = {}, - toggleCalculatorMode = {}, - equal = {}, - clearHistory = {}, - addBracket = {} + openDrawer = {}, + onInputChange = {}, + onAddTokenClick = {}, + onBracketsClick = {}, + onDeleteClick = {}, + onClearClick = {}, + onEqualClick = {}, + onRadianModeClick = {}, + onAdditionalButtonsClick = {}, + onInverseModeClick = {}, + onClearHistoryClick = {}, + onDeleteHistoryItemClick = {}, ) } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorScreen.kt similarity index 63% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorScreen.kt index a852154e..2824d554 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorScreen.kt @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.feature.calculator import androidx.activity.compose.BackHandler -import androidx.compose.animation.Crossfade +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.gestures.AnchoredDraggableState @@ -56,27 +56,26 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag -import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.MenuButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar -import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.data.model.HistoryItem -import com.sadellie.unitto.feature.calculator.components.CalculatorKeyboard -import com.sadellie.unitto.feature.calculator.components.HistoryItemHeight -import com.sadellie.unitto.feature.calculator.components.HistoryList -import com.sadellie.unitto.feature.calculator.components.TextBox +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowHeightSizeClass +import app.myzel394.numberhub.core.ui.common.DrawerButton +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ScaffoldWithTopBar +import app.myzel394.numberhub.data.model.HistoryItem +import app.myzel394.numberhub.feature.calculator.components.CalculatorKeyboard +import app.myzel394.numberhub.feature.calculator.components.HistoryItemHeight +import app.myzel394.numberhub.feature.calculator.components.HistoryList +import app.myzel394.numberhub.feature.calculator.components.TextBox import kotlinx.coroutines.launch import java.text.SimpleDateFormat import java.util.Locale @@ -84,99 +83,75 @@ import kotlin.math.roundToInt @Composable internal fun CalculatorRoute( - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, - viewModel: CalculatorViewModel = hiltViewModel() + openDrawer: () -> Unit, + viewModel: CalculatorViewModel = hiltViewModel(), ) { - val uiState = viewModel.uiState.collectAsStateWithLifecycle() - - CalculatorScreen( - uiState = uiState.value, - navigateToMenu = navigateToMenu, - navigateToSettings = navigateToSettings, - addTokens = viewModel::addTokens, - clearInput = viewModel::clearInput, - deleteTokens = viewModel::deleteTokens, - onCursorChange = viewModel::onCursorChange, - toggleCalculatorMode = viewModel::updateRadianMode, - equal = viewModel::equal, - clearHistory = viewModel::clearHistory, - addBracket = viewModel::addBracket - ) -} - -@Composable -internal fun CalculatorScreen( - uiState: CalculatorUIState, - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, - addTokens: (String) -> Unit, - addBracket: () -> Unit, - clearInput: () -> Unit, - deleteTokens: () -> Unit, - onCursorChange: (TextRange) -> Unit, - toggleCalculatorMode: (Boolean) -> Unit, - equal: () -> Unit, - clearHistory: () -> Unit -) { - when (uiState) { - is CalculatorUIState.Loading -> EmptyScreen() + when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { + CalculatorUIState.Loading -> EmptyScreen() is CalculatorUIState.Ready -> Ready( uiState = uiState, - navigateToMenu = navigateToMenu, - navigateToSettings = navigateToSettings, - addSymbol = addTokens, - clearSymbols = clearInput, - deleteSymbol = deleteTokens, - onCursorChange = onCursorChange, - toggleAngleMode = { toggleCalculatorMode(!uiState.radianMode) }, - equal = equal, - clearHistory = clearHistory, - addBracket = addBracket + openDrawer = openDrawer, + onInputChange = viewModel::updateInput, + onAddTokenClick = viewModel::addTokens, + onBracketsClick = viewModel::addBracket, + onDeleteClick = viewModel::deleteTokens, + onClearClick = viewModel::clearInput, + onEqualClick = viewModel::equal, + onRadianModeClick = viewModel::updateRadianMode, + onAdditionalButtonsClick = viewModel::updateAdditionalButtons, + onInverseModeClick = viewModel::updateInverseMode, + onClearHistoryClick = viewModel::clearHistory, + onDeleteHistoryItemClick = viewModel::deleteHistoryItem, ) } } @Composable -private fun Ready( +internal fun Ready( uiState: CalculatorUIState.Ready, - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, - addSymbol: (String) -> Unit, - addBracket: () -> Unit, - clearSymbols: () -> Unit, - deleteSymbol: () -> Unit, - onCursorChange: (TextRange) -> Unit, - toggleAngleMode: () -> Unit, - equal: () -> Unit, - clearHistory: () -> Unit + openDrawer: () -> Unit, + onInputChange: (TextFieldValue) -> Unit, + onAddTokenClick: (String) -> Unit, + onBracketsClick: () -> Unit, + onDeleteClick: () -> Unit, + onClearClick: () -> Unit, + onEqualClick: () -> Unit, + onRadianModeClick: (Boolean) -> Unit, + onAdditionalButtonsClick: (Boolean) -> Unit, + onInverseModeClick: (Boolean) -> Unit, + onClearHistoryClick: () -> Unit, + onDeleteHistoryItemClick: (HistoryItem) -> Unit, ) { val focusManager = LocalFocusManager.current var showClearHistoryDialog by rememberSaveable { mutableStateOf(false) } - var showClearHistoryButton by rememberSaveable { mutableStateOf(false) } + val dragState = remember { + AnchoredDraggableState( + initialValue = DragState.CLOSED, + positionalThreshold = { 0f }, + velocityThreshold = { 0f }, + animationSpec = tween(), + ) + } + val isOpen = dragState.currentValue == DragState.OPEN ScaffoldWithTopBar( - title = { Text(stringResource(R.string.calculator_title)) }, - navigationIcon = { MenuButton { navigateToMenu() } }, + title = {}, + navigationIcon = { DrawerButton { openDrawer() } }, colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceVariant), actions = { - Crossfade(showClearHistoryButton, label = "Clear button reveal") { - if (it) { - IconButton( - onClick = { showClearHistoryDialog = true }, - content = { - Icon( - Icons.Default.Delete, - stringResource(R.string.clear_history_label) - ) - }, - modifier = Modifier.semantics { testTag = "historyButton" } - ) - } else { - SettingsButton(navigateToSettings) - } + AnimatedVisibility(isOpen, label = "Clear button reveal") { + IconButton( + onClick = { showClearHistoryDialog = true }, + content = { + Icon( + Icons.Default.Delete, + stringResource(R.string.clear_history_label), + ) + }, + modifier = Modifier.semantics { testTag = "historyButton" }, + ) } - } + }, ) { paddingValues -> BoxWithConstraints( modifier = Modifier.padding(paddingValues), @@ -187,15 +162,6 @@ private fun Ready( val textBoxHeight = maxHeight * textBoxFill - val dragState = remember { - AnchoredDraggableState( - initialValue = DragState.CLOSED, - positionalThreshold = { 0f }, - velocityThreshold = { 0f }, - animationSpec = tween() - ) - } - var historyListHeight by remember { mutableStateOf(0.dp) } val keyboardHeight by remember(historyListHeight, textBoxHeight) { derivedStateOf { @@ -234,10 +200,6 @@ private fun Ready( focusManager.clearFocus() } - LaunchedEffect(dragState.currentValue) { - showClearHistoryButton = dragState.currentValue == DragState.OPEN - } - BackHandler(dragState.currentValue != DragState.CLOSED) { coroutineScope.launch { dragState.animateTo(DragState.CLOSED) @@ -251,7 +213,9 @@ private fun Ready( .height(historyListHeight), historyItems = uiState.history, formatterSymbols = uiState.formatterSymbols, - addTokens = addSymbol + addTokens = onAddTokenClick, + onDelete = onDeleteHistoryItemClick, + showDeleteButtons = isOpen, ) TextBox( @@ -261,33 +225,45 @@ private fun Ready( .fillMaxWidth() .anchoredDraggable( state = dragState, - orientation = Orientation.Vertical + orientation = Orientation.Vertical, ), formatterSymbols = uiState.formatterSymbols, input = uiState.input, - deleteSymbol = deleteSymbol, - addSymbol = addSymbol, - onCursorChange = onCursorChange, - output = uiState.output + onValueChange = onInputChange, + output = uiState.output, ) CalculatorKeyboard( modifier = Modifier .semantics { testTag = "ready" } - .offset { IntOffset(x = 0, y = (historyListHeight + textBoxHeight).toPx().roundToInt()) } + .offset { + IntOffset( + x = 0, + y = (historyListHeight + textBoxHeight) + .toPx() + .roundToInt(), + ) + } .height(keyboardHeight) .fillMaxWidth() .padding(horizontal = 8.dp, vertical = 4.dp), + onAddTokenClick = onAddTokenClick, + onBracketsClick = onBracketsClick, + onDeleteClick = onDeleteClick, + onClearClick = onClearClick, + onEqualClick = { + focusManager.clearFocus() + onEqualClick() + }, radianMode = uiState.radianMode, - fractional = uiState.formatterSymbols.fractional, - addSymbol = addSymbol, - clearSymbols = clearSymbols, - deleteSymbol = deleteSymbol, - toggleAngleMode = toggleAngleMode, - equal = { focusManager.clearFocus(); equal() }, + onRadianModeClick = onRadianModeClick, + additionalButtons = uiState.additionalButtons, + onAdditionalButtonsClick = onAdditionalButtonsClick, + inverseMode = uiState.inverseMode, + onInverseModeClick = onInverseModeClick, + showAcButton = uiState.acButton, middleZero = uiState.middleZero, - acButton = uiState.acButton, - addBracket = addBracket + fractional = uiState.formatterSymbols.fractional, ) } } @@ -306,21 +282,21 @@ private fun Ready( confirmButton = { TextButton( onClick = { - clearHistory() + onClearHistoryClick() showClearHistoryDialog = false - } + }, ) { Text(stringResource(R.string.clear_label)) } }, dismissButton = { TextButton( - onClick = { showClearHistoryDialog = false } + onClick = { showClearHistoryDialog = false }, ) { Text(stringResource(R.string.cancel_label)) } }, - onDismissRequest = { showClearHistoryDialog = false } + onDismissRequest = { showClearHistoryDialog = false }, ) } } @@ -349,32 +325,36 @@ private fun PreviewCalculatorScreen() { id = it.hashCode(), date = dtf.parse(it)!!, expression = "12345".repeat(10), - result = "1234" + result = "1234", ) } - CalculatorScreen( + Ready( uiState = CalculatorUIState.Ready( input = TextFieldValue("1.2345"), - output = CalculationResult.Default("1234"), + output = CalculationResult.Success("1234"), radianMode = false, precision = 3, outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), history = historyItems, middleZero = false, acButton = true, - partialHistoryView = true + additionalButtons = false, + inverseMode = false, + partialHistoryView = true, ), - navigateToMenu = {}, - navigateToSettings = {}, - addTokens = {}, - clearInput = {}, - deleteTokens = {}, - onCursorChange = {}, - toggleCalculatorMode = {}, - equal = {}, - clearHistory = {}, - addBracket = {} + openDrawer = {}, + onInputChange = {}, + onAddTokenClick = {}, + onBracketsClick = {}, + onDeleteClick = {}, + onClearClick = {}, + onEqualClick = {}, + onRadianModeClick = {}, + onAdditionalButtonsClick = {}, + onInverseModeClick = {}, + onClearHistoryClick = {}, + onDeleteHistoryItemClick = {}, ) -} \ No newline at end of file +} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorUIState.kt similarity index 68% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorUIState.kt index baa5b4c6..7b028862 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorUIState.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorUIState.kt @@ -16,13 +16,11 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.feature.calculator -import androidx.annotation.StringRes import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.data.model.HistoryItem +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.data.model.HistoryItem internal sealed class CalculatorUIState { data object Loading : CalculatorUIState() @@ -37,24 +35,18 @@ internal sealed class CalculatorUIState { val history: List, val middleZero: Boolean, val acButton: Boolean, + val additionalButtons: Boolean, + val inverseMode: Boolean, val partialHistoryView: Boolean, ) : CalculatorUIState() } sealed class CalculationResult { - data class Default(val text: String) : CalculationResult() - - data class Fraction(val text: String) : CalculationResult() + data class Success(val text: String) : CalculationResult() data object Empty : CalculationResult() - data object DivideByZeroError : CalculationResult() { - @StringRes - val label: Int = R.string.calculator_divide_by_zero_error - } + data object DivideByZeroError : CalculationResult() - data object Error : CalculationResult() { - @StringRes - val label: Int = R.string.error_label - } + data object Error : CalculationResult() } diff --git a/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorViewModel.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorViewModel.kt new file mode 100644 index 00000000..2644cdd8 --- /dev/null +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/CalculatorViewModel.kt @@ -0,0 +1,231 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.calculator + +import androidx.compose.ui.text.input.TextFieldValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.addBracket +import app.myzel394.numberhub.core.ui.common.textfield.addTokens +import app.myzel394.numberhub.core.ui.common.textfield.deleteTokens +import app.myzel394.numberhub.core.ui.common.textfield.getTextField +import app.myzel394.numberhub.core.ui.common.textfield.placeCursorAtTheEnd +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.data.common.isExpression +import app.myzel394.numberhub.data.common.isGreaterThan +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.HistoryItem +import app.myzel394.numberhub.data.model.repository.CalculatorHistoryRepository +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import io.github.sadellie.evaluatto.Expression +import io.github.sadellie.evaluatto.ExpressionException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.math.BigDecimal +import java.math.RoundingMode +import javax.inject.Inject + +@HiltViewModel +internal class CalculatorViewModel @Inject constructor( + private val userPrefsRepository: UserPreferencesRepository, + private val calculatorHistoryRepository: CalculatorHistoryRepository, + private val savedStateHandle: SavedStateHandle, +) : ViewModel() { + private var calculationJob: Job? = null + + private val inputKey = "CALCULATOR_INPUT" + private val input = MutableStateFlow(savedStateHandle.getTextField(inputKey)) + private val result = MutableStateFlow(CalculationResult.Empty) + private val equalClicked = MutableStateFlow(false) + private val prefs = userPrefsRepository.calculatorPrefs.stateIn(viewModelScope, null) + + val uiState: StateFlow = combine( + input, + result, + prefs, + calculatorHistoryRepository.historyFlow, + ) { input, result, prefs, history -> + prefs ?: return@combine CalculatorUIState.Loading + + return@combine CalculatorUIState.Ready( + input = input, + output = result, + radianMode = prefs.radianMode, + precision = prefs.precision, + outputFormat = prefs.outputFormat, + formatterSymbols = prefs.formatterSymbols, + history = history, + middleZero = prefs.middleZero, + acButton = prefs.acButton, + additionalButtons = prefs.additionalButtons, + inverseMode = prefs.inverseMode, + partialHistoryView = prefs.partialHistoryView, + ) + } + .stateIn(viewModelScope, CalculatorUIState.Loading) + + fun addTokens(tokens: String) { + val isClearInputNeeded = equalClicked.value and Token.Digit.allWithDot.contains(tokens) + val newValue = when { + // Clean input after clicking "=" and any token that is a Digit + isClearInputNeeded -> TextFieldValue() + equalClicked.value -> input.value.placeCursorAtTheEnd() + else -> input.value + }.addTokens(tokens) + updateInput(newValue) + } + + fun addBracket() { + val newValue = if (equalClicked.value) { + // Cursor is set to 0 when equal is clicked + input.value.placeCursorAtTheEnd() + } else { + input.value + }.addBracket() + updateInput(newValue) + } + + fun deleteTokens() { + val newValue = if (equalClicked.value) { + TextFieldValue() + } else { + input.value.deleteTokens() + } + updateInput(newValue) + } + + fun clearInput() = updateInput(TextFieldValue()) + + fun updateInput(value: TextFieldValue) { + equalClicked.update { false } + input.update { value } + savedStateHandle[inputKey] = value.text + calculateInput() + } + + fun updateRadianMode(newValue: Boolean) = viewModelScope.launch { + userPrefsRepository.updateRadianMode(newValue) + calculateInput() + } + + fun updateAdditionalButtons(newValue: Boolean) = viewModelScope.launch { + userPrefsRepository.updateAdditionalButtons(newValue) + } + + fun updateInverseMode(newValue: Boolean) = viewModelScope.launch { + userPrefsRepository.updateInverseMode(newValue) + } + + fun clearHistory() = viewModelScope.launch { + calculatorHistoryRepository.clear() + } + + fun deleteHistoryItem(item: HistoryItem) = viewModelScope.launch { + calculatorHistoryRepository.delete(item) + } + + fun equal() = viewModelScope.launch { + val prefs = prefs.value ?: return@launch + val inputValue = input.value.text + if (equalClicked.value) return@launch + if (!inputValue.isExpression()) return@launch + + val calculated = try { + calculate(inputValue, prefs.radianMode, RoundingMode.HALF_EVEN) + .format(prefs.precision, prefs.outputFormat) + } catch (e: ExpressionException.DivideByZero) { + result.update { CalculationResult.DivideByZeroError } + return@launch + } catch (e: Exception) { + result.update { CalculationResult.Error } + return@launch + } + + val fractional = try { + calculate(inputValue, prefs.radianMode, RoundingMode.DOWN) + .toFractionalString() + } catch (e: Exception) { + result.update { CalculationResult.Error } + return@launch + } + + calculatorHistoryRepository.add( + expression = inputValue, + result = calculated, + ) + + equalClicked.update { true } + input.update { TextFieldValue(calculated.replace("-", Token.Operator.minus)) } + result.update { CalculationResult.Success(fractional) } + } + + private fun calculateInput() { + calculationJob?.cancel() + calculationJob = viewModelScope.launch { + if (!input.value.text.isExpression()) { + result.update { CalculationResult.Empty } + return@launch + } + + val prefs = prefs.value ?: return@launch + val newResult = try { + val calculated = calculate( + input = input.value.text, + radianMode = prefs.radianMode, + roundingMode = RoundingMode.HALF_EVEN, + ) + CalculationResult.Success( + calculated.format(prefs.precision, prefs.outputFormat), + ) + } catch (e: Exception) { + CalculationResult.Empty + } + result.update { newResult } + } + } + + private suspend fun calculate( + input: String, + radianMode: Boolean, + roundingMode: RoundingMode = RoundingMode.HALF_EVEN, + ): BigDecimal = withContext(Dispatchers.Default) { + Expression(input, radianMode, roundingMode) + .calculate() + .also { + if (it.isGreaterThan(maxCalculationResult)) throw ExpressionException.TooBig() + } + } + + private val maxCalculationResult = BigDecimal.valueOf(Double.MAX_VALUE) + + override fun onCleared() { + viewModelScope.cancel() + super.onCleared() + } +} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DecimalToFraction.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/DecimalToFraction.kt similarity index 84% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DecimalToFraction.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/DecimalToFraction.kt index e2c15501..87a9d6bb 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DecimalToFraction.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/DecimalToFraction.kt @@ -16,10 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.feature.calculator -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.data.common.isEqualTo +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.data.common.isEqualTo +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import java.math.BigDecimal import java.math.BigInteger import java.math.RoundingMode @@ -36,13 +38,13 @@ import java.math.RoundingMode * @receiver [BigDecimal]. Scale doesn't matter, but should be `MAX_PRECISION` * @return */ -fun BigDecimal.toFractionalString(): String { +suspend fun BigDecimal.toFractionalString(): String = withContext(Dispatchers.Default) { // https://www.khanacademy.org/math/cc-eighth-grade-math/cc-8th-numbers-operations/cc-8th-repeating-decimals/v/coverting-repeating-decimals-to-fractions-1 // https://www.khanacademy.org/math/cc-eighth-grade-math/cc-8th-numbers-operations/cc-8th-repeating-decimals/v/coverting-repeating-decimals-to-fractions-2 - val (integral, fractional) = this.divideAndRemainder(BigDecimal.ONE) + val (integral, fractional) = this@toFractionalString.divideAndRemainder(BigDecimal.ONE) val integralBI = integral.toBigInteger() - if (fractional.isEqualTo(BigDecimal.ZERO)) return "" + if (fractional.isEqualTo(BigDecimal.ZERO)) return@withContext "" val res: String = if (integral.isEqualTo(BigDecimal.ZERO)) "" else "$integralBI " @@ -54,9 +56,9 @@ fun BigDecimal.toFractionalString(): String { fractional.repeatingFractional(repeatingDecimals.length) } - if (finalDenominator > maxDenominator) return "" + if (finalDenominator > maxDenominator) return@withContext "" - return "$res$finalNumerator⁄$finalDenominator" + return@withContext "$res$finalNumerator⁄$finalDenominator" } private fun BigDecimal.notRepeatingFractional(): Pair { @@ -73,7 +75,7 @@ private fun BigDecimal.notRepeatingFractional(): Pair { } private fun BigDecimal.repeatingFractional( - repeatingLength: Int + repeatingLength: Int, ): Pair { val multiplier = BigInteger.TEN.pow(repeatingLength) @@ -99,7 +101,7 @@ private fun BigDecimal.repeatingDecimals(): String? { repeat(inputString.length) { index -> val stringInFront = inputString.substring(index) - (1..stringInFront.length/2).forEach checkLoop@{ loop -> + (1..stringInFront.length / 2).forEach checkLoop@{ loop -> val pattern = stringInFront.take(loop) val checkRange = stringInFront.substring(0, stringInFront.length - stringInFront.length % pattern.length) val checkChunks = checkRange.chunked(pattern.length) diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DragState.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/DragState.kt similarity index 94% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DragState.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/DragState.kt index f2245a22..d5fedb34 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/DragState.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/DragState.kt @@ -16,6 +16,6 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.feature.calculator internal enum class DragState { CLOSED, SMALL, OPEN } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/CalculatorKeyboard.kt similarity index 51% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/CalculatorKeyboard.kt index be3ca4d7..674b23c3 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/CalculatorKeyboard.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/CalculatorKeyboard.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator.components +package app.myzel394.numberhub.feature.calculator.components import androidx.compose.animation.AnimatedContent import androidx.compose.animation.Crossfade @@ -44,121 +44,119 @@ import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.common.ColumnWithConstraints -import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightShort -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightShortAdditional -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTallAdditional -import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled -import com.sadellie.unitto.core.ui.common.KeyboardButtonLight -import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary -import com.sadellie.unitto.core.ui.common.KeypadFlow -import com.sadellie.unitto.core.ui.common.icons.IconPack -import com.sadellie.unitto.core.ui.common.icons.iconpack.AcTan -import com.sadellie.unitto.core.ui.common.icons.iconpack.ArCos -import com.sadellie.unitto.core.ui.common.icons.iconpack.ArSin -import com.sadellie.unitto.core.ui.common.icons.iconpack.Backspace -import com.sadellie.unitto.core.ui.common.icons.iconpack.Brackets -import com.sadellie.unitto.core.ui.common.icons.iconpack.Clear -import com.sadellie.unitto.core.ui.common.icons.iconpack.Comma -import com.sadellie.unitto.core.ui.common.icons.iconpack.Cos -import com.sadellie.unitto.core.ui.common.icons.iconpack.Deg -import com.sadellie.unitto.core.ui.common.icons.iconpack.Divide -import com.sadellie.unitto.core.ui.common.icons.iconpack.Dot -import com.sadellie.unitto.core.ui.common.icons.iconpack.Equal -import com.sadellie.unitto.core.ui.common.icons.iconpack.Euler -import com.sadellie.unitto.core.ui.common.icons.iconpack.Ex -import com.sadellie.unitto.core.ui.common.icons.iconpack.Factorial -import com.sadellie.unitto.core.ui.common.icons.iconpack.Inv -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key0 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key1 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key2 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key3 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key4 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key5 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key6 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key7 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key8 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key9 -import com.sadellie.unitto.core.ui.common.icons.iconpack.LeftBracket -import com.sadellie.unitto.core.ui.common.icons.iconpack.Ln -import com.sadellie.unitto.core.ui.common.icons.iconpack.Log -import com.sadellie.unitto.core.ui.common.icons.iconpack.Minus -import com.sadellie.unitto.core.ui.common.icons.iconpack.Modulo -import com.sadellie.unitto.core.ui.common.icons.iconpack.Multiply -import com.sadellie.unitto.core.ui.common.icons.iconpack.Percent -import com.sadellie.unitto.core.ui.common.icons.iconpack.Pi -import com.sadellie.unitto.core.ui.common.icons.iconpack.Plus -import com.sadellie.unitto.core.ui.common.icons.iconpack.Power -import com.sadellie.unitto.core.ui.common.icons.iconpack.Power10 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Rad -import com.sadellie.unitto.core.ui.common.icons.iconpack.RightBracket -import com.sadellie.unitto.core.ui.common.icons.iconpack.Root -import com.sadellie.unitto.core.ui.common.icons.iconpack.Sin -import com.sadellie.unitto.core.ui.common.icons.iconpack.Tan -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowHeightSizeClass +import app.myzel394.numberhub.core.ui.common.ColumnWithConstraints +import app.myzel394.numberhub.core.ui.common.KeyboardButtonAdditional +import app.myzel394.numberhub.core.ui.common.KeyboardButtonFilled +import app.myzel394.numberhub.core.ui.common.KeyboardButtonLight +import app.myzel394.numberhub.core.ui.common.KeyboardButtonTertiary +import app.myzel394.numberhub.core.ui.common.KeyboardButtonToken +import app.myzel394.numberhub.core.ui.common.KeypadFlow +import app.myzel394.numberhub.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.iconpack.AcTan +import app.myzel394.numberhub.core.ui.common.icons.iconpack.ArCos +import app.myzel394.numberhub.core.ui.common.icons.iconpack.ArSin +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Backspace +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Brackets +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Clear +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Comma +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Cos +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Deg +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Divide +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Dot +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Equal +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Euler +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Ex +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Factorial +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Inv +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key0 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key1 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key2 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key3 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key4 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key5 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key6 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key7 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key8 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key9 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.LeftBracket +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Ln +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Log +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Minus +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Modulo +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Multiply +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Percent +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Pi +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Plus +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Power +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Power10 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Rad +import app.myzel394.numberhub.core.ui.common.icons.iconpack.RightBracket +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Root +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Sin +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Tan @Composable internal fun CalculatorKeyboard( modifier: Modifier, + onAddTokenClick: (String) -> Unit, + onBracketsClick: () -> Unit, + onDeleteClick: () -> Unit, + onClearClick: () -> Unit, + onEqualClick: () -> Unit, radianMode: Boolean, - fractional: String, + onRadianModeClick: (Boolean) -> Unit, + additionalButtons: Boolean, + onAdditionalButtonsClick: (Boolean) -> Unit, + inverseMode: Boolean, + onInverseModeClick: (Boolean) -> Unit, + showAcButton: Boolean, middleZero: Boolean, - acButton: Boolean, - addSymbol: (String) -> Unit, - addBracket: () -> Unit, - clearSymbols: () -> Unit, - deleteSymbol: () -> Unit, - toggleAngleMode: () -> Unit, - equal: () -> Unit + fractional: String, ) { - var invMode: Boolean by remember { mutableStateOf(false) } - if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) { LandscapeKeyboard( modifier = modifier, + onAddTokenClick = onAddTokenClick, + onBracketsClick = onBracketsClick, + onDeleteClick = onDeleteClick, + onClearClick = onClearClick, + onEqualClick = onEqualClick, radianMode = radianMode, - fractional = fractional, + onRadianModeClick = onRadianModeClick, + inverseMode = inverseMode, + onInverseModeClick = onInverseModeClick, + showAcButton = showAcButton, middleZero = middleZero, - addSymbol = addSymbol, - toggleAngleMode = toggleAngleMode, - deleteSymbol = deleteSymbol, - clearSymbols = clearSymbols, - equal = equal, - acButton = acButton, - addBracket = addBracket, - invMode = invMode, - toggleInvMode = { invMode = !invMode }, + fractional = fractional, ) } else { PortraitKeyboard( modifier = modifier, + onAddTokenClick = onAddTokenClick, + onBracketsClick = onBracketsClick, + onDeleteClick = onDeleteClick, + onClearClick = onClearClick, + onEqualClick = onEqualClick, radianMode = radianMode, - fractional = fractional, + onRadianModeClick = onRadianModeClick, + additionalButtons = additionalButtons, + onAdditionalButtonsClick = onAdditionalButtonsClick, + inverseMode = inverseMode, + onInverseModeClick = onInverseModeClick, + showAcButton = showAcButton, middleZero = middleZero, - addSymbol = addSymbol, - toggleAngleMode = toggleAngleMode, - deleteSymbol = deleteSymbol, - clearSymbols = clearSymbols, - equal = equal, - acButton = acButton, - addBracket = addBracket, - invMode = invMode, - toggleInvMode = { invMode = !invMode }, + fractional = fractional, ) } } @@ -166,30 +164,31 @@ internal fun CalculatorKeyboard( @Composable private fun PortraitKeyboard( modifier: Modifier, + onAddTokenClick: (String) -> Unit, + onBracketsClick: () -> Unit, + onDeleteClick: () -> Unit, + onClearClick: () -> Unit, + onEqualClick: () -> Unit, radianMode: Boolean, - fractional: String, + onRadianModeClick: (Boolean) -> Unit, + additionalButtons: Boolean, + onAdditionalButtonsClick: (Boolean) -> Unit, + inverseMode: Boolean, + onInverseModeClick: (Boolean) -> Unit, + showAcButton: Boolean, middleZero: Boolean, - addSymbol: (String) -> Unit, - toggleAngleMode: () -> Unit, - deleteSymbol: () -> Unit, - clearSymbols: () -> Unit, - equal: () -> Unit, - acButton: Boolean, - addBracket: () -> Unit, - invMode: Boolean, - toggleInvMode: () -> Unit, + fractional: String, ) { val angleIcon = remember(radianMode) { if (radianMode) IconPack.Rad else IconPack.Deg } val angleIconDescription = remember(radianMode) { if (radianMode) R.string.keyboard_radian else R.string.keyboard_degree } - val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) IconPack.Dot else IconPack.Comma } - val fractionalIconDescription = remember(fractional) { if (fractional == Token.Digit.dot) R.string.keyboard_dot else R.string.comma } + val fractionalIcon = remember(fractional) { if (fractional == Token.PERIOD) IconPack.Dot else IconPack.Comma } + val fractionalIconDescription = remember(fractional) { if (fractional == Token.PERIOD) R.string.keyboard_dot else R.string.comma } - var showAdditional: Boolean by remember { mutableStateOf(false) } val expandRotation: Float by animateFloatAsState( - targetValue = if (showAdditional) 180f else 0f, + targetValue = if (additionalButtons) 180f else 0f, animationSpec = tween(easing = FastOutSlowInEasing), - label = "Rotate on expand" + label = "Rotate on expand", ) ColumnWithConstraints( @@ -203,71 +202,71 @@ private fun PortraitKeyboard( Row( modifier = Modifier .fillMaxWidth(), - horizontalArrangement = Arrangement.Start + horizontalArrangement = Arrangement.Start, ) { Crossfade( - targetState = invMode, + targetState = inverseMode, label = "Inverse switch", modifier = Modifier .fillMaxWidth() - .weight(1f) + .weight(1f), ) { inverse -> if (inverse) { AdditionalPortrait( modifier = Modifier.fillMaxWidth(), - showAdditional = showAdditional, + additionalButtons = additionalButtons, buttonHeight = additionalButtonHeight, content1 = { buttonModifier -> - KeyboardButtonAdditional(buttonModifier, IconPack.Modulo, stringResource(R.string.keyboard_modulo), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Operator.modulo) } - KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Const.pi) } - KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Operator.power) } - KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Operator.factorial) } + KeyboardButtonAdditional(buttonModifier, IconPack.Modulo, stringResource(R.string.keyboard_modulo), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Operator.modulo) } + KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Const.pi) } + KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Operator.power) } + KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Operator.factorial) } }, content2 = { buttonModifier -> - KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonContentHeightTallAdditional) { toggleAngleMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.ArSin, stringResource(R.string.keyboard_arsin), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.arsinBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.ArCos, stringResource(R.string.keyboard_arcos), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.arcosBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.AcTan, stringResource(R.string.keyboard_actan), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.actanBracket) } + KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onRadianModeClick(!radianMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.ArSin, stringResource(R.string.keyboard_arsin), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.arsinBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.ArCos, stringResource(R.string.keyboard_arcos), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.arcosBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.AcTan, stringResource(R.string.keyboard_actan), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.actanBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonContentHeightTallAdditional) { toggleInvMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_euler), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Const.e) } - KeyboardButtonAdditional(buttonModifier, IconPack.Ex, stringResource(R.string.keyboard_exp), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.expBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Power10, stringResource(R.string.keyboard_power_10), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) } - } + KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onInverseModeClick(!inverseMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_euler), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Const.e) } + KeyboardButtonAdditional(buttonModifier, IconPack.Ex, stringResource(R.string.keyboard_exp), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.expBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Power10, stringResource(R.string.keyboard_power_10), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) } + }, ) } else { AdditionalPortrait( modifier = Modifier.fillMaxWidth(), - showAdditional = showAdditional, + additionalButtons = additionalButtons, buttonHeight = additionalButtonHeight, content1 = { buttonModifier -> - KeyboardButtonAdditional(buttonModifier, IconPack.Root, stringResource(R.string.keyboard_root), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Operator.sqrt) } - KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Const.pi) } - KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Operator.power) } - KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Operator.factorial) } + KeyboardButtonAdditional(buttonModifier, IconPack.Root, stringResource(R.string.keyboard_root), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Operator.sqrt) } + KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Const.pi) } + KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Operator.power) } + KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Operator.factorial) } }, content2 = { buttonModifier -> - KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonContentHeightTallAdditional) { toggleAngleMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Sin, stringResource(R.string.keyboard_sin), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.sinBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Cos, stringResource(R.string.keyboard_cos), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.cosBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Tan, stringResource(R.string.keyboard_tan), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.tanBracket) } + KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onRadianModeClick(!radianMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Sin, stringResource(R.string.keyboard_sin), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.sinBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Cos, stringResource(R.string.keyboard_cos), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.cosBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Tan, stringResource(R.string.keyboard_tan), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.tanBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonContentHeightTallAdditional) { toggleInvMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_exp), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Const.e) } - KeyboardButtonAdditional(buttonModifier, IconPack.Ln, stringResource(R.string.keyboard_ln), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.lnBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Log, stringResource(R.string.keyboard_log), KeyboardButtonContentHeightTallAdditional) { addSymbol(Token.Func.logBracket) } - } + KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onInverseModeClick(!inverseMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_exp), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Const.e) } + KeyboardButtonAdditional(buttonModifier, IconPack.Ln, stringResource(R.string.keyboard_ln), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.lnBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Log, stringResource(R.string.keyboard_log), KeyboardButtonToken.CONTENT_HEIGHT_TALL_ADDITIONAL) { onAddTokenClick(Token.Func.logBracket) } + }, ) } } Box( modifier = Modifier.size(additionalButtonHeight), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { IconButton( - onClick = { showAdditional = !showAdditional }, - colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.inverseOnSurface) + onClick = { onAdditionalButtonsClick(!additionalButtons) }, + colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.inverseOnSurface), ) { Icon(Icons.Default.ExpandMore, null, Modifier.rotate(expandRotation)) } @@ -287,40 +286,40 @@ private fun PortraitKeyboard( .fillMaxWidth(width) .fillMaxHeight(height) - if (acButton) { - KeyboardButtonTertiary(mainButtonModifier, IconPack.Clear, stringResource(R.string.clear_label), KeyboardButtonContentHeightTall) { clearSymbols() } - KeyboardButtonFilled(mainButtonModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), KeyboardButtonContentHeightTall) { addBracket() } + if (showAcButton) { + KeyboardButtonTertiary(mainButtonModifier, IconPack.Clear, stringResource(R.string.clear_label), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onClearClick() } + KeyboardButtonFilled(mainButtonModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onBracketsClick() } } else { - KeyboardButtonFilled(mainButtonModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.leftBracket) } - KeyboardButtonFilled(mainButtonModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.rightBracket) } + KeyboardButtonFilled(mainButtonModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.leftBracket) } + KeyboardButtonFilled(mainButtonModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.rightBracket) } } - KeyboardButtonFilled(mainButtonModifier, IconPack.Percent, stringResource(R.string.keyboard_percent), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.percent) } - KeyboardButtonFilled(mainButtonModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.divide) } + KeyboardButtonFilled(mainButtonModifier, IconPack.Percent, stringResource(R.string.keyboard_percent), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.percent) } + KeyboardButtonFilled(mainButtonModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.divide) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key7, Token.Digit._7, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._7) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key8, Token.Digit._8, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._8) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key9, Token.Digit._9, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._9) } - KeyboardButtonFilled(mainButtonModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.multiply) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key7, Token.Digit._7, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._7) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key8, Token.Digit._8, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._8) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key9, Token.Digit._9, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._9) } + KeyboardButtonFilled(mainButtonModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.multiply) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key4, Token.Digit._4, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._4) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key5, Token.Digit._5, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._5) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key6, Token.Digit._6, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._6) } - KeyboardButtonFilled(mainButtonModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.minus) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key4, Token.Digit._4, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._4) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key5, Token.Digit._5, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._5) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key6, Token.Digit._6, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._6) } + KeyboardButtonFilled(mainButtonModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.minus) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key1, Token.Digit._1, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._1) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key2, Token.Digit._2, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._2) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key3, Token.Digit._3, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._3) } - KeyboardButtonFilled(mainButtonModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), KeyboardButtonContentHeightTall) { addSymbol(Token.Operator.plus) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key1, Token.Digit._1, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._1) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key2, Token.Digit._2, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._2) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key3, Token.Digit._3, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._3) } + KeyboardButtonFilled(mainButtonModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Operator.plus) } if (middleZero) { - KeyboardButtonLight(mainButtonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonContentHeightTall) { addSymbol(Token.Digit.dot) } - KeyboardButtonLight(mainButtonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._0) } + KeyboardButtonLight(mainButtonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit.dot) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._0) } } else { - KeyboardButtonLight(mainButtonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonContentHeightTall) { addSymbol(Token.Digit._0) } - KeyboardButtonLight(mainButtonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonContentHeightTall) { addSymbol(Token.Digit.dot) } + KeyboardButtonLight(mainButtonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit._0) } + KeyboardButtonLight(mainButtonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onAddTokenClick(Token.Digit.dot) } } - KeyboardButtonLight(mainButtonModifier, IconPack.Backspace, stringResource(R.string.delete_label), KeyboardButtonContentHeightTall, clearSymbols) { deleteSymbol() } - KeyboardButtonFilled(mainButtonModifier, IconPack.Equal, stringResource(R.string.keyboard_equal), KeyboardButtonContentHeightTall) { equal() } + KeyboardButtonLight(mainButtonModifier, IconPack.Backspace, stringResource(R.string.delete_label), KeyboardButtonToken.CONTENT_HEIGHT_TALL, onClearClick) { onDeleteClick() } + KeyboardButtonFilled(mainButtonModifier, IconPack.Equal, stringResource(R.string.keyboard_equal), KeyboardButtonToken.CONTENT_HEIGHT_TALL) { onEqualClick() } } Spacer(modifier = Modifier.height(spacerHeight)) @@ -334,7 +333,7 @@ private fun PortraitKeyboard( * * Height: 3 buttons * - * @param showAdditional When `true` reveals [content2] with animation. + * @param additionalButtons When `true` reveals [content2] with animation. * @param buttonHeight Button height in [Dp]. * @param content1 First row of buttons. * @param content2 Second and third rows of buttons. @@ -342,19 +341,19 @@ private fun PortraitKeyboard( @Composable private fun AdditionalPortrait( modifier: Modifier, - showAdditional: Boolean, + additionalButtons: Boolean, buttonHeight: Dp, content1: @Composable (buttonModifier: Modifier) -> Unit, - content2: @Composable (buttonModifier: Modifier) -> Unit + content2: @Composable (buttonModifier: Modifier) -> Unit, ) { AnimatedContent( - targetState = showAdditional, + targetState = additionalButtons, modifier = modifier, label = "Additional buttons reveal", transitionSpec = { expandVertically(expandFrom = Alignment.Top) togetherWith - shrinkVertically(shrinkTowards = Alignment.Top) using (SizeTransform()) - } + shrinkVertically(shrinkTowards = Alignment.Top) using (SizeTransform()) + }, ) { show -> if (show) { KeypadFlow( @@ -398,141 +397,141 @@ private fun AdditionalPortrait( @Composable private fun LandscapeKeyboard( modifier: Modifier, + onAddTokenClick: (String) -> Unit, + onBracketsClick: () -> Unit, + onDeleteClick: () -> Unit, + onClearClick: () -> Unit, + onEqualClick: () -> Unit, radianMode: Boolean, - fractional: String, + onRadianModeClick: (Boolean) -> Unit, + inverseMode: Boolean, + onInverseModeClick: (Boolean) -> Unit, + showAcButton: Boolean, middleZero: Boolean, - addSymbol: (String) -> Unit, - toggleAngleMode: () -> Unit, - deleteSymbol: () -> Unit, - clearSymbols: () -> Unit, - equal: () -> Unit, - acButton: Boolean, - addBracket: () -> Unit, - invMode: Boolean, - toggleInvMode: () -> Unit, + fractional: String, ) { val angleIcon = remember(radianMode) { if (radianMode) IconPack.Rad else IconPack.Deg } val angleIconDescription = remember(radianMode) { if (radianMode) R.string.keyboard_radian else R.string.keyboard_degree } - val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) IconPack.Dot else IconPack.Comma } - val fractionalIconDescription = remember(fractional) { if (fractional == Token.Digit.dot) R.string.keyboard_dot else R.string.comma } + val fractionalIcon = remember(fractional) { if (fractional == Token.PERIOD) IconPack.Dot else IconPack.Comma } + val fractionalIconDescription = remember(fractional) { if (fractional == Token.PERIOD) R.string.keyboard_dot else R.string.comma } Crossfade( - targetState = invMode, + targetState = inverseMode, label = "Inverse switch", - modifier = modifier + modifier = modifier, ) { inverse -> if (inverse) { KeypadFlow( modifier = Modifier.fillMaxSize(), rows = 4, - columns = 8 + columns = 8, ) { width, height -> val buttonModifier = Modifier .fillMaxWidth(width) .fillMaxHeight(height) - KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonContentHeightShortAdditional) { toggleAngleMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Modulo, stringResource(R.string.keyboard_modulo), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Operator.modulo) } - KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Const.pi) } - KeyboardButtonLight(buttonModifier, IconPack.Key7, Token.Digit._7, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._7) } - KeyboardButtonLight(buttonModifier, IconPack.Key8, Token.Digit._8, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._8) } - KeyboardButtonLight(buttonModifier, IconPack.Key9, Token.Digit._9, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._9) } - if (acButton) { - KeyboardButtonTertiary(buttonModifier, IconPack.Clear, stringResource(R.string.clear_label), KeyboardButtonContentHeightShort) { clearSymbols() } - KeyboardButtonFilled(buttonModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), KeyboardButtonContentHeightShort) { addBracket() } + KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onRadianModeClick(!radianMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Modulo, stringResource(R.string.keyboard_modulo), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Operator.modulo) } + KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Const.pi) } + KeyboardButtonLight(buttonModifier, IconPack.Key7, Token.Digit._7, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._7) } + KeyboardButtonLight(buttonModifier, IconPack.Key8, Token.Digit._8, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._8) } + KeyboardButtonLight(buttonModifier, IconPack.Key9, Token.Digit._9, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._9) } + if (showAcButton) { + KeyboardButtonTertiary(buttonModifier, IconPack.Clear, stringResource(R.string.clear_label), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onClearClick() } + KeyboardButtonFilled(buttonModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onBracketsClick() } } else { - KeyboardButtonFilled(buttonModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.leftBracket) } - KeyboardButtonFilled(buttonModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.rightBracket) } + KeyboardButtonFilled(buttonModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.leftBracket) } + KeyboardButtonFilled(buttonModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.rightBracket) } } - KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonContentHeightShortAdditional) { toggleInvMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Operator.power) } - KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Operator.factorial) } - KeyboardButtonLight(buttonModifier, IconPack.Key4, Token.Digit._4, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._4) } - KeyboardButtonLight(buttonModifier, IconPack.Key5, Token.Digit._5, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._5) } - KeyboardButtonLight(buttonModifier, IconPack.Key6, Token.Digit._6, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._6) } - KeyboardButtonFilled(buttonModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.multiply) } - KeyboardButtonFilled(buttonModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.divide) } + KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onInverseModeClick(!inverseMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Operator.power) } + KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Operator.factorial) } + KeyboardButtonLight(buttonModifier, IconPack.Key4, Token.Digit._4, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._4) } + KeyboardButtonLight(buttonModifier, IconPack.Key5, Token.Digit._5, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._5) } + KeyboardButtonLight(buttonModifier, IconPack.Key6, Token.Digit._6, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._6) } + KeyboardButtonFilled(buttonModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.multiply) } + KeyboardButtonFilled(buttonModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.divide) } - KeyboardButtonAdditional(buttonModifier, IconPack.ArSin, stringResource(R.string.keyboard_arsin), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.arsinBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.ArCos, stringResource(R.string.keyboard_arcos), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.arcosBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.AcTan, stringResource(R.string.keyboard_actan), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.actanBracket) } - KeyboardButtonLight(buttonModifier, IconPack.Key1, Token.Digit._1, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._1) } - KeyboardButtonLight(buttonModifier, IconPack.Key2, Token.Digit._2, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._2) } - KeyboardButtonLight(buttonModifier, IconPack.Key3, Token.Digit._3, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._3) } - KeyboardButtonFilled(buttonModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.minus) } - KeyboardButtonFilled(buttonModifier, IconPack.Percent, stringResource(R.string.keyboard_percent), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.percent) } + KeyboardButtonAdditional(buttonModifier, IconPack.ArSin, stringResource(R.string.keyboard_arsin), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.arsinBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.ArCos, stringResource(R.string.keyboard_arcos), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.arcosBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.AcTan, stringResource(R.string.keyboard_actan), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.actanBracket) } + KeyboardButtonLight(buttonModifier, IconPack.Key1, Token.Digit._1, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._1) } + KeyboardButtonLight(buttonModifier, IconPack.Key2, Token.Digit._2, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._2) } + KeyboardButtonLight(buttonModifier, IconPack.Key3, Token.Digit._3, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._3) } + KeyboardButtonFilled(buttonModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.minus) } + KeyboardButtonFilled(buttonModifier, IconPack.Percent, stringResource(R.string.keyboard_percent), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.percent) } - KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_euler), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Const.e) } - KeyboardButtonAdditional(buttonModifier, IconPack.Ex, stringResource(R.string.keyboard_exp), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.expBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Power10, stringResource(R.string.keyboard_power_10), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) } + KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_euler), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Const.e) } + KeyboardButtonAdditional(buttonModifier, IconPack.Ex, stringResource(R.string.keyboard_exp), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.expBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Power10, stringResource(R.string.keyboard_power_10), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Digit._1 + Token.Digit._0 + Token.Operator.power) } if (middleZero) { - KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) } - KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) } + KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit.dot) } + KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._0) } } else { - KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) } - KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) } + KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._0) } + KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit.dot) } } - KeyboardButtonLight(buttonModifier, IconPack.Backspace, stringResource(R.string.delete_label), KeyboardButtonContentHeightShort, clearSymbols) { deleteSymbol() } - KeyboardButtonFilled(buttonModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.plus) } - KeyboardButtonFilled(buttonModifier, IconPack.Equal, stringResource(R.string.keyboard_equal), KeyboardButtonContentHeightShort) { equal() } + KeyboardButtonLight(buttonModifier, IconPack.Backspace, stringResource(R.string.delete_label), KeyboardButtonToken.CONTENT_HEIGHT_SHORT, onClearClick) { onDeleteClick() } + KeyboardButtonFilled(buttonModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.plus) } + KeyboardButtonFilled(buttonModifier, IconPack.Equal, stringResource(R.string.keyboard_equal), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onEqualClick() } } } else { KeypadFlow( modifier = Modifier.fillMaxSize(), rows = 4, - columns = 8 + columns = 8, ) { width, height -> val buttonModifier = Modifier .fillMaxWidth(width) .fillMaxHeight(height) - KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonContentHeightShortAdditional) { toggleAngleMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Root, stringResource(R.string.keyboard_root), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Operator.sqrt) } - KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Const.pi) } - KeyboardButtonLight(buttonModifier, IconPack.Key7, Token.Digit._7, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._7) } - KeyboardButtonLight(buttonModifier, IconPack.Key8, Token.Digit._8, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._8) } - KeyboardButtonLight(buttonModifier, IconPack.Key9, Token.Digit._9, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._9) } - if (acButton) { - KeyboardButtonTertiary(buttonModifier, IconPack.Clear, stringResource(R.string.clear_label), KeyboardButtonContentHeightShort) { clearSymbols() } - KeyboardButtonFilled(buttonModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), KeyboardButtonContentHeightShort) { addBracket() } + KeyboardButtonAdditional(buttonModifier, angleIcon, stringResource(angleIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onRadianModeClick(!radianMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Root, stringResource(R.string.keyboard_root), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Operator.sqrt) } + KeyboardButtonAdditional(buttonModifier, IconPack.Pi, stringResource(R.string.keyboard_pi), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Const.pi) } + KeyboardButtonLight(buttonModifier, IconPack.Key7, Token.Digit._7, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._7) } + KeyboardButtonLight(buttonModifier, IconPack.Key8, Token.Digit._8, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._8) } + KeyboardButtonLight(buttonModifier, IconPack.Key9, Token.Digit._9, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._9) } + if (showAcButton) { + KeyboardButtonTertiary(buttonModifier, IconPack.Clear, stringResource(R.string.clear_label), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onClearClick() } + KeyboardButtonFilled(buttonModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onBracketsClick() } } else { - KeyboardButtonFilled(buttonModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.leftBracket) } - KeyboardButtonFilled(buttonModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.rightBracket) } + KeyboardButtonFilled(buttonModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.leftBracket) } + KeyboardButtonFilled(buttonModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.rightBracket) } } - KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonContentHeightShortAdditional) { toggleInvMode() } - KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Operator.power) } - KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Operator.factorial) } - KeyboardButtonLight(buttonModifier, IconPack.Key4, Token.Digit._4, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._4) } - KeyboardButtonLight(buttonModifier, IconPack.Key5, Token.Digit._5, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._5) } - KeyboardButtonLight(buttonModifier, IconPack.Key6, Token.Digit._6, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._6) } - KeyboardButtonFilled(buttonModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.multiply) } - KeyboardButtonFilled(buttonModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.divide) } + KeyboardButtonAdditional(buttonModifier, IconPack.Inv, stringResource(R.string.keyboard_inverse), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onInverseModeClick(!inverseMode) } + KeyboardButtonAdditional(buttonModifier, IconPack.Power, stringResource(R.string.keyboard_power), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Operator.power) } + KeyboardButtonAdditional(buttonModifier, IconPack.Factorial, stringResource(R.string.keyboard_factorial), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Operator.factorial) } + KeyboardButtonLight(buttonModifier, IconPack.Key4, Token.Digit._4, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._4) } + KeyboardButtonLight(buttonModifier, IconPack.Key5, Token.Digit._5, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._5) } + KeyboardButtonLight(buttonModifier, IconPack.Key6, Token.Digit._6, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._6) } + KeyboardButtonFilled(buttonModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.multiply) } + KeyboardButtonFilled(buttonModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.divide) } - KeyboardButtonAdditional(buttonModifier, IconPack.Sin, stringResource(R.string.keyboard_sin), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.sinBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Cos, stringResource(R.string.keyboard_cos), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.cosBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Tan, stringResource(R.string.keyboard_tan), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.tanBracket) } - KeyboardButtonLight(buttonModifier, IconPack.Key1, Token.Digit._1, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._1) } - KeyboardButtonLight(buttonModifier, IconPack.Key2, Token.Digit._2, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._2) } - KeyboardButtonLight(buttonModifier, IconPack.Key3, Token.Digit._3, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._3) } - KeyboardButtonFilled(buttonModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.minus) } - KeyboardButtonFilled(buttonModifier, IconPack.Percent, stringResource(R.string.keyboard_percent), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.percent) } + KeyboardButtonAdditional(buttonModifier, IconPack.Sin, stringResource(R.string.keyboard_sin), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.sinBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Cos, stringResource(R.string.keyboard_cos), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.cosBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Tan, stringResource(R.string.keyboard_tan), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.tanBracket) } + KeyboardButtonLight(buttonModifier, IconPack.Key1, Token.Digit._1, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._1) } + KeyboardButtonLight(buttonModifier, IconPack.Key2, Token.Digit._2, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._2) } + KeyboardButtonLight(buttonModifier, IconPack.Key3, Token.Digit._3, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._3) } + KeyboardButtonFilled(buttonModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.minus) } + KeyboardButtonFilled(buttonModifier, IconPack.Percent, stringResource(R.string.keyboard_percent), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.percent) } - KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_euler), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Const.e) } - KeyboardButtonAdditional(buttonModifier, IconPack.Ln, stringResource(R.string.keyboard_ln), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.lnBracket) } - KeyboardButtonAdditional(buttonModifier, IconPack.Log, stringResource(R.string.keyboard_log), KeyboardButtonContentHeightShortAdditional) { addSymbol(Token.Func.logBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Euler, stringResource(R.string.keyboard_euler), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Const.e) } + KeyboardButtonAdditional(buttonModifier, IconPack.Ln, stringResource(R.string.keyboard_ln), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.lnBracket) } + KeyboardButtonAdditional(buttonModifier, IconPack.Log, stringResource(R.string.keyboard_log), KeyboardButtonToken.CONTENT_HEIGHT_SHORT_ADDITIONAL) { onAddTokenClick(Token.Func.logBracket) } if (middleZero) { - KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) } - KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) } + KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit.dot) } + KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._0) } } else { - KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonContentHeightShort) { addSymbol(Token.Digit._0) } - KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonContentHeightShort) { addSymbol(Token.Digit.dot) } + KeyboardButtonLight(buttonModifier, IconPack.Key0, Token.Digit._0, KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit._0) } + KeyboardButtonLight(buttonModifier, fractionalIcon, stringResource(fractionalIconDescription), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Digit.dot) } } - KeyboardButtonLight(buttonModifier, IconPack.Backspace, stringResource(R.string.delete_label), KeyboardButtonContentHeightShort, clearSymbols) { deleteSymbol() } - KeyboardButtonFilled(buttonModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), KeyboardButtonContentHeightShort) { addSymbol(Token.Operator.plus) } - KeyboardButtonFilled(buttonModifier, IconPack.Equal, stringResource(R.string.keyboard_equal), KeyboardButtonContentHeightShort) { equal() } + KeyboardButtonLight(buttonModifier, IconPack.Backspace, stringResource(R.string.delete_label), KeyboardButtonToken.CONTENT_HEIGHT_SHORT, onClearClick) { onDeleteClick() } + KeyboardButtonFilled(buttonModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onAddTokenClick(Token.Operator.plus) } + KeyboardButtonFilled(buttonModifier, IconPack.Equal, stringResource(R.string.keyboard_equal), KeyboardButtonToken.CONTENT_HEIGHT_SHORT) { onEqualClick() } } } } @@ -543,18 +542,20 @@ private fun LandscapeKeyboard( private fun PreviewPortraitKeyboard() { PortraitKeyboard( modifier = Modifier.fillMaxHeight(), + onAddTokenClick = {}, + onBracketsClick = {}, + onDeleteClick = {}, + onClearClick = {}, + onEqualClick = {}, radianMode = true, - fractional = FormatterSymbols.Comma.fractional, - addSymbol = {}, - clearSymbols = {}, - deleteSymbol = {}, - toggleAngleMode = {}, - equal = {}, + onRadianModeClick = {}, + additionalButtons = false, + onAdditionalButtonsClick = {}, + inverseMode = false, + onInverseModeClick = {}, + showAcButton = true, middleZero = false, - acButton = true, - addBracket = {}, - invMode = false, - toggleInvMode = {} + fractional = Token.PERIOD, ) } @@ -563,17 +564,17 @@ private fun PreviewPortraitKeyboard() { private fun PreviewLandscapeKeyboard() { LandscapeKeyboard( modifier = Modifier.fillMaxHeight(), + onAddTokenClick = {}, + onBracketsClick = {}, + onDeleteClick = {}, + onClearClick = {}, + onEqualClick = {}, radianMode = true, - fractional = FormatterSymbols.Comma.fractional, - addSymbol = {}, - clearSymbols = {}, - deleteSymbol = {}, - toggleAngleMode = {}, - equal = {}, + onRadianModeClick = {}, + inverseMode = false, + onInverseModeClick = {}, + showAcButton = true, middleZero = false, - acButton = true, - addBracket = {}, - invMode = false, - toggleInvMode = {} + fractional = Token.PERIOD, ) } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/HistoryList.kt similarity index 54% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/HistoryList.kt index 986d8ca7..606c6f33 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/HistoryList.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/HistoryList.kt @@ -16,12 +16,17 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator.components +package app.myzel394.numberhub.feature.calculator.components +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.Crossfade import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +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.height import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn @@ -29,7 +34,9 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.History +import androidx.compose.material.icons.outlined.Close import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -40,10 +47,11 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.textfield.FixedInputTextField -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.data.model.HistoryItem +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.FixedExpressionInputTextField +import app.myzel394.numberhub.data.model.HistoryItem import java.text.SimpleDateFormat import java.util.Locale @@ -53,18 +61,27 @@ internal fun HistoryList( historyItems: List, formatterSymbols: FormatterSymbols, addTokens: (String) -> Unit, + onDelete: (HistoryItem) -> Unit, + showDeleteButtons: Boolean, ) { - if (historyItems.isEmpty()) { - HistoryListPlaceholder( - modifier = modifier, - ) - } else { - HistoryListContent( - modifier = modifier, - historyItems = historyItems, - addTokens = addTokens, - formatterSymbols = formatterSymbols, - ) + Crossfade( + targetState = historyItems.isEmpty(), + label = "History list", + ) { emptyList -> + if (emptyList) { + HistoryListPlaceholder( + modifier = modifier, + ) + } else { + HistoryListContent( + modifier = modifier, + historyItems = historyItems, + formatterSymbols = formatterSymbols, + addTokens = addTokens, + onDelete = onDelete, + showDeleteButtons = showDeleteButtons, + ) + } } } @@ -75,12 +92,12 @@ private fun HistoryListPlaceholder( Column( modifier = modifier.wrapContentHeight(unbounded = true), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Column( modifier = Modifier.height(HistoryItemHeight), verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { Icon(Icons.Default.History, stringResource(R.string.calculator_no_history)) Text(stringResource(R.string.calculator_no_history)) @@ -92,19 +109,24 @@ private fun HistoryListPlaceholder( private fun HistoryListContent( modifier: Modifier, historyItems: List, - addTokens: (String) -> Unit, formatterSymbols: FormatterSymbols, + addTokens: (String) -> Unit, + onDelete: (HistoryItem) -> Unit, + showDeleteButtons: Boolean, ) { val state = rememberLazyListState() val focusManager = LocalFocusManager.current - // Very bad workaround for https://issuetracker.google.com/issues/295745063 - // Will remove once the fix is released + // Selection handles cause lag LaunchedEffect(state.isScrollInProgress) { focusManager.clearFocus(true) } - LaunchedEffect(historyItems) { state.scrollToItem(0) } + LaunchedEffect(historyItems) { + // Don't scroll when the UI is in state where user can delete an item. This fixes items + // placement animation + if (!showDeleteButtons) state.scrollToItem(0) + } LazyColumn( modifier = modifier, @@ -113,9 +135,12 @@ private fun HistoryListContent( ) { items(historyItems, { it.id }) { historyItem -> HistoryListItem( + modifier = Modifier.animateItemPlacement(), historyItem = historyItem, formatterSymbols = formatterSymbols, addTokens = addTokens, + onDelete = { onDelete(historyItem) }, + showDeleteButton = showDeleteButtons, ) } } @@ -127,24 +152,48 @@ private fun HistoryListItem( historyItem: HistoryItem, formatterSymbols: FormatterSymbols, addTokens: (String) -> Unit, + onDelete: () -> Unit, + showDeleteButton: Boolean, ) { - Column( + Row( modifier = modifier.height(HistoryItemHeight), - verticalArrangement = Arrangement.Center + verticalAlignment = Alignment.CenterVertically, ) { - FixedInputTextField( - value = historyItem.expression, - formatterSymbols = formatterSymbols, - textColor = MaterialTheme.colorScheme.onSurfaceVariant, - onClick = addTokens, - ) + AnimatedVisibility(visible = showDeleteButton) { + IconButton(onClick = onDelete) { + Icon( + modifier = Modifier, + imageVector = Icons.Outlined.Close, + contentDescription = stringResource(R.string.delete_label), + tint = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } + } + Column( + modifier = Modifier + .weight(1f) + .fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.End, + ) { + FixedExpressionInputTextField( + modifier = Modifier + .fillMaxWidth(), + value = historyItem.expression, + formatterSymbols = formatterSymbols, + textColor = MaterialTheme.colorScheme.onSurfaceVariant, + onClick = { addTokens(historyItem.expression) }, + ) - FixedInputTextField( - value = historyItem.result, - formatterSymbols = formatterSymbols, - textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f), - onClick = addTokens, - ) + FixedExpressionInputTextField( + modifier = Modifier + .fillMaxWidth(), + value = historyItem.result, + formatterSymbols = formatterSymbols, + textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f), + onClick = { addTokens(historyItem.result) }, + ) + } } } @@ -169,7 +218,7 @@ private fun PreviewHistoryList() { id = it.hashCode(), date = dtf.parse(it)!!, expression = "12345".repeat(10), - result = "67890" + result = "67890", ) } @@ -178,7 +227,9 @@ private fun PreviewHistoryList() { .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)) .fillMaxSize(), historyItems = historyItems, - formatterSymbols = FormatterSymbols.Spaces, - addTokens = {} + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), + addTokens = {}, + onDelete = {}, + showDeleteButtons = true, ) } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/TextBox.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/TextBox.kt similarity index 56% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/TextBox.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/TextBox.kt index f94099ed..2a5c57f9 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/TextBox.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/components/TextBox.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator.components +package app.myzel394.numberhub.feature.calculator.components import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box @@ -37,24 +37,22 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag -import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.UnformattedTextField -import com.sadellie.unitto.feature.calculator.CalculationResult +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowHeightSizeClass +import app.myzel394.numberhub.core.ui.common.textfield.ExpressionTextField +import app.myzel394.numberhub.core.ui.common.textfield.SimpleTextField +import app.myzel394.numberhub.feature.calculator.CalculationResult @Composable fun TextBox( modifier: Modifier, formatterSymbols: FormatterSymbols, input: TextFieldValue, - deleteSymbol: () -> Unit, - addSymbol: (String) -> Unit, - onCursorChange: (TextRange) -> Unit, + onValueChange: (TextFieldValue) -> Unit, output: CalculationResult, ) { Column( @@ -63,9 +61,11 @@ fun TextBox( .background( MaterialTheme.colorScheme.surfaceVariant, RoundedCornerShape( - topStartPercent = 0, topEndPercent = 0, - bottomStartPercent = 20, bottomEndPercent = 20 - ) + topStartPercent = 0, + topEndPercent = 0, + bottomStartPercent = 20, + bottomEndPercent = 20, + ), ) .padding(top = 4.dp), horizontalAlignment = Alignment.CenterHorizontally, @@ -77,88 +77,61 @@ fun TextBox( .padding(horizontal = 8.dp), value = input, minRatio = 0.5f, - cutCallback = deleteSymbol, - pasteCallback = addSymbol, - onCursorChange = onCursorChange, - formatterSymbols = formatterSymbols + onValueChange = onValueChange, + formatterSymbols = formatterSymbols, ) if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) { + val calculationResultModifier = Modifier + .weight(2f) + .fillMaxWidth() + .padding(horizontal = 8.dp) + when (output) { is CalculationResult.Empty -> { Spacer( - modifier = Modifier - .weight(2f) - .fillMaxWidth() - .padding(horizontal = 8.dp) + modifier = calculationResultModifier, ) } - is CalculationResult.Default -> { - var outputTF by remember(output) { - mutableStateOf(TextFieldValue(output.text)) - } + is CalculationResult.Success -> { + var outputTF by remember(output) { mutableStateOf(TextFieldValue(output.text)) } ExpressionTextField( - modifier = Modifier - .weight(2f) - .fillMaxWidth() - .padding(horizontal = 8.dp), + modifier = calculationResultModifier, value = outputTF, minRatio = 0.8f, - onCursorChange = { outputTF = outputTF.copy(selection = it) }, - formatterSymbols = formatterSymbols, + onValueChange = { outputTF = outputTF.copy(selection = it.selection) }, textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f), - readOnly = true, - ) - } - - is CalculationResult.Fraction -> { - var outputTF by remember(output) { - mutableStateOf(TextFieldValue(output.text)) - } - ExpressionTextField( - modifier = Modifier - .weight(2f) - .fillMaxWidth() - .padding(horizontal = 8.dp), - value = outputTF, - minRatio = 0.8f, - onCursorChange = { outputTF = outputTF.copy(selection = it) }, formatterSymbols = formatterSymbols, - textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f), readOnly = true, ) } is CalculationResult.DivideByZeroError -> { - UnformattedTextField( - modifier = Modifier - .weight(2f) - .fillMaxWidth() - .padding(horizontal = 8.dp), - value = TextFieldValue(stringResource(output.label)), + SimpleTextField( + modifier = calculationResultModifier, + value = TextFieldValue(stringResource(R.string.calculator_divide_by_zero_error)), minRatio = 0.8f, - onCursorChange = {}, + onValueChange = {}, textColor = MaterialTheme.colorScheme.error, readOnly = true, ) } is CalculationResult.Error -> { - UnformattedTextField( + SimpleTextField( modifier = Modifier .weight(2f) .fillMaxWidth() .padding(horizontal = 8.dp), - value = TextFieldValue(stringResource(output.label)), + value = TextFieldValue(stringResource(R.string.error_label)), minRatio = 0.8f, - onCursorChange = {}, + onValueChange = {}, textColor = MaterialTheme.colorScheme.error, readOnly = true, ) } } - } // Handle Box( @@ -166,9 +139,9 @@ fun TextBox( .padding(8.dp) .background( MaterialTheme.colorScheme.onSurfaceVariant, - RoundedCornerShape(100) + RoundedCornerShape(100), ) - .sizeIn(24.dp, 4.dp) + .sizeIn(24.dp, 4.dp), ) } -} \ No newline at end of file +} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/navigation/CalculatorNavigation.kt similarity index 57% rename from feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt rename to feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/navigation/CalculatorNavigation.kt index d6f6f262..d01966fb 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/navigation/CalculatorNavigation.kt +++ b/feature/calculator/src/main/java/app/myzel394/numberhub/feature/calculator/navigation/CalculatorNavigation.kt @@ -16,43 +16,32 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator.navigation +package app.myzel394.numberhub.feature.calculator.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.navDeepLink -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.unittoComposable -import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.feature.calculator.CalculatorRoute -import com.sadellie.unitto.feature.calculator.RPNCalculatorRoute +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.unittoComposable +import app.myzel394.numberhub.core.ui.unittoNavigation +import app.myzel394.numberhub.feature.calculator.CalculatorRoute private val graph = DrawerItem.Calculator.graph private val start = DrawerItem.Calculator.start fun NavGraphBuilder.calculatorGraph( - rpnMode: Boolean, openDrawer: () -> Unit, - navigateToSettings: () -> Unit ) { unittoNavigation( startDestination = start, route = graph, deepLinks = listOf( - navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" } - ) + navDeepLink { uriPattern = "app://app.myzel394.numberhub/$graph" }, + ), ) { unittoComposable(start) { - if (rpnMode) { - RPNCalculatorRoute( - openDrawer = openDrawer, - navigateToSettings = navigateToSettings - ) - } else { - CalculatorRoute( - navigateToMenu = openDrawer, - navigateToSettings = navigateToSettings - ) - } + CalculatorRoute( + openDrawer = openDrawer, + ) } } } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt deleted file mode 100644 index 93ecc99b..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator - -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.addBracket -import com.sadellie.unitto.core.ui.common.textfield.addTokens -import com.sadellie.unitto.core.ui.common.textfield.deleteTokens -import com.sadellie.unitto.core.ui.common.textfield.getTextField -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.common.isExpression -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.CalculatorHistoryRepository -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import io.github.sadellie.evaluatto.Expression -import io.github.sadellie.evaluatto.ExpressionException -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.mapLatest -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.math.BigDecimal -import java.math.RoundingMode -import javax.inject.Inject - -@HiltViewModel -internal class CalculatorViewModel @Inject constructor( - private val userPrefsRepository: UserPreferencesRepository, - private val calculatorHistoryRepository: CalculatorHistoryRepository, - private val savedStateHandle: SavedStateHandle, -) : ViewModel() { - private val _inputKey = "CALCULATOR_INPUT" - private val _input = MutableStateFlow(savedStateHandle.getTextField(_inputKey)) - private val _result = MutableStateFlow(CalculationResult.Empty) - private val _equalClicked = MutableStateFlow(false) - private val _prefs = userPrefsRepository.calculatorPrefs - .stateIn(viewModelScope, null) - private var _fractionJob: Job? = null - - val uiState: StateFlow = combine( - _input, - _result, - _prefs, - calculatorHistoryRepository.historyFlow, - ) { input, result, prefs, history -> - prefs ?: return@combine CalculatorUIState.Loading - - return@combine CalculatorUIState.Ready( - input = input, - output = result, - radianMode = prefs.radianMode, - precision = prefs.precision, - outputFormat = prefs.outputFormat, - formatterSymbols = AllFormatterSymbols.getById(prefs.separator), - history = history, - middleZero = prefs.middleZero, - acButton = prefs.acButton, - partialHistoryView = prefs.partialHistoryView, - ) - } - .mapLatest { ui -> - if (ui !is CalculatorUIState.Ready) return@mapLatest ui - if (_equalClicked.value) return@mapLatest ui - - if (!ui.input.text.isExpression()) { - _result.update { CalculationResult.Empty } - return@mapLatest ui - } - - _result.update { - try { - CalculationResult.Default( - calculate( - input = ui.input.text, - radianMode = ui.radianMode, - ) - .format(ui.precision, ui.outputFormat) - ) - } catch (e: ExpressionException.DivideByZero) { - CalculationResult.Empty - } catch (e: Exception) { - CalculationResult.Empty - } - } - - ui - } - .stateIn(viewModelScope, CalculatorUIState.Loading) - - fun addTokens(tokens: String) = _input.update { - val isClearInputNeeded = _equalClicked.value and Token.Digit.allWithDot.contains(tokens) - - var newValue = when { - // Clean input after clicking "=" and any token that is a Digit - isClearInputNeeded -> TextFieldValue() - _equalClicked.value -> it.copy(selection = TextRange(it.text.length)) - else -> it - } - newValue = newValue.addTokens(tokens) - - _equalClicked.update { false } - _fractionJob?.cancel() - savedStateHandle[_inputKey] = newValue.text - newValue - } - - fun addBracket() = _input.update { - var newValue = if (_equalClicked.value) { - // Cursor is set to 0 when equal is clicked - it.copy(selection = TextRange(it.text.length)) - } else { - it - } - newValue = newValue.addBracket() - - _equalClicked.update { false } - _fractionJob?.cancel() - savedStateHandle[_inputKey] = newValue.text - newValue - } - - fun deleteTokens() = _input.update { - val newValue = if (_equalClicked.value) { - TextFieldValue() - } else { - it.deleteTokens() - } - _equalClicked.update { false } - _fractionJob?.cancel() - savedStateHandle[_inputKey] = newValue.text - newValue - } - - fun clearInput() = _input.update { - _equalClicked.update { false } - _fractionJob?.cancel() - savedStateHandle[_inputKey] = "" - TextFieldValue() - } - - fun onCursorChange(selection: TextRange) = _input.update { - // Without this line: will place token (even in the middle of the input) and place cursor at - // the end. This line also removes fractional output once user touches input text field - _equalClicked.update { false } - it.copy(selection = selection) - } - - fun updateRadianMode(newValue: Boolean) = viewModelScope.launch { - userPrefsRepository.updateRadianMode(newValue) - } - - fun clearHistory() = viewModelScope.launch(Dispatchers.IO) { - calculatorHistoryRepository.clear() - } - - fun equal() = viewModelScope.launch { - val prefs = _prefs.value ?: return@launch - if (_equalClicked.value) return@launch - if (!_input.value.text.isExpression()) return@launch - - val result = try { - calculate(_input.value.text, prefs.radianMode, RoundingMode.DOWN) - } catch (e: ExpressionException.DivideByZero) { - _equalClicked.update { true } - _result.update { CalculationResult.DivideByZeroError } - return@launch - } catch (e: ExpressionException.FactorialCalculation) { - _equalClicked.update { true } - _result.update { CalculationResult.Error } - return@launch - } catch (e: Exception) { - _equalClicked.update { true } - _result.update { CalculationResult.Error } - return@launch - } - - _equalClicked.update { true } - - val resultFormatted = result - .format(prefs.precision, prefs.outputFormat) - .replace("-", Token.Operator.minus) - - withContext(Dispatchers.IO) { - calculatorHistoryRepository.add( - expression = _input.value.text.replace("-", Token.Operator.minus), - result = resultFormatted - ) - } - - _fractionJob?.cancel() - _fractionJob = launch(Dispatchers.Default) { - val fraction = result.toFractionalString() - - _input.update { TextFieldValue(resultFormatted, TextRange.Zero) } - _result.update { CalculationResult.Fraction(fraction) } - } - } - - private suspend fun calculate( - input: String, - radianMode: Boolean, - roundingMode: RoundingMode = RoundingMode.HALF_EVEN, - ): BigDecimal = withContext(Dispatchers.Default) { - Expression(input, radianMode, roundingMode) - .calculate() - .also { - if (it > BigDecimal.valueOf(Double.MAX_VALUE)) throw ExpressionException.TooBig() - } - } -} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/InputBox.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/InputBox.kt deleted file mode 100644 index a8b84558..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/InputBox.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -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.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField -import com.sadellie.unitto.core.ui.common.textfield.FixedInputTextField -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.data.common.format -import java.math.BigDecimal - -@Composable -internal fun InputBox( - modifier: Modifier, - input: TextFieldValue, - onCursorChange: (TextRange) -> Unit, - stack: List, - formatterSymbols: FormatterSymbols, - precision: Int, - outputFormat: Int, -) { - val listState = rememberLazyListState() - - LaunchedEffect(stack) { - listState.animateScrollToItem(stack.lastIndex.coerceAtLeast(0)) - } - - Column( - modifier = modifier - .clip(RoundedCornerShape(24.dp)) - .fillMaxWidth() - .background(MaterialTheme.colorScheme.surfaceVariant) - .padding(start = 12.dp, end = 12.dp, bottom = 12.dp), - verticalArrangement = Arrangement.Bottom - ) { - LazyColumn( - modifier = Modifier.weight(1f), - state = listState, - verticalArrangement = Arrangement.Bottom, - ) { - items(stack) { - FixedInputTextField( - modifier = Modifier.fillMaxWidth(), - value = it.format(precision, outputFormat), - formatterSymbols = formatterSymbols, - textColor = MaterialTheme.colorScheme.onSurfaceVariant, - onClick = {} - ) - } - } - - ExpressionTextField( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight(0.25f), - value = input, - minRatio = 0.6f, - onCursorChange = onCursorChange, - formatterSymbols = formatterSymbols, - textColor = MaterialTheme.colorScheme.onSurfaceVariant - ) - } -} - -@Preview(device = "spec:width=1080px,height=2160px,dpi=440") -@Composable -fun PreviewInputBox() { - InputBox( - modifier = Modifier.fillMaxSize(), - input = TextFieldValue("123456.789"), - onCursorChange = {}, - stack = listOf( - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - ), - formatterSymbols = FormatterSymbols.Spaces, - precision = 3, - outputFormat = OutputFormat.PLAIN - ) -} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorKeyboard.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorKeyboard.kt deleted file mode 100644 index f38788ab..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorKeyboard.kt +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.tooling.preview.Preview -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightShort -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTallAdditional -import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled -import com.sadellie.unitto.core.ui.common.KeyboardButtonLight -import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary -import com.sadellie.unitto.core.ui.common.KeypadFlow -import com.sadellie.unitto.core.ui.common.icons.IconPack -import com.sadellie.unitto.core.ui.common.icons.iconpack.Backspace -import com.sadellie.unitto.core.ui.common.icons.iconpack.Clear -import com.sadellie.unitto.core.ui.common.icons.iconpack.Comma -import com.sadellie.unitto.core.ui.common.icons.iconpack.Divide -import com.sadellie.unitto.core.ui.common.icons.iconpack.Dot -import com.sadellie.unitto.core.ui.common.icons.iconpack.Down -import com.sadellie.unitto.core.ui.common.icons.iconpack.Enter -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key0 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key1 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key2 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key3 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key4 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key5 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key6 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key7 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key8 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key9 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Minus -import com.sadellie.unitto.core.ui.common.icons.iconpack.Multiply -import com.sadellie.unitto.core.ui.common.icons.iconpack.Percent -import com.sadellie.unitto.core.ui.common.icons.iconpack.Plus -import com.sadellie.unitto.core.ui.common.icons.iconpack.Pop -import com.sadellie.unitto.core.ui.common.icons.iconpack.Swap -import com.sadellie.unitto.core.ui.common.icons.iconpack.Unary -import com.sadellie.unitto.core.ui.common.icons.iconpack.Up -import io.github.sadellie.evaluatto.RPNCalculation - -@Composable -internal fun RPNCalculatorKeyboard( - modifier: Modifier, - fractional: String, - middleZero: Boolean, - onCalculationClick: (RPNCalculation) -> Unit, - onInputEditClick: (RPNInputEdit) -> Unit, -) { - val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) IconPack.Dot else IconPack.Comma } - - if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) { - RPNCalculatorKeyboardLandscape( - modifier = modifier, - fractionalIcon = fractionalIcon, - middleZero = middleZero, - onCalculationClick = onCalculationClick, - onInputEditClick = onInputEditClick - ) - } else { - RPNCalculatorKeyboardPortrait( - modifier = modifier, - fractionalIcon = fractionalIcon, - middleZero = middleZero, - onCalculationClick = onCalculationClick, - onInputEditClick = onInputEditClick - ) - } -} - -@Composable -private fun RPNCalculatorKeyboardPortrait( - modifier: Modifier, - fractionalIcon: ImageVector, - middleZero: Boolean, - onCalculationClick: (RPNCalculation) -> Unit, - onInputEditClick: (RPNInputEdit) -> Unit, -) { - Column( - modifier = modifier - ) { - KeypadFlow( - modifier = Modifier.fillMaxHeight(0.1f).fillMaxWidth(), - rows = 1, - columns = 4 - ) { width, height -> - val aModifier = Modifier - .fillMaxWidth(width) - .fillMaxHeight(height) - - KeyboardButtonAdditional(aModifier, IconPack.Swap, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Swap) } - KeyboardButtonAdditional(aModifier, IconPack.Up, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateUp) } - KeyboardButtonAdditional(aModifier, IconPack.Down, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateDown) } - KeyboardButtonAdditional(aModifier, IconPack.Pop, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Pop) } - } - - KeypadFlow( - modifier = Modifier.weight(1f).fillMaxSize(), - rows = 5, - columns = 4 - ) { width, height -> - val bModifier = Modifier - .fillMaxWidth(width) - .fillMaxHeight(height) - - KeyboardButtonTertiary(bModifier, IconPack.Clear, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Clear) } - KeyboardButtonFilled(bModifier, IconPack.Unary, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Negate) } - KeyboardButtonFilled(bModifier, IconPack.Percent, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Percent) } - KeyboardButtonFilled(bModifier, IconPack.Divide, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Divide) } - - KeyboardButtonLight(bModifier, IconPack.Key7, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) } - KeyboardButtonLight(bModifier, IconPack.Key8, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) } - KeyboardButtonLight(bModifier, IconPack.Key9, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) } - KeyboardButtonFilled(bModifier, IconPack.Multiply, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Multiply) } - - KeyboardButtonLight(bModifier, IconPack.Key4, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) } - KeyboardButtonLight(bModifier, IconPack.Key5, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) } - KeyboardButtonLight(bModifier, IconPack.Key6, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) } - KeyboardButtonFilled(bModifier, IconPack.Minus, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Minus) } - - KeyboardButtonLight(bModifier, IconPack.Key1, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) } - KeyboardButtonLight(bModifier, IconPack.Key2, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) } - KeyboardButtonLight(bModifier, IconPack.Key3, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) } - KeyboardButtonFilled(bModifier, IconPack.Plus, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Plus) } - - if (middleZero) { - KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Dot) } - KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) } - } else { - KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) } - KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Dot) } - } - KeyboardButtonLight(bModifier, IconPack.Backspace, null, KeyboardButtonContentHeightTall) { onInputEditClick(RPNInputEdit.Delete) } - KeyboardButtonFilled(bModifier, IconPack.Enter, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Enter) } - } - } -} - -@Composable -private fun RPNCalculatorKeyboardLandscape( - modifier: Modifier, - fractionalIcon: ImageVector, - middleZero: Boolean, - onCalculationClick: (RPNCalculation) -> Unit, - onInputEditClick: (RPNInputEdit) -> Unit, -) { - KeypadFlow( - modifier = modifier, - rows = 4, - columns = 6 - ) { width, height -> - val bModifier = Modifier - .fillMaxHeight(height) - .fillMaxWidth(width) - - KeyboardButtonAdditional(bModifier, IconPack.Swap, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Swap) } - KeyboardButtonLight(bModifier, IconPack.Key7, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._7)) } - KeyboardButtonLight(bModifier, IconPack.Key8, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._8)) } - KeyboardButtonLight(bModifier, IconPack.Key9, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._9)) } - KeyboardButtonTertiary(bModifier, IconPack.Clear, null, KeyboardButtonContentHeightTall) { onCalculationClick(RPNCalculation.Clear) } - KeyboardButtonFilled(bModifier, IconPack.Unary, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Negate) } - - KeyboardButtonAdditional(bModifier, IconPack.Up, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateUp) } - KeyboardButtonLight(bModifier, IconPack.Key4, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._4)) } - KeyboardButtonLight(bModifier, IconPack.Key5, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._5)) } - KeyboardButtonLight(bModifier, IconPack.Key6, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._6)) } - KeyboardButtonFilled(bModifier, IconPack.Multiply, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Multiply) } - KeyboardButtonFilled(bModifier, IconPack.Divide, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Divide) } - - KeyboardButtonAdditional(bModifier, IconPack.Down, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.RotateDown) } - KeyboardButtonLight(bModifier, IconPack.Key1, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._1)) } - KeyboardButtonLight(bModifier, IconPack.Key2, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._2)) } - KeyboardButtonLight(bModifier, IconPack.Key3, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._3)) } - KeyboardButtonFilled(bModifier, IconPack.Plus, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Plus) } - KeyboardButtonFilled(bModifier, IconPack.Minus, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Minus) } - - KeyboardButtonAdditional(bModifier, IconPack.Pop, null, KeyboardButtonContentHeightTallAdditional) { onCalculationClick(RPNCalculation.Pop) } - if (middleZero) { - KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Dot) } - KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) } - } else { - KeyboardButtonLight(bModifier, IconPack.Key0, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Digit(Token.Digit._0)) } - KeyboardButtonLight(bModifier, fractionalIcon, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Dot) } - } - KeyboardButtonLight(bModifier, IconPack.Backspace, null, KeyboardButtonContentHeightShort) { onInputEditClick(RPNInputEdit.Delete) } - KeyboardButtonFilled(bModifier, IconPack.Percent, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Percent) } - KeyboardButtonFilled(bModifier, IconPack.Enter, null, KeyboardButtonContentHeightShort) { onCalculationClick(RPNCalculation.Enter) } - } -} - -@Preview(device = "spec:parent=pixel_5,orientation=portrait") -@Preview(device = "spec:parent=pixel_5,orientation=landscape") -@Composable -private fun PreviewKeyboard() { - RPNCalculatorKeyboard( - modifier = Modifier.fillMaxSize(), - fractional = Token.Digit.dot, - middleZero = false, - onCalculationClick = {}, - onInputEditClick = {} - ) -} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorScreen.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorScreen.kt deleted file mode 100644 index 7028b939..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorScreen.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.common.MenuButton -import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import io.github.sadellie.evaluatto.RPNCalculation -import java.math.BigDecimal - -@Composable -internal fun RPNCalculatorRoute( - openDrawer: () -> Unit, - navigateToSettings: () -> Unit, - viewModel: RPNCalculatorViewModel = hiltViewModel(), -) { - when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { - RPNCalculatorUIState.Loading -> EmptyScreen() - is RPNCalculatorUIState.Ready -> RPNCalculatorScreen( - uiState = uiState, - openDrawer = openDrawer, - navigateToSettings = navigateToSettings, - onCursorChange = viewModel::onCursorChange, - onCalculationClick = viewModel::onCalculationClick, - onInputEditClick = viewModel::onInputEdit - ) - } -} - -@Composable -internal fun RPNCalculatorScreen( - uiState: RPNCalculatorUIState.Ready, - openDrawer: () -> Unit, - navigateToSettings: () -> Unit, - onCursorChange: (TextRange) -> Unit, - onCalculationClick: (RPNCalculation) -> Unit, - onInputEditClick: (RPNInputEdit) -> Unit, -) { - ScaffoldWithTopBar( - title = { Text(stringResource(id = R.string.calculator_title)) }, - navigationIcon = { MenuButton(openDrawer) }, - actions = { SettingsButton(navigateToSettings) } - ) { paddingValues -> - Column( - Modifier.padding(paddingValues) - ) { - InputBox( - modifier = Modifier - .padding(8.dp) - .fillMaxHeight(if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) 0.3f else 0.5f), - input = uiState.input, - stack = uiState.stack, - formatterSymbols = uiState.formatterSymbols, - precision = uiState.precision, - outputFormat = uiState.outputFormat, - onCursorChange = onCursorChange - ) - RPNCalculatorKeyboard( - modifier = Modifier - .padding(horizontal = 4.dp) - .fillMaxSize(), - fractional = uiState.formatterSymbols.fractional, - middleZero = uiState.middleZero, - onCalculationClick = onCalculationClick, - onInputEditClick = onInputEditClick - ) - } - } -} - -@Preview(widthDp = 432, heightDp = 1008, device = "spec:parent=pixel_5,orientation=portrait") -@Preview(widthDp = 432, heightDp = 864, device = "spec:parent=pixel_5,orientation=portrait") -@Preview(widthDp = 597, heightDp = 1393, device = "spec:parent=pixel_5,orientation=portrait") -@Composable -private fun RPNCalculatorScreenPreview() { - RPNCalculatorScreen( - uiState = RPNCalculatorUIState.Ready( - input = TextFieldValue("test"), - stack = listOf( - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - BigDecimal("123456.7890"), - ), - precision = 3, - outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces, - middleZero = true, - ), - openDrawer = {}, - navigateToSettings = {}, - onCalculationClick = {}, - onInputEditClick = {}, - onCursorChange = {} - ) -} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorViewModel.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorViewModel.kt deleted file mode 100644 index 2de873d3..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNCalculatorViewModel.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator - -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.addTokens -import com.sadellie.unitto.core.ui.common.textfield.deleteTokens -import com.sadellie.unitto.core.ui.common.textfield.getTextField -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import io.github.sadellie.evaluatto.RPNCalculation -import io.github.sadellie.evaluatto.RPNResult -import io.github.sadellie.evaluatto.perform -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.math.BigDecimal -import javax.inject.Inject - -@HiltViewModel -internal class RPNCalculatorViewModel @Inject constructor( - userPrefsRepository: UserPreferencesRepository, - private val savedStateHandle: SavedStateHandle, -) : ViewModel() { - - private val _inputKey = "RPN_CALCULATOR_INPUT" - private val _input = MutableStateFlow(savedStateHandle.getTextField(_inputKey)) - private val _stack = MutableStateFlow(emptyList()) - private val _prefs = userPrefsRepository.calculatorPrefs.stateIn(viewModelScope, null) - - val uiState = combine( - _prefs, - _input, - _stack - ) { prefs, input, stack -> - prefs ?: return@combine RPNCalculatorUIState.Loading - - return@combine RPNCalculatorUIState.Ready( - input = input, - stack = stack, - precision = prefs.precision, - outputFormat = prefs.outputFormat, - formatterSymbols = AllFormatterSymbols.getById(prefs.separator), - middleZero = prefs.middleZero - ) - } - .stateIn(viewModelScope, RPNCalculatorUIState.Loading) - - fun onInputEdit(action: RPNInputEdit) { - val input = _input.value - val newInput = when (action) { - is RPNInputEdit.Digit -> input.addTokens(action.value) - RPNInputEdit.Dot -> { - if (_input.value.text.contains(Token.Digit.dot)) return - input.addTokens(Token.Digit.dot) - } - RPNInputEdit.Delete -> input.deleteTokens() - } - - _input.update { newInput } - savedStateHandle[_inputKey] = newInput.text - } - - fun onCalculationClick(action: RPNCalculation) = viewModelScope.launch { - val prefs = _prefs.value ?: return@launch - - val newResult = withContext(Dispatchers.Default) { - action.perform(_input.value.text, _stack.value) - } - - when (newResult) { - is RPNResult.Result -> { - val newInput = newResult.input?.format(prefs.precision, prefs.outputFormat) ?: "" - _input.update { TextFieldValue(newInput, TextRange(newInput.length)) } - _stack.update { newResult.stack } - } - - is RPNResult.NewStack -> { - _stack.update { newResult.stack } - } - - is RPNResult.NewInput -> { - val newInput = newResult.input.format(prefs.precision, prefs.outputFormat) - _input.update { TextFieldValue(newInput, TextRange(newInput.length)) } - } - RPNResult.BadInput, RPNResult.DivideByZero -> Unit - } - } - - fun onCursorChange(selection: TextRange) = _input.update { it.copy(selection = selection) } -} diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNInputEdit.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNInputEdit.kt deleted file mode 100644 index 28a391d9..00000000 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/RPNInputEdit.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.calculator - -sealed class RPNInputEdit { - data class Digit(val value: String) : RPNInputEdit() - data object Delete : RPNInputEdit() - data object Dot : RPNInputEdit() -} diff --git a/feature/calculator/src/test/java/com/sadellie/unitto/feature/calculator/DecimalToFractionTest.kt b/feature/calculator/src/test/java/app/myzel394/numberhub/feature/calculator/DecimalToFractionTest.kt similarity index 57% rename from feature/calculator/src/test/java/com/sadellie/unitto/feature/calculator/DecimalToFractionTest.kt rename to feature/calculator/src/test/java/app/myzel394/numberhub/feature/calculator/DecimalToFractionTest.kt index da71d66a..a53ad676 100644 --- a/feature/calculator/src/test/java/com/sadellie/unitto/feature/calculator/DecimalToFractionTest.kt +++ b/feature/calculator/src/test/java/app/myzel394/numberhub/feature/calculator/DecimalToFractionTest.kt @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.calculator +package app.myzel394.numberhub.feature.calculator +import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals import org.junit.Test import java.math.BigDecimal @@ -25,60 +26,52 @@ import java.math.BigDecimal class DecimalToFractionTest { @Test fun testNoDecimal1() { - val bd = BigDecimal("100") - assertFractional("", bd.toFractionalString()) + assertFractional("", "100") } @Test fun testNoDecimal2() { - val bd = BigDecimal("100.000000000") - assertFractional("", bd.toFractionalString()) + assertFractional("", "100.000000000") } @Test fun testSimpleDecimal1() { - val bd = BigDecimal("0.25") - assertFractional("1/4", bd.toFractionalString()) + assertFractional("1/4", "0.25") } @Test fun testSimpleDecimal2() { - val bd = BigDecimal("100.25") - assertFractional("100 1/4", bd.toFractionalString()) + assertFractional("100 1/4", "100.25") } @Test fun testRepeating1() { - val bd = BigDecimal("0.666666666") - assertFractional("2/3", bd.toFractionalString()) + assertFractional("2/3", "0.666666666") } @Test fun testRepeating2() { - val bd = BigDecimal("4.666666666") - assertFractional("4 2/3", bd.toFractionalString()) + assertFractional("4 2/3", "4.666666666") } @Test fun testRepeating3() { - val bd = BigDecimal("0.78571428571428571428") - assertFractional("11/14", bd.toFractionalString()) + assertFractional("11/14", "0.78571428571428571428") } @Test fun testRepeating4() { - val bd = BigDecimal("66.78571428571428571428") - assertFractional("66 11/14", bd.toFractionalString()) + assertFractional("66 11/14", "66.78571428571428571428") } @Test fun testRepeating5() { - val bd = BigDecimal("0.666000") - assertFractional("333/500", bd.toFractionalString()) + assertFractional("333/500", "0.666000") } private fun assertFractional(expected: String, actual: String) = assertEquals( expected, - actual.replace("⁄", "/") + runBlocking { BigDecimal(actual).toFractionalString() } + .replace("⁄", "/"), ) } diff --git a/feature/converter/build.gradle.kts b/feature/converter/build.gradle.kts index 8bdfcc50..6ec553c8 100644 --- a/feature/converter/build.gradle.kts +++ b/feature/converter/build.gradle.kts @@ -25,7 +25,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.converter" +android.namespace = "app.myzel394.numberhub.feature.converter" android.testOptions.unitTests.isIncludeAndroidResources = true dependencies { @@ -36,9 +36,6 @@ dependencies { ksp(libs.androidx.room.compiler) testImplementation(libs.androidx.datastore.datastore.preferences) - implementation(libs.com.squareup.moshi.moshi.kotlin) - implementation(libs.com.squareup.retrofit2.converter.moshi) - implementation(project(":data:common")) implementation(project(":data:database")) implementation(project(":data:evaluatto")) diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/NetworkUtils.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConnectionState.kt similarity index 89% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/NetworkUtils.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConnectionState.kt index ae47624b..95d5e200 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/NetworkUtils.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConnectionState.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter +package app.myzel394.numberhub.feature.converter import android.content.Context import android.net.ConnectivityManager @@ -41,8 +41,12 @@ private fun Context.observeConnectivityAsFlow() = callbackFlow { val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val callback = object : ConnectivityManager.NetworkCallback() { - override fun onAvailable(network: Network) { trySend(ConnectionState.Available) } - override fun onLost(network: Network) { trySend(ConnectionState.Unavailable) } + override fun onAvailable(network: Network) { + trySend(ConnectionState.Available) + } + override fun onLost(network: Network) { + trySend(ConnectionState.Unavailable) + } } val networkRequest = NetworkRequest.Builder() diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterScreen.kt similarity index 57% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterScreen.kt index eb9548f3..c6be06a3 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter +package app.myzel394.numberhub.feature.converter import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility @@ -55,6 +55,7 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -64,119 +65,107 @@ import androidx.compose.ui.focus.onFocusEvent import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.LocalLocale -import com.sadellie.unitto.core.ui.common.ColumnWithConstraints -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.MenuButton -import com.sadellie.unitto.core.ui.common.PortraitLandscape -import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar -import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.UnformattedTextField -import com.sadellie.unitto.core.ui.datetime.formatDateWeekDayMonthYear -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.feature.converter.components.DefaultKeyboard -import com.sadellie.unitto.feature.converter.components.NumberBaseKeyboard -import com.sadellie.unitto.feature.converter.components.UnitSelectionButton +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.LocalLocale +import app.myzel394.numberhub.core.ui.common.ColumnWithConstraints +import app.myzel394.numberhub.core.ui.common.DrawerButton +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.PortraitLandscape +import app.myzel394.numberhub.core.ui.common.ScaffoldWithTopBar +import app.myzel394.numberhub.core.ui.common.textfield.ExpressionTextField +import app.myzel394.numberhub.core.ui.common.textfield.NumberBaseTextField +import app.myzel394.numberhub.core.ui.common.textfield.SimpleTextField +import app.myzel394.numberhub.core.ui.common.textfield.addBracket +import app.myzel394.numberhub.core.ui.common.textfield.addTokens +import app.myzel394.numberhub.core.ui.common.textfield.deleteTokens +import app.myzel394.numberhub.core.ui.datetime.formatDateWeekDayMonthYear +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.data.common.isEqualTo +import app.myzel394.numberhub.data.common.isExpression +import app.myzel394.numberhub.data.converter.ConverterResult +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.feature.converter.components.DefaultKeyboard +import app.myzel394.numberhub.feature.converter.components.NumberBaseKeyboard +import app.myzel394.numberhub.feature.converter.components.UnitSelectionButton +import java.math.BigDecimal import java.util.Locale @Composable internal fun ConverterRoute( viewModel: ConverterViewModel = hiltViewModel(), - navigateToLeftScreen: () -> Unit, - navigateToRightScreen: () -> Unit, - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, + openDrawer: () -> Unit, ) { - val uiState = viewModel.converterUiState.collectAsStateWithLifecycle() + val uiState = viewModel.converterUIState.collectAsStateWithLifecycle() ConverterScreen( uiState = uiState.value, navigateToLeftScreen = navigateToLeftScreen, navigateToRightScreen = navigateToRightScreen, - navigateToSettings = navigateToSettings, - navigateToMenu = navigateToMenu, + openDrawer = openDrawer, swapUnits = viewModel::swapUnits, - processInput = viewModel::addTokens, - deleteDigit = viewModel::deleteTokens, - clearInput = viewModel::clearInput, - onCursorChange = viewModel::onCursorChange, - onFocusOnInput2 = viewModel::updateFocused, - onErrorClick = viewModel::updateCurrencyRates, - addBracket = viewModel::addBracket + updateInput1 = viewModel::updateInput1, + updateInput2 = viewModel::updateInput2, + convertDefault = viewModel::convertDefault, + convertNumberBase = viewModel::convertNumberBase, ) } @Composable private fun ConverterScreen( uiState: UnitConverterUIState, - navigateToLeftScreen: () -> Unit, - navigateToRightScreen: () -> Unit, - navigateToSettings: () -> Unit, - navigateToMenu: () -> Unit, - swapUnits: () -> Unit, - processInput: (String) -> Unit, - deleteDigit: () -> Unit, - clearInput: () -> Unit, - onCursorChange: (TextRange) -> Unit, - onFocusOnInput2: (Boolean) -> Unit, - onErrorClick: (AbstractUnit) -> Unit, - addBracket: () -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, + openDrawer: () -> Unit, + swapUnits: (String, String) -> Unit, + updateInput1: (TextFieldValue) -> Unit, + updateInput2: (TextFieldValue) -> Unit, + convertDefault: () -> Unit, + convertNumberBase: () -> Unit, ) { when (uiState) { UnitConverterUIState.Loading -> EmptyScreen() is UnitConverterUIState.NumberBase -> { UnitConverterTopBar( - navigateToMenu = navigateToMenu, - navigateToSettings = navigateToSettings + openDrawer = openDrawer, ) { NumberBase( modifier = Modifier.padding(it), uiState = uiState, - onCursorChange = onCursorChange, - processInput = processInput, - deleteDigit = deleteDigit, + updateInput1 = updateInput1, navigateToLeftScreen = navigateToLeftScreen, swapUnits = swapUnits, navigateToRightScreen = navigateToRightScreen, - clearInput = clearInput + convert = convertNumberBase, ) } } is UnitConverterUIState.Default -> { UnitConverterTopBar( - navigateToMenu = navigateToMenu, - navigateToSettings = navigateToSettings + openDrawer = openDrawer, ) { Default( modifier = Modifier.padding(it), uiState = uiState, - onCursorChange = onCursorChange, - onFocusOnInput2 = onFocusOnInput2, - processInput = processInput, - deleteDigit = deleteDigit, + updateInput1 = updateInput1, + updateInput2 = updateInput2, navigateToLeftScreen = navigateToLeftScreen, swapUnits = swapUnits, navigateToRightScreen = navigateToRightScreen, - clearInput = clearInput, - refreshCurrencyRates = onErrorClick, - addBracket = addBracket, + convert = convertDefault, ) } } @@ -185,18 +174,14 @@ private fun ConverterScreen( @Composable private fun UnitConverterTopBar( - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, - content: @Composable (PaddingValues) -> Unit + openDrawer: () -> Unit, + content: @Composable (PaddingValues) -> Unit, ) { ScaffoldWithTopBar( - title = { Text(stringResource(R.string.unit_converter_title)) }, - navigationIcon = { MenuButton { navigateToMenu() } }, - actions = { - SettingsButton(navigateToSettings) - }, + title = {}, + navigationIcon = { DrawerButton { openDrawer() } }, colors = TopAppBarDefaults.centerAlignedTopAppBarColors(containerColor = Color.Transparent), - content = { content(it) } + content = { content(it) }, ) } @@ -204,34 +189,38 @@ private fun UnitConverterTopBar( private fun NumberBase( modifier: Modifier, uiState: UnitConverterUIState.NumberBase, - onCursorChange: (TextRange) -> Unit, - processInput: (String) -> Unit, - deleteDigit: () -> Unit, - navigateToLeftScreen: () -> Unit, - swapUnits: () -> Unit, - navigateToRightScreen: () -> Unit, - clearInput: () -> Unit, + updateInput1: (TextFieldValue) -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + swapUnits: (String, String) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, + convert: () -> Unit, ) { + LaunchedEffect( + uiState.input.text, + uiState.unitFrom.id, + uiState.unitTo.id, + ) { + convert() + } + PortraitLandscape( modifier = modifier.fillMaxSize(), content1 = { contentModifier -> ColumnWithConstraints(modifier = contentModifier) { val textFieldModifier = Modifier.weight(2f) - UnformattedTextField( + NumberBaseTextField( modifier = textFieldModifier, minRatio = 0.7f, placeholder = Token.Digit._0, value = uiState.input, - onCursorChange = onCursorChange, - pasteCallback = processInput, - cutCallback = deleteDigit, + onValueChange = updateInput1, ) AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName)) ConverterResultTextField( modifier = textFieldModifier, - result = uiState.result + result = uiState.result, ) AnimatedUnitShortName(stringResource(uiState.unitTo.shortName)) @@ -240,20 +229,29 @@ private fun NumberBase( UnitSelectionButtons( unitFromLabel = stringResource(uiState.unitFrom.displayName), unitToLabel = stringResource(uiState.unitTo.displayName), - swapUnits = swapUnits, - navigateToLeftScreen = navigateToLeftScreen, - navigateToRightScreen = navigateToRightScreen + swapUnits = { swapUnits(uiState.unitTo.id, uiState.unitFrom.id) }, + navigateToLeftScreen = { + navigateToLeftScreen(uiState.unitFrom.id, uiState.unitFrom.group) + }, + navigateToRightScreen = { + navigateToRightScreen( + uiState.unitFrom.id, + uiState.unitTo.id, + uiState.unitFrom.group, + uiState.input.text, + ) + }, ) } }, - content2 = { + content2 = { modifier2 -> NumberBaseKeyboard( - modifier = it, - addDigit = processInput, - deleteDigit = deleteDigit, - clearInput = clearInput, + modifier = modifier2, + addDigit = { updateInput1(uiState.input.addTokens(it)) }, + deleteDigit = { updateInput1(uiState.input.deleteTokens()) }, + clearInput = { updateInput1(TextFieldValue()) }, ) - } + }, ) } @@ -261,22 +259,21 @@ private fun NumberBase( private fun Default( modifier: Modifier, uiState: UnitConverterUIState.Default, - onCursorChange: (TextRange) -> Unit, - onFocusOnInput2: (Boolean) -> Unit, - processInput: (String) -> Unit, - deleteDigit: () -> Unit, - navigateToLeftScreen: () -> Unit, - swapUnits: () -> Unit, - navigateToRightScreen: () -> Unit, - clearInput: () -> Unit, - refreshCurrencyRates: (AbstractUnit) -> Unit, - addBracket: () -> Unit, + updateInput1: (TextFieldValue) -> Unit, + updateInput2: (TextFieldValue) -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + swapUnits: (String, String) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, + convert: () -> Unit, ) { val locale: Locale = LocalLocale.current - var calculation by remember(uiState.calculation) { - mutableStateOf( - TextFieldValue(uiState.calculation?.format(uiState.scale, uiState.outputFormat) ?: "") - ) + val showCalculation = remember(uiState.input1.text, uiState.result) { + if (uiState.input1.text.isExpression()) { + if (uiState.result is ConverterResult.Default) { + return@remember !uiState.result.calculation.isEqualTo(BigDecimal.ZERO) + } + } + false } val connection by connectivityState() val lastUpdate by remember(uiState.currencyRateUpdateState) { @@ -285,14 +282,25 @@ private fun Default( uiState.currencyRateUpdateState.date.formatDateWeekDayMonthYear(locale) } } + var focusedOnInput1 by rememberSaveable { mutableStateOf(true) } LaunchedEffect(connection) { - if ((connection == ConnectionState.Available) and (uiState.result == ConverterResult.Error)) { + if ((connection == ConnectionState.Available) and (uiState.result is ConverterResult.Error)) { val unitFrom = uiState.unitFrom - if (unitFrom.group == UnitGroup.CURRENCY) refreshCurrencyRates(unitFrom) + if (unitFrom.group == UnitGroup.CURRENCY) convert() } } + LaunchedEffect( + uiState.input1.text, + uiState.input2.text, + uiState.unitFrom.id, + uiState.unitTo.id, + uiState.formatTime, + ) { + convert() + } + PortraitLandscape( modifier = modifier.fillMaxSize(), content1 = { contentModifier -> @@ -314,29 +322,29 @@ private fun Default( .fillMaxWidth(), text = lastUpdate.orEmpty(), color = MaterialTheme.colorScheme.onSurfaceVariant, - textAlign = TextAlign.Center + textAlign = TextAlign.Center, ) } if (uiState.unitFrom.id == UnitID.foot) { Row( modifier = textFieldModifier, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { Column( modifier = Modifier .fillMaxWidth() - .weight(1f) + .weight(1f), ) { ExpressionTextField( - modifier = Modifier.fillMaxWidth().weight(1f), - minRatio = 0.7f, - placeholder = Token.Digit._0, + modifier = Modifier + .fillMaxWidth() + .weight(1f), value = uiState.input1, - onCursorChange = onCursorChange, - pasteCallback = processInput, - cutCallback = deleteDigit, + minRatio = 0.7f, + onValueChange = updateInput1, formatterSymbols = uiState.formatterSymbols, + placeholder = Token.Digit._0, ) AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName)) } @@ -346,18 +354,18 @@ private fun Default( Column( modifier = Modifier .fillMaxWidth() - .weight(1f) + .weight(1f), ) { ExpressionTextField( - modifier = Modifier.fillMaxWidth().weight(1f) - .onFocusEvent { state -> onFocusOnInput2(state.hasFocus) }, - minRatio = 0.7f, - placeholder = Token.Digit._0, + modifier = Modifier + .fillMaxWidth() + .weight(1f) + .onFocusEvent { state -> focusedOnInput1 = !state.hasFocus }, value = uiState.input2, - onCursorChange = onCursorChange, - pasteCallback = processInput, - cutCallback = deleteDigit, + minRatio = 0.7f, + onValueChange = updateInput2, formatterSymbols = uiState.formatterSymbols, + placeholder = Token.Digit._0, ) AnimatedUnitShortName(stringResource(R.string.unit_inch_short)) } @@ -365,28 +373,35 @@ private fun Default( } else { ExpressionTextField( modifier = textFieldModifier, - minRatio = 0.7f, - placeholder = Token.Digit._0, value = uiState.input1, - onCursorChange = onCursorChange, - pasteCallback = processInput, - cutCallback = deleteDigit, + minRatio = 0.7f, + onValueChange = updateInput1, formatterSymbols = uiState.formatterSymbols, + placeholder = Token.Digit._0, ) AnimatedVisibility( - visible = calculation.text.isNotEmpty(), + visible = showCalculation, modifier = Modifier.weight(1f), enter = expandVertically(clip = false), - exit = shrinkVertically(clip = false) + exit = shrinkVertically(clip = false), ) { + var calculationTextField by remember(uiState.result) { + val text = if (uiState.result is ConverterResult.Default) { + uiState.result.calculation + .format(uiState.scale, uiState.outputFormat) + } else { + "" + } + mutableStateOf(TextFieldValue(text)) + } ExpressionTextField( modifier = Modifier, - value = calculation, - onCursorChange = { calculation = calculation.copy(selection = it) }, - formatterSymbols = uiState.formatterSymbols, + value = calculationTextField, minRatio = 0.7f, + onValueChange = { calculationTextField = it }, textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f), - readOnly = true + formatterSymbols = uiState.formatterSymbols, + readOnly = true, ) } AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName)) @@ -398,13 +413,16 @@ private fun Default( scale = uiState.scale, outputFormat = uiState.outputFormat, formatterSymbols = uiState.formatterSymbols, - onErrorClick = { refreshCurrencyRates(uiState.unitFrom) } + onErrorClick = convert, ) AnimatedUnitShortName( stringResource( - if (uiState.result is ConverterResult.Error) R.string.click_to_try_again_label - else uiState.unitTo.shortName - ) + when (uiState.result) { + // Currency conversion can be retried + is ConverterResult.Error.Currency -> R.string.click_to_try_again_label + else -> uiState.unitTo.shortName + }, + ), ) Spacer(modifier = Modifier.height(boxWithConstraintsScope.maxHeight * 0.03f)) @@ -412,24 +430,60 @@ private fun Default( UnitSelectionButtons( unitFromLabel = stringResource(uiState.unitFrom.displayName), unitToLabel = stringResource(uiState.unitTo.displayName), - swapUnits = swapUnits, - navigateToLeftScreen = navigateToLeftScreen, - navigateToRightScreen = navigateToRightScreen + swapUnits = { swapUnits(uiState.unitTo.id, uiState.unitFrom.id) }, + navigateToLeftScreen = { + navigateToLeftScreen(uiState.unitFrom.id, uiState.unitFrom.group) + }, + navigateToRightScreen = { + val input = if (uiState.result is ConverterResult.Default) { + uiState.result.calculation.toPlainString() + } else { + uiState.input1.text + } + + navigateToRightScreen( + uiState.unitFrom.id, + uiState.unitTo.id, + uiState.unitFrom.group, + input, + ) + }, ) } }, - content2 = { + content2 = { modifier2 -> DefaultKeyboard( - modifier = it, - addDigit = processInput, - deleteDigit = deleteDigit, - clearInput = clearInput, + modifier = modifier2, + addDigit = { + if (focusedOnInput1) { + updateInput1(uiState.input1.addTokens(it)) + } else { + updateInput2(uiState.input2.addTokens(it)) + } + }, + deleteDigit = { + if (focusedOnInput1) { + updateInput1(uiState.input1.deleteTokens()) + } else { + updateInput2(uiState.input2.deleteTokens()) + } + }, + clearInput = { + updateInput1(TextFieldValue()) + updateInput2(TextFieldValue()) + }, fractional = uiState.formatterSymbols.fractional, middleZero = uiState.middleZero, acButton = uiState.acButton, - addBracket = addBracket + addBracket = { + if (focusedOnInput1) { + updateInput1(uiState.input1.addBracket()) + } else { + updateInput2(uiState.input2.addBracket()) + } + }, ) - } + }, ) } @@ -439,7 +493,7 @@ private fun ConverterResultTextField( result: ConverterResult, scale: Int = 0, outputFormat: Int = OutputFormat.PLAIN, - formatterSymbols: FormatterSymbols = FormatterSymbols.Spaces, + formatterSymbols: FormatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), onErrorClick: () -> Unit = {}, ) { val mContext = LocalContext.current @@ -456,20 +510,31 @@ private fun ConverterResultTextField( when (result) { is ConverterResult.Loading -> { - UnformattedTextField( + SimpleTextField( modifier = modifier, value = TextFieldValue(stringResource(R.string.loading_label)), - onCursorChange = {}, + onValueChange = {}, minRatio = 0.7f, - readOnly = true + readOnly = true, + ) + } + + is ConverterResult.Error.DivideByZero -> { + SimpleTextField( + modifier = modifier, + value = TextFieldValue(stringResource(R.string.calculator_divide_by_zero_error)), + onValueChange = { onErrorClick() }, + minRatio = 0.7f, + readOnly = true, + textColor = MaterialTheme.colorScheme.error, ) } is ConverterResult.Error -> { - UnformattedTextField( + SimpleTextField( modifier = modifier, value = TextFieldValue(stringResource(R.string.error_label)), - onCursorChange = { onErrorClick() }, + onValueChange = { onErrorClick() }, minRatio = 0.7f, readOnly = true, textColor = MaterialTheme.colorScheme.error, @@ -480,22 +545,32 @@ private fun ConverterResultTextField( ExpressionTextField( modifier = modifier, value = resultTextField, - onCursorChange = { resultTextField = resultTextField.copy(selection = it) }, - formatterSymbols = formatterSymbols, minRatio = 0.7f, - readOnly = true + onValueChange = { resultTextField = it }, + formatterSymbols = formatterSymbols, + readOnly = true, ) } - is ConverterResult.NumberBase, - is ConverterResult.Time, - is ConverterResult.FootInch -> { - UnformattedTextField( + is ConverterResult.NumberBase -> { + NumberBaseTextField( modifier = modifier, value = resultTextField, - onCursorChange = { resultTextField = resultTextField.copy(selection = it) }, + onValueChange = { resultTextField = it }, minRatio = 0.7f, - readOnly = true + readOnly = true, + ) + } + + is ConverterResult.Time, + is ConverterResult.FootInch, + -> { + SimpleTextField( + modifier = modifier, + value = resultTextField, + onValueChange = { resultTextField = it }, + minRatio = 0.7f, + readOnly = true, ) } } @@ -510,14 +585,16 @@ private fun AnimatedUnitShortName( targetState = label, transitionSpec = { // Enter animation - (expandHorizontally(clip = false, expandFrom = Alignment.Start) + fadeIn() - togetherWith fadeOut()) using SizeTransform(clip = false) + ( + expandHorizontally(clip = false, expandFrom = Alignment.Start) + fadeIn() + togetherWith fadeOut() + ) using SizeTransform(clip = false) }, - label = "Animated short name from" + label = "Animated short name from", ) { value -> Text( text = value, - style = MaterialTheme.typography.bodyMedium.copy(textAlign = TextAlign.End) + style = MaterialTheme.typography.bodyMedium.copy(textAlign = TextAlign.End), ) } } @@ -534,7 +611,7 @@ private fun UnitSelectionButtons( val swapButtonRotation: Float by animateFloatAsState( targetValue = if (swapped) 0f else 180f, animationSpec = tween(easing = FastOutSlowInEasing), - label = "Swap button rotation" + label = "Swap button rotation", ) Row(verticalAlignment = Alignment.CenterVertically) { @@ -543,7 +620,7 @@ private fun UnitSelectionButtons( .fillMaxWidth() .weight(1f), label = unitFromLabel, - onClick = navigateToLeftScreen + onClick = navigateToLeftScreen, ) IconButton( onClick = { @@ -554,7 +631,7 @@ private fun UnitSelectionButtons( Icon( modifier = Modifier.rotate(swapButtonRotation), imageVector = Icons.Outlined.SwapHoriz, - contentDescription = stringResource(R.string.converter_swap_units_description) + contentDescription = stringResource(R.string.converter_swap_units_description), ) } UnitSelectionButton( @@ -562,7 +639,7 @@ private fun UnitSelectionButtons( .fillMaxWidth() .weight(1f), label = unitToLabel, - onClick = navigateToRightScreen + onClick = navigateToRightScreen, ) } } @@ -577,17 +654,13 @@ private fun UnitSelectionButtons( private fun PreviewConverterScreen() { ConverterScreen( uiState = UnitConverterUIState.Loading, - navigateToLeftScreen = {}, - navigateToRightScreen = {}, - navigateToSettings = {}, - navigateToMenu = {}, - swapUnits = {}, - processInput = {}, - deleteDigit = {}, - clearInput = {}, - onCursorChange = {}, - onFocusOnInput2 = {}, - onErrorClick = {}, - addBracket = {} + navigateToLeftScreen = { _, _ -> }, + navigateToRightScreen = { _, _, _, _ -> }, + openDrawer = {}, + swapUnits = { _, _ -> }, + updateInput1 = {}, + updateInput2 = {}, + convertDefault = {}, + convertNumberBase = {}, ) } diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterUIState.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterUIState.kt new file mode 100644 index 00000000..ad53bb50 --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterUIState.kt @@ -0,0 +1,117 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2022-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import android.content.Context +import androidx.compose.ui.text.input.TextFieldValue +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.data.common.isGreaterThan +import app.myzel394.numberhub.data.converter.ConverterResult +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import java.math.BigDecimal + +internal sealed class UnitConverterUIState { + data object Loading : UnitConverterUIState() + + data class Default( + val input1: TextFieldValue, + val input2: TextFieldValue, + val result: ConverterResult, + val unitFrom: BasicUnit.Default, + val unitTo: BasicUnit.Default, + val middleZero: Boolean, + val formatterSymbols: FormatterSymbols, + val scale: Int, + val outputFormat: Int, + val formatTime: Boolean, + val currencyRateUpdateState: CurrencyRateUpdateState, + val acButton: Boolean, + ) : UnitConverterUIState() + + data class NumberBase( + val input: TextFieldValue, + val result: ConverterResult, + val unitFrom: BasicUnit.NumberBase, + val unitTo: BasicUnit.NumberBase, + ) : UnitConverterUIState() +} + +internal fun ConverterResult.Time.format( + mContext: Context, + formatterSymbols: FormatterSymbols, +): String { + val result = mutableListOf() + + if (day.isGreaterThan(BigDecimal.ZERO)) { + result += "${day.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_day_short)}" + } + + if (hour.isGreaterThan(BigDecimal.ZERO)) { + result += "${hour.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_hour_short)}" + } + + if (minute.isGreaterThan(BigDecimal.ZERO)) { + result += "${minute.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_minute_short)}" + } + + if (second.isGreaterThan(BigDecimal.ZERO)) { + result += "${second.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_second_short)}" + } + + if (millisecond.isGreaterThan(BigDecimal.ZERO)) { + result += "${millisecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_millisecond_short)}" + } + + if (microsecond.isGreaterThan(BigDecimal.ZERO)) { + result += "${microsecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_microsecond_short)}" + } + + if (nanosecond.isGreaterThan(BigDecimal.ZERO)) { + result += "${nanosecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_nanosecond_short)}" + } + + if (attosecond.isGreaterThan(BigDecimal.ZERO)) { + result += "${attosecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_attosecond_short)}" + } + + return (if (negative) Token.Operator.minus else "") + result.joinToString(" ").ifEmpty { Token.Digit._0 } +} + +internal fun ConverterResult.FootInch.format( + mContext: Context, + scale: Int, + outputFormat: Int, + formatterSymbols: FormatterSymbols, +): String { + var result = "" + result += foot.format(scale, outputFormat).formatExpression(formatterSymbols) + + if (inch.isGreaterThan(BigDecimal.ZERO)) { + result += mContext.getString(R.string.unit_foot_short) + result += " " + result += inch.format(scale, outputFormat).formatExpression(formatterSymbols) + result += mContext.getString(R.string.unit_inch_short) + } + + return result +} diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterViewModel.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterViewModel.kt new file mode 100644 index 00000000..c8657388 --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/ConverterViewModel.kt @@ -0,0 +1,231 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2022-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import androidx.compose.ui.text.input.TextFieldValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.ui.common.textfield.getTextField +import app.myzel394.numberhub.data.common.combine +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.converter.ConverterResult +import app.myzel394.numberhub.data.converter.UnitsRepositoryImpl +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +internal class ConverterViewModel @Inject constructor( + private val userPrefsRepository: UserPreferencesRepository, + private val unitsRepo: UnitsRepositoryImpl, + private val savedStateHandle: SavedStateHandle, +) : ViewModel() { + private var conversionJob: Job? = null + + private val converterInputKey1 = "CONVERTER_INPUT_1" + private val converterInputKey2 = "CONVERTER_INPUT_2" + private val input1 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey1)) + private val input2 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey2)) + private val output = MutableStateFlow(ConverterResult.Loading) + + private val unitFromId = MutableStateFlow(null) + private val unitToId = MutableStateFlow(null) + + private val unitFrom = unitFromId + .mapLatest { it?.let { unitsRepo.getById(it) } } + .flowOn(Dispatchers.Default) + .stateIn(viewModelScope, null) + + private val unitTo = unitToId + .mapLatest { it?.let { unitsRepo.getById(it) } } + .flowOn(Dispatchers.Default) + .stateIn(viewModelScope, null) + + val converterUIState: StateFlow = combine( + input1, + input2, + output, + unitFrom, + unitTo, + userPrefsRepository.converterPrefs, + ) { input1Value, input2Value, outputValue, unitFromValue, unitToValue, prefs -> + if (unitFromValue == null) return@combine UnitConverterUIState.Loading + if (unitToValue == null) return@combine UnitConverterUIState.Loading + + whenBothAre( + value1 = unitFromValue, + value2 = unitToValue, + ) { unitFrom, unitTo -> + return@combine UnitConverterUIState.Default( + input1 = input1Value, + input2 = input2Value, + result = outputValue, + unitFrom = unitFrom, + unitTo = unitTo, + middleZero = prefs.middleZero, + formatterSymbols = prefs.formatterSymbols, + scale = prefs.precision, + outputFormat = OutputFormat.PLAIN, + formatTime = prefs.unitConverterFormatTime, + currencyRateUpdateState = CurrencyRateUpdateState.Nothing, + acButton = prefs.acButton, + ) + } + + whenBothAre( + value1 = unitFromValue, + value2 = unitToValue, + ) { unitFrom, unitTo -> + return@combine UnitConverterUIState.NumberBase( + input = input1Value, + result = outputValue, + unitFrom = unitFrom, + unitTo = unitTo, + ) + } + + return@combine UnitConverterUIState.Loading + } + .stateIn(viewModelScope, UnitConverterUIState.Loading) + + fun updateInput1(value: TextFieldValue) { + input1.update { value } + savedStateHandle[converterInputKey1] = value.text + } + + fun updateInput2(value: TextFieldValue) { + input2.update { value } + savedStateHandle[converterInputKey2] = value.text + } + + fun updateUnitFromId(id: String) = viewModelScope.launch { + val pairId = unitsRepo.getPairId(id) + + unitFromId.update { id } + unitToId.update { pairId } + + unitsRepo.incrementCounter(id) + updateLatestPairOfUnits() + } + + fun updateUnitToId(id: String) = viewModelScope.launch { + unitToId.update { id } + unitsRepo.incrementCounter(id) + setPair() + updateLatestPairOfUnits() + } + + fun swapUnits( + newUnitFromId: String, + newInputToId: String, + ) = viewModelScope.launch { + unitFromId.update { newUnitFromId } + unitToId.update { newInputToId } + setPair() + updateLatestPairOfUnits() + } + + fun convertDefault() { + conversionJob?.cancel() + conversionJob = viewModelScope.launch { + val result = unitsRepo.convertDefault( + unitFromId = unitFromId.value ?: return@launch, + unitToId = unitToId.value ?: return@launch, + value1 = input1.value.text, + value2 = input2.value.text, + formatTime = userPrefsRepository.converterPrefs.first().unitConverterFormatTime, + ) + + when (result) { + is ConverterResult.Error.BadInput -> Unit + else -> output.update { result } + } + } + } + + fun convertNumberBase() { + conversionJob?.cancel() + conversionJob = viewModelScope.launch { + unitsRepo.convertNumberBase( + unitFromId = unitFromId.value ?: return@launch, + unitToId = unitToId.value ?: return@launch, + value = input1.value.text, + ) + } + } + + private fun loadInitialUnits() = viewModelScope.launch { + val prefs = userPrefsRepository.converterPrefs.first() + unitFromId.update { prefs.latestLeftSideUnit } + unitToId.update { prefs.latestRightSideUnit } + } + + private fun setPair() = viewModelScope.launch { + unitsRepo.setPair( + id = unitFromId.value ?: return@launch, + pairId = unitToId.value ?: return@launch, + ) + } + + private fun updateLatestPairOfUnits() = viewModelScope.launch { + userPrefsRepository + .updateLatestPairOfUnits( + unitFrom = unitFromId.value ?: return@launch, + unitTo = unitToId.value ?: return@launch, + ) + } + + /** + * Will call [block] if both [value1] and [value2] are [T]. + * + * @param T What to check against. + * @param value1 Value to check. + * @param value2 Value to check. + * @param block Block that will be called if the has passed. + */ + private inline fun whenBothAre( + value1: Any?, + value2: Any?, + block: (v1: T, v2: T) -> Unit, + ) { + if ((value1 is T) and (value2 is T)) block(value1 as T, value2 as T) + } + + init { + loadInitialUnits() + } + + override fun onCleared() { + super.onCleared() + viewModelScope.cancel() + } +} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/CurrencyRateUpdateState.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/CurrencyRateUpdateState.kt similarity index 95% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/CurrencyRateUpdateState.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/CurrencyRateUpdateState.kt index ba396b5d..82a0a8df 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/CurrencyRateUpdateState.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/CurrencyRateUpdateState.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter +package app.myzel394.numberhub.feature.converter import java.time.LocalDate diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitFromSelectorScreen.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitFromSelectorScreen.kt new file mode 100644 index 00000000..90be2e13 --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitFromSelectorScreen.kt @@ -0,0 +1,169 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.SearchBar +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.converter.UnitSearchResultItem +import app.myzel394.numberhub.data.database.UnitsEntity +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import app.myzel394.numberhub.feature.converter.components.ChipsRow +import app.myzel394.numberhub.feature.converter.components.FavoritesButton +import app.myzel394.numberhub.feature.converter.components.UnitsList +import java.math.BigDecimal + +@Composable +internal fun UnitFromSelectorRoute( + unitSelectorViewModel: UnitFromSelectorViewModel, + converterViewModel: ConverterViewModel, + navigateUp: () -> Unit, + navigateToUnitGroups: () -> Unit, +) { + when ( + val uiState = unitSelectorViewModel.unitFromUIState.collectAsStateWithLifecycle().value + ) { + is UnitSelectorUIState.UnitFrom -> UnitFromSelectorScreen( + uiState = uiState, + onQueryChange = unitSelectorViewModel::updateSelectorQuery, + toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly, + updateUnitFrom = converterViewModel::updateUnitFromId, + updateUnitGroup = unitSelectorViewModel::updateSelectedUnitGroup, + favoriteUnit = unitSelectorViewModel::favoriteUnit, + navigateUp = navigateUp, + navigateToUnitGroups = navigateToUnitGroups, + ) + else -> EmptyScreen() + } +} + +@Composable +private fun UnitFromSelectorScreen( + uiState: UnitSelectorUIState.UnitFrom, + onQueryChange: (TextFieldValue) -> Unit, + toggleFavoritesOnly: (Boolean) -> Unit, + updateUnitFrom: (String) -> Unit, + updateUnitGroup: (UnitGroup?) -> Unit, + favoriteUnit: (UnitSearchResultItem) -> Unit, + navigateUp: () -> Unit, + navigateToUnitGroups: () -> Unit, +) { + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + Column( + Modifier.background(MaterialTheme.colorScheme.surface), + ) { + SearchBar( + query = uiState.query, + onQueryChange = onQueryChange, + navigateUp = navigateUp, + trailingIcon = { + FavoritesButton(uiState.showFavoritesOnly) { + toggleFavoritesOnly(!uiState.showFavoritesOnly) + } + }, + scrollBehavior = scrollBehavior, + ) + + ChipsRow( + modifier = Modifier + .padding(start = 8.dp, end = 8.dp, bottom = 4.dp) + .fillMaxWidth(), + chosenUnitGroup = uiState.selectedUnitGroup, + items = uiState.shownUnitGroups, + selectAction = updateUnitGroup, + navigateToSettingsAction = navigateToUnitGroups, + ) + } + }, + ) { paddingValues -> + val resources = LocalContext.current.resources + + UnitsList( + modifier = Modifier.padding(paddingValues), + searchResult = uiState.units, + navigateToUnitGroups = navigateToUnitGroups, + currentUnitId = uiState.unitFromId, + supportLabel = { resources.getString(it.basicUnit.shortName) }, + onClick = { + onQueryChange(TextFieldValue()) + updateUnitFrom(it.basicUnit.id) + navigateUp() + }, + favoriteUnit = { favoriteUnit(it) }, + ) + } +} + +@Preview +@Composable +private fun UnitFromSelectorScreenPreview() { + val units: Map> = mapOf( + UnitGroup.LENGTH to listOf( + NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), + NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), + NormalUnit(UnitID.nautical_mile, BigDecimal("1852000000000000000000"), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), + NormalUnit(UnitID.inch, BigDecimal("25400000000000000"), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), + NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), + NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), + NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), + ) + .map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) }, + ) + + UnitFromSelectorScreen( + uiState = UnitSelectorUIState.UnitFrom( + unitFromId = UnitID.kilometer, + query = TextFieldValue("test"), + units = units, + selectedUnitGroup = UnitGroup.SPEED, + shownUnitGroups = UnitGroup.entries, + showFavoritesOnly = false, + sorting = UnitsListSorting.USAGE, + ), + onQueryChange = {}, + toggleFavoritesOnly = {}, + updateUnitFrom = {}, + updateUnitGroup = {}, + favoriteUnit = {}, + navigateUp = {}, + navigateToUnitGroups = {}, + ) +} diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitFromSelectorViewModel.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitFromSelectorViewModel.kt new file mode 100644 index 00000000..8ced112d --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitFromSelectorViewModel.kt @@ -0,0 +1,124 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import androidx.compose.ui.text.input.TextFieldValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.converter.UnitSearchResultItem +import app.myzel394.numberhub.data.converter.UnitsRepositoryImpl +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.feature.converter.navigation.UNIT_FROM_ID_ARG +import app.myzel394.numberhub.feature.converter.navigation.UNIT_GROUP_ARG +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +internal class UnitFromSelectorViewModel @Inject constructor( + private val userPrefsRepository: UserPreferencesRepository, + private val unitsRepo: UnitsRepositoryImpl, + savedStateHandle: SavedStateHandle, +) : ViewModel() { + private var searchJob: Job? = null + + private val query = MutableStateFlow(TextFieldValue()) + private val searchResults = MutableStateFlow>?>(null) + private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get(UNIT_GROUP_ARG)) + private val unitFromId = savedStateHandle.get(UNIT_FROM_ID_ARG) + + val unitFromUIState: StateFlow = combine( + query, + searchResults, + selectedUnitGroup, + userPrefsRepository.converterPrefs, + ) { query, searchResults, selectedUnitGroup, prefs -> + if (searchResults == null) return@combine UnitSelectorUIState.Loading + + return@combine UnitSelectorUIState.UnitFrom( + query = query, + unitFromId = unitFromId ?: "", + shownUnitGroups = prefs.shownUnitGroups, + showFavoritesOnly = prefs.unitConverterFavoritesOnly, + units = searchResults, + selectedUnitGroup = selectedUnitGroup, + sorting = prefs.unitConverterSorting, + ) + } + .stateIn(viewModelScope, UnitSelectorUIState.Loading) + + fun updateSelectorQuery(value: TextFieldValue) { + query.update { value } + onSearch() + } + + fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch { + userPrefsRepository.updateUnitConverterFavoritesOnly(value) + onSearch() + } + + fun updateSelectedUnitGroup(value: UnitGroup?) { + selectedUnitGroup.update { value } + onSearch() + } + + fun favoriteUnit(unit: UnitSearchResultItem) = viewModelScope.launch { + unitsRepo.favorite(unit.basicUnit.id) + onSearch() + } + + private fun onSearch() { + searchJob?.cancel() + searchJob = viewModelScope.launch { + val prefs = userPrefsRepository.converterPrefs.first() + val selectedGroupValue = selectedUnitGroup.value + val result = unitsRepo.filterUnits( + query = query.value.text, + favoritesOnly = prefs.unitConverterFavoritesOnly, + sorting = prefs.unitConverterSorting, + unitGroups = if (selectedGroupValue == null) { + prefs.shownUnitGroups + } else { + listOf(selectedGroupValue) + }, + ) + + searchResults.update { result } + } + } + + init { + onSearch() + } + + override fun onCleared() { + super.onCleared() + viewModelScope.cancel() + } +} diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitSelectorUIState.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitSelectorUIState.kt new file mode 100644 index 00000000..f86daf6a --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitSelectorUIState.kt @@ -0,0 +1,53 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import androidx.compose.ui.text.input.TextFieldValue +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.data.converter.UnitSearchResultItem +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.converter.unit.BasicUnit + +internal sealed class UnitSelectorUIState { + data object Loading : UnitSelectorUIState() + + data class UnitFrom( + val query: TextFieldValue, + val unitFromId: String, + val shownUnitGroups: List, + val showFavoritesOnly: Boolean, + val units: Map>, + val selectedUnitGroup: UnitGroup?, + val sorting: UnitsListSorting, + ) : UnitSelectorUIState() + + data class UnitTo( + val query: TextFieldValue, + val unitFrom: BasicUnit, + val unitTo: BasicUnit, + val showFavoritesOnly: Boolean, + val units: Map>, + val input: String?, + val sorting: UnitsListSorting, + val scale: Int, + val outputFormat: Int, + val formatterSymbols: FormatterSymbols, + ) : UnitSelectorUIState() +} diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitToSelectorScreen.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitToSelectorScreen.kt new file mode 100644 index 00000000..1acfcba4 --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitToSelectorScreen.kt @@ -0,0 +1,171 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.tooling.preview.Preview +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.SearchBar +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.data.converter.DefaultBatchConvertResult +import app.myzel394.numberhub.data.converter.NumberBaseBatchConvertResult +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.converter.UnitSearchResultItem +import app.myzel394.numberhub.data.database.UnitsEntity +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import app.myzel394.numberhub.feature.converter.components.FavoritesButton +import app.myzel394.numberhub.feature.converter.components.UnitsList +import java.math.BigDecimal + +@Composable +internal fun UnitToSelectorRoute( + unitSelectorViewModel: UnitToSelectorViewModel, + converterViewModel: ConverterViewModel, + navigateUp: () -> Unit, + navigateToUnitGroups: () -> Unit, +) { + when ( + val uiState = unitSelectorViewModel.unitToUIState.collectAsStateWithLifecycle().value + ) { + is UnitSelectorUIState.UnitTo -> UnitToSelectorScreen( + uiState = uiState, + onQueryChange = unitSelectorViewModel::updateSelectorQuery, + toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly, + updateUnitTo = converterViewModel::updateUnitToId, + favoriteUnit = unitSelectorViewModel::favoriteUnit, + navigateUp = navigateUp, + navigateToUnitGroups = navigateToUnitGroups, + ) + else -> EmptyScreen() + } +} + +@Composable +private fun UnitToSelectorScreen( + uiState: UnitSelectorUIState.UnitTo, + onQueryChange: (TextFieldValue) -> Unit, + toggleFavoritesOnly: (Boolean) -> Unit, + updateUnitTo: (String) -> Unit, + favoriteUnit: (UnitSearchResultItem) -> Unit, + navigateUp: () -> Unit, + navigateToUnitGroups: () -> Unit, +) { + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + SearchBar( + query = uiState.query, + onQueryChange = onQueryChange, + navigateUp = navigateUp, + trailingIcon = { + FavoritesButton(uiState.showFavoritesOnly) { + toggleFavoritesOnly(!uiState.showFavoritesOnly) + } + }, + scrollBehavior = scrollBehavior, + ) + }, + ) { paddingValues -> + val resources = LocalContext.current.resources + UnitsList( + modifier = Modifier.padding(paddingValues), + searchResult = uiState.units, + navigateToUnitGroups = navigateToUnitGroups, + currentUnitId = uiState.unitTo.id, + supportLabel = { + val label = resources.getString(it.basicUnit.shortName) + + when (val conversion = it.conversion) { + is DefaultBatchConvertResult -> { + val formattedConversion = conversion.value + .format(uiState.scale, uiState.outputFormat) + .formatExpression(uiState.formatterSymbols) + + "$formattedConversion $label" + } + is NumberBaseBatchConvertResult -> { + "${conversion.value} $label" + } + else -> label + } + }, + onClick = { + onQueryChange(TextFieldValue()) + updateUnitTo(it.basicUnit.id) + navigateUp() + }, + favoriteUnit = { favoriteUnit(it) }, + ) + } +} + +@Preview +@Composable +private fun UnitToSelectorPreview() { + val units: Map> = mapOf( + UnitGroup.LENGTH to listOf( + NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), + NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), + NormalUnit(UnitID.nautical_mile, BigDecimal("1852000000000000000000"), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), + NormalUnit(UnitID.inch, BigDecimal("25400000000000000"), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), + NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), + NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), + NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), + ) + .map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) }, + ) + + UnitToSelectorScreen( + uiState = UnitSelectorUIState.UnitTo( + unitFrom = units.values.first().first().basicUnit, + unitTo = units.values.first().first().basicUnit, + query = TextFieldValue("test"), + units = units, + showFavoritesOnly = false, + sorting = UnitsListSorting.USAGE, + input = "100", + scale = 3, + outputFormat = OutputFormat.PLAIN, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), + ), + onQueryChange = {}, + toggleFavoritesOnly = {}, + updateUnitTo = {}, + favoriteUnit = {}, + navigateUp = {}, + navigateToUnitGroups = {}, + ) +} diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitToSelectorViewModel.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitToSelectorViewModel.kt new file mode 100644 index 00000000..26e454fc --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/UnitToSelectorViewModel.kt @@ -0,0 +1,124 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter + +import androidx.compose.ui.text.input.TextFieldValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.converter.UnitSearchResultItem +import app.myzel394.numberhub.data.converter.UnitsRepositoryImpl +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.feature.converter.navigation.INPUT_ARG +import app.myzel394.numberhub.feature.converter.navigation.UNIT_FROM_ID_ARG +import app.myzel394.numberhub.feature.converter.navigation.UNIT_GROUP_ARG +import app.myzel394.numberhub.feature.converter.navigation.UNIT_TO_ID_ARG +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +internal class UnitToSelectorViewModel @Inject constructor( + private val userPrefsRepository: UserPreferencesRepository, + private val unitsRepo: UnitsRepositoryImpl, + savedStateHandle: SavedStateHandle, +) : ViewModel() { + private var searchJob: Job? = null + + private val query = MutableStateFlow(TextFieldValue()) + private val searchResults = MutableStateFlow>?>(null) + private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get(UNIT_GROUP_ARG)) + private val unitFromId = savedStateHandle.get(UNIT_FROM_ID_ARG) + private val unitToId = savedStateHandle.get(UNIT_TO_ID_ARG) + private val input = savedStateHandle.get(INPUT_ARG) + + val unitToUIState: StateFlow = combine( + query, + searchResults, + userPrefsRepository.converterPrefs, + ) { query, searchResults, prefs -> + if (unitFromId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading + if (unitToId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading + if (searchResults == null) return@combine UnitSelectorUIState.Loading + + UnitSelectorUIState.UnitTo( + query = query, + unitFrom = unitsRepo.getById(unitFromId), + unitTo = unitsRepo.getById(unitToId), + showFavoritesOnly = prefs.unitConverterFavoritesOnly, + units = searchResults, + input = input, + sorting = prefs.unitConverterSorting, + scale = prefs.precision, + outputFormat = prefs.outputFormat, + formatterSymbols = prefs.formatterSymbols, + ) + } + .stateIn(viewModelScope, UnitSelectorUIState.Loading) + + fun updateSelectorQuery(value: TextFieldValue) { + query.update { value } + onSearch() + } + + fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch { + userPrefsRepository.updateUnitConverterFavoritesOnly(value) + onSearch() + } + + fun favoriteUnit(unit: UnitSearchResultItem) = viewModelScope.launch { + unitsRepo.favorite(unit.basicUnit.id) + onSearch() + } + + private fun onSearch() { + searchJob?.cancel() + searchJob = viewModelScope.launch { + val prefs = userPrefsRepository.converterPrefs.first() + val result = unitsRepo.filterUnitsAndBatchConvert( + query = query.value.text, + unitGroup = selectedUnitGroup.value ?: return@launch, + favoritesOnly = prefs.unitConverterFavoritesOnly, + sorting = prefs.unitConverterSorting, + unitFromId = unitFromId ?: return@launch, + input = input, + ) + + searchResults.update { result } + } + } + + init { + onSearch() + } + + override fun onCleared() { + super.onCleared() + viewModelScope.cancel() + } +} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/BasicUnitListItem.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/BasicUnitListItem.kt similarity index 89% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/BasicUnitListItem.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/BasicUnitListItem.kt index 913cc0a7..26e4fab5 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/BasicUnitListItem.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/BasicUnitListItem.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter.components +package app.myzel394.numberhub.feature.converter.components import androidx.compose.animation.AnimatedContent import androidx.compose.animation.SizeTransform @@ -49,7 +49,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R @Composable internal fun BasicUnitListItem( @@ -69,23 +69,23 @@ internal fun BasicUnitListItem( .clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(), - onClick = onClick + onClick = onClick, ) - .padding(horizontal = 12.dp) + .padding(horizontal = 12.dp), ) { Row( modifier = Modifier .background( if (isSelected) MaterialTheme.colorScheme.primaryContainer else Color.Transparent, - RoundedCornerShape(24.dp) + RoundedCornerShape(24.dp), ) .padding(paddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp)) .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { Column( - Modifier.weight(1f), // This makes additional composable to be seen + Modifier.weight(1f), ) { Text( modifier = Modifier @@ -102,7 +102,7 @@ internal fun BasicUnitListItem( style = MaterialTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = itemColor + color = itemColor, ) } AnimatedContent( @@ -110,18 +110,18 @@ internal fun BasicUnitListItem( .clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(false), - onClick = favoriteUnit + onClick = favoriteUnit, ), targetState = isFavorite, transitionSpec = { (scaleIn() togetherWith scaleOut()).using(SizeTransform(clip = false)) }, - label = "Favorite unit" + label = "Favorite unit", ) { Icon( imageVector = if (it) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder, contentDescription = stringResource(R.string.converter_favorite_button_description), - tint = itemColor + tint = itemColor, ) } } diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/ChipsRow.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/ChipsRow.kt new file mode 100644 index 00000000..6a618106 --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/ChipsRow.kt @@ -0,0 +1,242 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2022-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter.components + +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.animation.togetherWith +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ExpandLess +import androidx.compose.material.icons.filled.ExpandMore +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.Placeable +import androidx.compose.ui.layout.SubcomposeLayout +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.AssistChip +import app.myzel394.numberhub.core.ui.common.FilterChip +import app.myzel394.numberhub.data.model.converter.UnitGroup + +/** + * Row of chips with [UnitGroup]s. Temporary solution + * + * @param items All [UnitGroup]s + * @param chosenUnitGroup Currently selected [UnitGroup] + * @param selectAction Action to perform when a chip is clicked + * @param navigateToSettingsAction Action to perform when clicking settings chip at the end + */ +@Composable +internal fun ChipsRow( + modifier: Modifier, + items: List, + chosenUnitGroup: UnitGroup?, + selectAction: (UnitGroup?) -> Unit, + navigateToSettingsAction: () -> Unit, +) { + var expanded by remember { mutableStateOf(false) } + val chipModifier = Modifier.padding(horizontal = 4.dp) + + AnimatedContent( + targetState = expanded, + transitionSpec = { + expandVertically(expandFrom = Alignment.Top) { it } + fadeIn() togetherWith + shrinkVertically(shrinkTowards = Alignment.Top) { it } + fadeOut() + }, + label = "Expand chips row", + ) { isExpanded -> + FlexRow( + modifier = modifier, + maxRows = if (isExpanded) Int.MAX_VALUE else 2, + mainContent = { + items.forEach { item -> + val selected: Boolean = item == chosenUnitGroup + FilterChip( + modifier = chipModifier, + isSelected = selected, + onClick = { + selectAction(if (selected) null else item) + expanded = false + }, + label = stringResource(item.res), + ) + } + + AssistChip( + modifier = chipModifier, + onClick = navigateToSettingsAction, + imageVector = Icons.Default.Settings, + contentDescription = stringResource(R.string.open_settings_label), + ) + + if (expanded) { + AssistChip( + modifier = chipModifier, + onClick = { expanded = false }, + imageVector = Icons.Default.ExpandLess, + // TODO + contentDescription = "", + ) + } + }, + expandContent = { + AssistChip( + modifier = chipModifier, + onClick = { expanded = true }, + imageVector = Icons.Default.ExpandMore, + // TODO + contentDescription = "", + ) + }, + ) + } +} + +/** + * Foldable row that places a specified element if overflown. + * + * @param modifier [Modifier] to be applied to this layout. + * @param maxRows Max amount of rows including with [expandContent]. + * @param mainContent Main content (list of items) that will be folded. + * @param expandContent Item that will be placed at the end if given [maxRows] wasn't high enough to + * place all [mainContent] items. + */ +@Composable +private fun FlexRow( + modifier: Modifier = Modifier, + maxRows: Int = Int.MAX_VALUE, + mainContent: @Composable () -> Unit, + expandContent: @Composable () -> Unit, +) { + SubcomposeLayout( + modifier = modifier, + ) { constraints -> + val localConstraints = constraints.copy(minWidth = 0, minHeight = 0) + val layoutWidth = localConstraints.maxWidth + + val mainMeasurables = subcompose(FlexRowSlots.Main, mainContent) + val expandMeasurables = subcompose( + slotId = FlexRowSlots.Expand, + content = { expandContent() }, + ).map { + it.measure(localConstraints) + } + val expandContentWidth = expandMeasurables.sumOf { it.measuredWidth } + + val placeables = mutableListOf>(mutableListOf()) + + var widthLeft = layoutWidth + var index = 0 + for (measurable in mainMeasurables) { + val mainPlaceable = measurable.measure(localConstraints) + + val lastAvailableRow = placeables.size >= maxRows + val notLastItem = index < mainMeasurables.lastIndex + + // count expandContent width only for last row and not last main placeable + val measuredWidth = if (lastAvailableRow and notLastItem) { + mainPlaceable.measuredWidth + expandContentWidth + } else { + mainPlaceable.measuredWidth + } + + // need new row + if (widthLeft <= measuredWidth) { + // Can't add more rows, add expandContent + if (lastAvailableRow) { + expandMeasurables.forEach { + placeables.last().add(it) + } + break + } + + placeables.add(mutableListOf()) + widthLeft = layoutWidth + } + placeables.last().add(mainPlaceable) + index++ + widthLeft -= mainPlaceable.measuredWidth + } + + val flattenPlaceables = placeables.flatten() + val layoutHeight = placeables.size * (flattenPlaceables.maxByOrNull { it.height }?.height ?: 0) + + layout(layoutWidth, layoutHeight) { + var yPos = 0 + placeables.forEach { row -> + var xPos = 0 + row.forEach { placeable -> + placeable.place(x = xPos, y = yPos) + xPos += placeable.width + } + yPos += row.maxByOrNull { it.height }?.height ?: 0 + } + } + } +} + +private enum class FlexRowSlots { Main, Expand } + +@Preview(device = "spec:width=380dp,height=850.9dp,dpi=440") +@Composable +fun PreviewUnittoChips() { + var selected by remember { mutableStateOf(UnitGroup.LENGTH) } + + fun selectAction(unitGroup: UnitGroup?) { + selected = unitGroup + } + + Column { + ChipsRow( + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + .fillMaxWidth(), + items = UnitGroup.entries.take(7), + chosenUnitGroup = selected, + selectAction = { selectAction(it) }, + navigateToSettingsAction = {}, + ) + + ChipsRow( + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + .fillMaxWidth(), + items = UnitGroup.entries.take(10), + chosenUnitGroup = selected, + selectAction = { selectAction(it) }, + navigateToSettingsAction = {}, + ) + } +} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/ConverterKeyboard.kt similarity index 72% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/ConverterKeyboard.kt index f1b0f51d..3a1ab001 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ConverterKeyboard.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/ConverterKeyboard.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter.components +package app.myzel394.numberhub.feature.converter.components import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize @@ -26,47 +26,45 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.LocalWindowSize -import com.sadellie.unitto.core.ui.WindowHeightSizeClass -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightShort -import com.sadellie.unitto.core.ui.common.KeyboardButtonContentHeightTall -import com.sadellie.unitto.core.ui.common.KeyboardButtonFilled -import com.sadellie.unitto.core.ui.common.KeyboardButtonLight -import com.sadellie.unitto.core.ui.common.KeyboardButtonTertiary -import com.sadellie.unitto.core.ui.common.KeypadFlow -import com.sadellie.unitto.core.ui.common.icons.IconPack -import com.sadellie.unitto.core.ui.common.icons.iconpack.Backspace -import com.sadellie.unitto.core.ui.common.icons.iconpack.Brackets -import com.sadellie.unitto.core.ui.common.icons.iconpack.Clear -import com.sadellie.unitto.core.ui.common.icons.iconpack.Comma -import com.sadellie.unitto.core.ui.common.icons.iconpack.Divide -import com.sadellie.unitto.core.ui.common.icons.iconpack.Dot -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key0 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key1 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key2 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key3 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key4 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key5 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key6 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key7 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key8 -import com.sadellie.unitto.core.ui.common.icons.iconpack.Key9 -import com.sadellie.unitto.core.ui.common.icons.iconpack.KeyA -import com.sadellie.unitto.core.ui.common.icons.iconpack.KeyB -import com.sadellie.unitto.core.ui.common.icons.iconpack.KeyC -import com.sadellie.unitto.core.ui.common.icons.iconpack.KeyD -import com.sadellie.unitto.core.ui.common.icons.iconpack.KeyE -import com.sadellie.unitto.core.ui.common.icons.iconpack.KeyF -import com.sadellie.unitto.core.ui.common.icons.iconpack.LeftBracket -import com.sadellie.unitto.core.ui.common.icons.iconpack.Minus -import com.sadellie.unitto.core.ui.common.icons.iconpack.Multiply -import com.sadellie.unitto.core.ui.common.icons.iconpack.Plus -import com.sadellie.unitto.core.ui.common.icons.iconpack.Power -import com.sadellie.unitto.core.ui.common.icons.iconpack.RightBracket -import com.sadellie.unitto.core.ui.common.icons.iconpack.Root -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowHeightSizeClass +import app.myzel394.numberhub.core.ui.common.KeyboardButtonFilled +import app.myzel394.numberhub.core.ui.common.KeyboardButtonLight +import app.myzel394.numberhub.core.ui.common.KeyboardButtonTertiary +import app.myzel394.numberhub.core.ui.common.KeyboardButtonToken +import app.myzel394.numberhub.core.ui.common.KeypadFlow +import app.myzel394.numberhub.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Backspace +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Brackets +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Clear +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Comma +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Divide +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Dot +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key0 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key1 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key2 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key3 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key4 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key5 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key6 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key7 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key8 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Key9 +import app.myzel394.numberhub.core.ui.common.icons.iconpack.KeyA +import app.myzel394.numberhub.core.ui.common.icons.iconpack.KeyB +import app.myzel394.numberhub.core.ui.common.icons.iconpack.KeyC +import app.myzel394.numberhub.core.ui.common.icons.iconpack.KeyD +import app.myzel394.numberhub.core.ui.common.icons.iconpack.KeyE +import app.myzel394.numberhub.core.ui.common.icons.iconpack.KeyF +import app.myzel394.numberhub.core.ui.common.icons.iconpack.LeftBracket +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Minus +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Multiply +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Plus +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Power +import app.myzel394.numberhub.core.ui.common.icons.iconpack.RightBracket +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Root @Composable internal fun DefaultKeyboard( @@ -79,14 +77,14 @@ internal fun DefaultKeyboard( acButton: Boolean, addBracket: () -> Unit, ) { - val fractionalIcon = remember(fractional) { if (fractional == Token.Digit.dot) IconPack.Dot else IconPack.Comma } - val fractionalIconDescription = remember(fractional) { if (fractional == Token.Digit.dot) R.string.keyboard_dot else R.string.comma } - val contentHeight: Float = if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonContentHeightShort else KeyboardButtonContentHeightTall + val fractionalIcon = remember(fractional) { if (fractional == Token.PERIOD) IconPack.Dot else IconPack.Comma } + val fractionalIconDescription = remember(fractional) { if (fractional == Token.PERIOD) R.string.keyboard_dot else R.string.comma } + val contentHeight: Float = if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonToken.CONTENT_HEIGHT_SHORT else KeyboardButtonToken.CONTENT_HEIGHT_TALL KeypadFlow( modifier = modifier, rows = 5, - columns = 4 + columns = 4, ) { width, height -> val bModifier = Modifier.fillMaxWidth(width).fillMaxHeight(height) @@ -134,12 +132,12 @@ internal fun NumberBaseKeyboard( clearInput: () -> Unit, deleteDigit: () -> Unit, ) { - val contentHeight: Float = if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonContentHeightShort else KeyboardButtonContentHeightTall + val contentHeight: Float = if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonToken.CONTENT_HEIGHT_SHORT else KeyboardButtonToken.CONTENT_HEIGHT_TALL KeypadFlow( modifier = modifier, rows = 6, - columns = 3 + columns = 3, ) { width, height -> val bModifier = Modifier.fillMaxWidth(width).fillMaxHeight(height) val wideButtonModifier = Modifier.fillMaxHeight(height).fillMaxWidth(width * 2) @@ -178,10 +176,10 @@ private fun PreviewConverterKeyboard() { addDigit = {}, clearInput = {}, deleteDigit = {}, - fractional = FormatterSymbols.Spaces.fractional, + fractional = Token.PERIOD, middleZero = false, acButton = true, - addBracket = {} + addBracket = {}, ) } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/FavoritesButton.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/FavoritesButton.kt similarity index 86% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/FavoritesButton.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/FavoritesButton.kt index bcd9745d..a1494556 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/FavoritesButton.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/FavoritesButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter.components +package app.myzel394.numberhub.feature.converter.components import androidx.compose.animation.AnimatedContent import androidx.compose.animation.SizeTransform @@ -29,13 +29,13 @@ import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.SearchBarIconButton +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.SearchBarIconButton @Composable internal fun FavoritesButton( state: Boolean, - onClick: () -> Unit + onClick: () -> Unit, ) { SearchBarIconButton(onClick = onClick) { AnimatedContent( @@ -43,11 +43,11 @@ internal fun FavoritesButton( transitionSpec = { (scaleIn() togetherWith scaleOut()).using(SizeTransform(clip = false)) }, - label = "Animated click" + label = "Animated click", ) { Icon( if (it) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder, - contentDescription = stringResource(R.string.converter_favorite_button_description) + contentDescription = stringResource(R.string.converter_favorite_button_description), ) } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitGroupHeader.kt similarity index 85% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitGroupHeader.kt index dc0c5fb9..04ca0669 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitGroupHeader.kt @@ -16,21 +16,21 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter.components +package app.myzel394.numberhub.feature.converter.components import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.Header -import com.sadellie.unitto.data.model.UnitGroup +import app.myzel394.numberhub.core.ui.common.Header +import app.myzel394.numberhub.data.model.converter.UnitGroup @Composable internal fun UnitGroupHeader(modifier: Modifier, unitGroup: UnitGroup) { Header( text = stringResource(unitGroup.res), modifier = modifier, - paddingValues = PaddingValues(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp) + paddingValues = PaddingValues(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp), ) } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitSelectionButton.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitSelectionButton.kt similarity index 87% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitSelectionButton.kt rename to feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitSelectionButton.kt index d163254f..9f9bb5a8 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitSelectionButton.kt +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitSelectionButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.converter.components +package app.myzel394.numberhub.feature.converter.components import android.annotation.SuppressLint import androidx.compose.animation.AnimatedContent @@ -34,7 +34,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.Button +import app.myzel394.numberhub.core.ui.common.Button /** * Button to select a unit @@ -49,7 +49,7 @@ internal fun UnitSelectionButton( modifier: Modifier = Modifier, onClick: () -> Unit = {}, label: String, - enabled: Boolean = true + enabled: Boolean = true, ) { Button( modifier = modifier, @@ -63,21 +63,21 @@ internal fun UnitSelectionButton( transitionSpec = { if (targetState > initialState) { (slideInVertically { height -> height } + fadeIn()) togetherWith - slideOutVertically { height -> -height } + fadeOut() + slideOutVertically { height -> -height } + fadeOut() } else { (slideInVertically { height -> -height } + fadeIn()) togetherWith - slideOutVertically { height -> height } + fadeOut() + slideOutVertically { height -> height } + fadeOut() }.using( - SizeTransform(clip = false) + SizeTransform(clip = false), ) }, - label = "Unit change" + label = "Unit change", ) { Text( text = it, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = MaterialTheme.colorScheme.onPrimaryContainer + color = MaterialTheme.colorScheme.onPrimaryContainer, ) } } diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitsList.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitsList.kt new file mode 100644 index 00000000..39c7e39d --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/components/UnitsList.kt @@ -0,0 +1,113 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter.components + +import androidx.compose.animation.Crossfade +import androidx.compose.animation.core.tween +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.SearchPlaceholder +import app.myzel394.numberhub.data.converter.UnitID +import app.myzel394.numberhub.data.converter.UnitSearchResultItem +import app.myzel394.numberhub.data.database.UnitsEntity +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.unit.NormalUnit +import java.math.BigDecimal + +@Composable +internal fun UnitsList( + modifier: Modifier, + searchResult: Map>, + navigateToUnitGroups: () -> Unit, + currentUnitId: String, + supportLabel: (UnitSearchResultItem) -> String, + onClick: (UnitSearchResultItem) -> Unit, + favoriteUnit: (UnitSearchResultItem) -> Unit, +) { + Crossfade( + modifier = modifier, + targetState = searchResult, + label = "Units list", + animationSpec = tween(200), + ) { result -> + when { + result.isEmpty() -> SearchPlaceholder( + onButtonClick = navigateToUnitGroups, + supportText = stringResource(R.string.converter_no_results_support), + buttonLabel = stringResource(R.string.open_settings_label), + ) + else -> LazyColumn( + modifier = Modifier.fillMaxSize(), + ) { + result.forEach { (group, units) -> + item(group.name) { + UnitGroupHeader(Modifier.animateItemPlacement(), group) + } + + items(units, { it.basicUnit.id }) { + BasicUnitListItem( + modifier = Modifier.animateItemPlacement(), + name = stringResource(it.basicUnit.displayName), + supportLabel = supportLabel(it), + isFavorite = it.stats.isFavorite, + isSelected = it.basicUnit.id == currentUnitId, + onClick = { onClick(it) }, + favoriteUnit = { favoriteUnit(it) }, + ) + } + } + } + } + } +} + +@Preview +@Composable +private fun PreviewUnitsList() { + val resources = LocalContext.current.resources + val units: Map> = mapOf( + UnitGroup.LENGTH to listOf( + NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), + NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), + NormalUnit(UnitID.nautical_mile, BigDecimal("1852000000000000000000"), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), + NormalUnit(UnitID.inch, BigDecimal("25400000000000000"), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), + NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), + NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), + NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), + ) + .map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) }, + ) + + UnitsList( + modifier = Modifier.fillMaxSize(), + searchResult = units, + navigateToUnitGroups = {}, + currentUnitId = UnitID.mile, + supportLabel = { resources.getString(it.basicUnit.shortName) }, + onClick = {}, + favoriteUnit = {}, + ) +} diff --git a/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/navigation/ConverterNavigation.kt b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/navigation/ConverterNavigation.kt new file mode 100644 index 00000000..cda3ae1f --- /dev/null +++ b/feature/converter/src/main/java/app/myzel394/numberhub/feature/converter/navigation/ConverterNavigation.kt @@ -0,0 +1,146 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.converter.navigation + +import androidx.compose.runtime.remember +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.navArgument +import androidx.navigation.navDeepLink +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.unittoComposable +import app.myzel394.numberhub.core.ui.unittoNavigation +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.feature.converter.ConverterRoute +import app.myzel394.numberhub.feature.converter.ConverterViewModel +import app.myzel394.numberhub.feature.converter.UnitFromSelectorRoute +import app.myzel394.numberhub.feature.converter.UnitToSelectorRoute + +private val graph = DrawerItem.Converter.graph +private val start = DrawerItem.Converter.start + +private const val UNIT_FROM = "unitFromSelector" +private const val UNIT_TO = "unitToSelector" +internal const val UNIT_GROUP_ARG = "unitGroupArg" +internal const val UNIT_FROM_ID_ARG = "unitFromIdArg" +internal const val UNIT_TO_ID_ARG = "unitToIdArg" +internal const val INPUT_ARG = "inputArg" + +private const val UNIT_FROM_ROUTE = "$UNIT_FROM/{$UNIT_FROM_ID_ARG}/{$UNIT_GROUP_ARG}" +private const val UNIT_TO_ROUTE = "$UNIT_TO/{$UNIT_FROM_ID_ARG}/{$UNIT_TO_ID_ARG}/{$UNIT_GROUP_ARG}/{$INPUT_ARG}" +private fun NavHostController.navigateLeft( + unitFromId: String, + unitGroup: UnitGroup, +) = navigate("$UNIT_FROM/$unitFromId/$unitGroup") + +private fun NavHostController.navigateRight( + unitFromId: String, + unitToId: String, + unitGroup: UnitGroup, + input: String, +) = navigate("$UNIT_TO/$unitFromId/$unitToId/$unitGroup/${input.ifEmpty { null }}") + +fun NavGraphBuilder.converterGraph( + openDrawer: () -> Unit, + navController: NavHostController, + navigateToUnitGroups: () -> Unit, +) { + unittoNavigation( + startDestination = start, + route = graph, + deepLinks = listOf( + navDeepLink { uriPattern = "app://app.myzel394.numberhub/$graph" }, + ), + ) { + unittoComposable(start) { backStackEntry -> + val parentEntry = remember(backStackEntry) { + navController.getBackStackEntry(graph) + } + + val parentViewModel = hiltViewModel(parentEntry) + + ConverterRoute( + viewModel = parentViewModel, + navigateToLeftScreen = navController::navigateLeft, + navigateToRightScreen = navController::navigateRight, + openDrawer = openDrawer, + ) + } + + unittoComposable( + route = UNIT_FROM_ROUTE, + arguments = listOf( + navArgument(UNIT_FROM_ID_ARG) { + type = NavType.StringType + }, + navArgument(UNIT_GROUP_ARG) { + type = NavType.EnumType(UnitGroup::class.java) + }, + ), + ) { backStackEntry -> + val parentEntry = remember(backStackEntry) { + navController.getBackStackEntry(graph) + } + + val parentViewModel = hiltViewModel(parentEntry) + + UnitFromSelectorRoute( + unitSelectorViewModel = hiltViewModel(), + converterViewModel = parentViewModel, + navigateUp = navController::navigateUp, + navigateToUnitGroups = navigateToUnitGroups, + ) + } + + unittoComposable( + route = UNIT_TO_ROUTE, + arguments = listOf( + navArgument(UNIT_FROM_ID_ARG) { + type = NavType.StringType + }, + navArgument(UNIT_TO_ID_ARG) { + type = NavType.StringType + }, + navArgument(UNIT_GROUP_ARG) { + type = NavType.EnumType(UnitGroup::class.java) + }, + navArgument(INPUT_ARG) { + type = NavType.StringType + nullable = true + defaultValue = null + }, + ), + ) { backStackEntry -> + val parentEntry = remember(backStackEntry) { + navController.getBackStackEntry(graph) + } + + val parentViewModel = hiltViewModel(parentEntry) + + UnitToSelectorRoute( + unitSelectorViewModel = hiltViewModel(), + converterViewModel = parentViewModel, + navigateUp = navController::navigateUp, + navigateToUnitGroups = navigateToUnitGroups, + ) + } + } +} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt deleted file mode 100644 index 47fc4eb4..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2022-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import android.content.Context -import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.common.isEqualTo -import com.sadellie.unitto.data.common.isGreaterThan -import com.sadellie.unitto.data.common.isLessThan -import com.sadellie.unitto.data.common.trimZeros -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import java.math.BigDecimal -import java.math.RoundingMode - -internal sealed class UnitConverterUIState { - data object Loading : UnitConverterUIState() - - data class Default( - val input1: TextFieldValue, - val input2: TextFieldValue, - val calculation: BigDecimal?, - val result: ConverterResult, - val unitFrom: DefaultUnit, - val unitTo: DefaultUnit, - val middleZero: Boolean, - val formatterSymbols: FormatterSymbols, - val scale: Int, - val outputFormat: Int, - val formatTime: Boolean, - val currencyRateUpdateState: CurrencyRateUpdateState, - val acButton: Boolean, - ) : UnitConverterUIState() - - data class NumberBase( - val input: TextFieldValue, - val result: ConverterResult, - val unitFrom: NumberBaseUnit, - val unitTo: NumberBaseUnit, - ) : UnitConverterUIState() -} - -internal sealed class ConverterResult { - data class Default(val value: BigDecimal) : ConverterResult() { - override fun equals(other: Any?): Boolean { - if (other !is Default) return false - return this.value.isEqualTo(other.value) - } - - override fun hashCode(): Int = value.hashCode() - } - - data class NumberBase(val value: String) : ConverterResult() - - data class Time( - val negative: Boolean, - val day: BigDecimal, - val hour: BigDecimal, - val minute: BigDecimal, - val second: BigDecimal, - val millisecond: BigDecimal, - val microsecond: BigDecimal, - val nanosecond: BigDecimal, - val attosecond: BigDecimal, - ) : ConverterResult() - - data class FootInch( - val foot: BigDecimal, - val inch: BigDecimal, - ) : ConverterResult() - - data object Loading : ConverterResult() - - data object Error : ConverterResult() -} - -internal fun ConverterResult.Time.format( - mContext: Context, - formatterSymbols: FormatterSymbols -): String { - val result = mutableListOf() - - if (day.isGreaterThan(BigDecimal.ZERO)) { - result += "${day.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_day_short)}" - } - - if (hour.isGreaterThan(BigDecimal.ZERO)) { - result += "${hour.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_hour_short)}" - } - - if (minute.isGreaterThan(BigDecimal.ZERO)) { - result += "${minute.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_minute_short)}" - } - - if (second.isGreaterThan(BigDecimal.ZERO)) { - result += "${second.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_second_short)}" - } - - if (millisecond.isGreaterThan(BigDecimal.ZERO)) { - result += "${millisecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_millisecond_short)}" - } - - if (microsecond.isGreaterThan(BigDecimal.ZERO)) { - result += "${microsecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_microsecond_short)}" - } - - if (nanosecond.isGreaterThan(BigDecimal.ZERO)) { - result += "${nanosecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_nanosecond_short)}" - } - - if (attosecond.isGreaterThan(BigDecimal.ZERO)) { - result += "${attosecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_attosecond_short)}" - } - - return (if (negative) Token.Operator.minus else "") + result.joinToString(" ").ifEmpty { Token.Digit._0 } -} - -internal fun ConverterResult.FootInch.format( - mContext: Context, - scale: Int, - outputFormat: Int, - formatterSymbols: FormatterSymbols -): String { - var result = "" - result += foot.format(scale, outputFormat).formatExpression(formatterSymbols) - - if (inch.isGreaterThan(BigDecimal.ZERO)) { - result += mContext.getString(R.string.unit_foot_short) - result += " " - result += inch.format(scale, outputFormat).formatExpression(formatterSymbols) - result += mContext.getString(R.string.unit_inch_short) - } - - return result -} - -internal fun formatTime( - input: BigDecimal, -): ConverterResult.Time { - val negative = input < BigDecimal.ZERO - val inputAbs = input.abs() - - if (inputAbs.isLessThan(attosecondBasicUnit)) return ConverterResult.Time( - negative = negative, - day = BigDecimal.ZERO, - hour = BigDecimal.ZERO, - minute = BigDecimal.ZERO, - second = BigDecimal.ZERO, - millisecond = BigDecimal.ZERO, - microsecond = BigDecimal.ZERO, - nanosecond = BigDecimal.ZERO, - attosecond = inputAbs - ) - - if (inputAbs.isLessThan(nanosecondBasicUnit)) return ConverterResult.Time( - negative = negative, - day = BigDecimal.ZERO, - hour = BigDecimal.ZERO, - minute = BigDecimal.ZERO, - second = BigDecimal.ZERO, - millisecond = BigDecimal.ZERO, - microsecond = BigDecimal.ZERO, - nanosecond = BigDecimal.ZERO, - attosecond = inputAbs.trimZeros() - ) - - // DAY - var division = inputAbs.divideAndRemainder(dayBasicUnit) - val day = division.component1().setScale(0, RoundingMode.HALF_EVEN) - var remainingSeconds = division.component2().setScale(0, RoundingMode.HALF_EVEN) - - division = remainingSeconds.divideAndRemainder(hourBasicUnit) - val hour = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(minuteBasicUnit) - val minute = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(secondBasicUnit) - val second = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(millisecondBasicUnit) - val millisecond = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(microsecondBasicUnit) - val microsecond = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(nanosecondBasicUnit) - val nanosecond = division.component1() - remainingSeconds = division.component2() - - val attosecond = remainingSeconds - - return ConverterResult.Time( - negative = negative, - day = day, - hour = hour, - minute = minute, - second = second, - millisecond = millisecond, - microsecond = microsecond, - nanosecond = nanosecond, - attosecond = attosecond - ) -} - -/** - * Creates an object for displaying formatted foot and inch output. Units are passed as objects so - * that changes in basic units don't require modifying the method. Also this method can't access - * units repository directly. - * - * @param input Input in feet. - * @param footUnit Foot unit [DefaultUnit]. - * @param inchUnit Inch unit [DefaultUnit]. - * @return Result where decimal places are converter into inches. - */ -internal fun formatFootInch( - input: BigDecimal, - footUnit: DefaultUnit, - inchUnit: DefaultUnit -): ConverterResult.FootInch { - val (integral, fractional) = input.divideAndRemainder(BigDecimal.ONE) - - return ConverterResult.FootInch(integral, footUnit.convert(inchUnit, fractional)) -} - -private val dayBasicUnit by lazy { BigDecimal("86400000000000000000000") } -private val hourBasicUnit by lazy { BigDecimal("3600000000000000000000") } -private val minuteBasicUnit by lazy { BigDecimal("60000000000000000000") } -private val secondBasicUnit by lazy { BigDecimal("1000000000000000000") } -private val millisecondBasicUnit by lazy { BigDecimal("1000000000000000") } -private val microsecondBasicUnit by lazy { BigDecimal("1000000000000") } -private val nanosecondBasicUnit by lazy { BigDecimal("1000000000") } -private val attosecondBasicUnit by lazy { BigDecimal("1") } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt deleted file mode 100644 index 70a3e623..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt +++ /dev/null @@ -1,520 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2022-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.addBracket -import com.sadellie.unitto.core.ui.common.textfield.addTokens -import com.sadellie.unitto.core.ui.common.textfield.deleteTokens -import com.sadellie.unitto.core.ui.common.textfield.getTextField -import com.sadellie.unitto.data.common.combine -import com.sadellie.unitto.data.common.isExpression -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.repository.UnitsRepository -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import dagger.hilt.android.lifecycle.HiltViewModel -import io.github.sadellie.evaluatto.Expression -import io.github.sadellie.evaluatto.ExpressionException -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.getAndUpdate -import kotlinx.coroutines.flow.mapLatest -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.math.BigDecimal -import javax.inject.Inject - -@HiltViewModel -internal class ConverterViewModel @Inject constructor( - private val userPrefsRepository: UserPreferencesRepository, - private val unitsRepo: UnitsRepository, - private val savedStateHandle: SavedStateHandle -) : ViewModel() { - - private val converterInputKey1 = "CONVERTER_INPUT_1" - private val converterInputKey2 = "CONVERTER_INPUT_2" - private val _input1 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey1)) - private val _input2 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey2)) - private val _focusedOnInput2 = MutableStateFlow(false) - private val _calculation = MutableStateFlow(null) - private val _result = MutableStateFlow(ConverterResult.Loading) - private val _unitFrom = MutableStateFlow(null) - private val _unitTo = MutableStateFlow(null) - - private val _leftQuery = MutableStateFlow(TextFieldValue()) - private val _leftUnits = MutableStateFlow>>(emptyMap()) - private val _leftUnitGroup = MutableStateFlow(null) - - private val _rightQuery = MutableStateFlow(TextFieldValue()) - private val _rightUnits = MutableStateFlow>>(emptyMap()) - - private val _currenciesState = MutableStateFlow(CurrencyRateUpdateState.Nothing) - private var _loadCurrenciesJob: Job? = null - - val converterUiState: StateFlow = combine( - _input1, - _input2, - _calculation, - _result, - _unitFrom, - _unitTo, - userPrefsRepository.converterPrefs, - _currenciesState - ) { input1, input2, calculation, result, unitFrom, unitTo, prefs, currenciesState -> - return@combine when { - (unitFrom is DefaultUnit) and (unitTo is DefaultUnit) -> { - UnitConverterUIState.Default( - input1 = input1, - input2 = input2, - calculation = calculation, - result = result, - unitFrom = unitFrom as DefaultUnit, - unitTo = unitTo as DefaultUnit, - middleZero = prefs.middleZero, - formatterSymbols = AllFormatterSymbols.getById(prefs.separator), - scale = prefs.precision, - outputFormat = prefs.outputFormat, - formatTime = prefs.unitConverterFormatTime, - currencyRateUpdateState = currenciesState, - acButton = prefs.acButton, - ) - } - (unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit) -> { - UnitConverterUIState.NumberBase( - input = input1, - result = result, - unitFrom = unitFrom as NumberBaseUnit, - unitTo = unitTo as NumberBaseUnit, - ) - } - else -> UnitConverterUIState.Loading - } - } - .mapLatest { ui -> - when (_currenciesState.value) { - is CurrencyRateUpdateState.Loading -> { - _result.update { ConverterResult.Loading } - return@mapLatest ui - } - is CurrencyRateUpdateState.Error -> { - _result.update { ConverterResult.Error } - return@mapLatest ui - } - is CurrencyRateUpdateState.Ready, is CurrencyRateUpdateState.Nothing -> {} - } - - when (ui) { - is UnitConverterUIState.Default -> { - convertDefault( - unitFrom = ui.unitFrom, - unitTo = ui.unitTo, - input1 = ui.input1, - input2 = ui.input2, - formatTime = ui.formatTime - ) - } - is UnitConverterUIState.NumberBase -> { - convertNumberBase( - unitFrom = ui.unitFrom, - unitTo = ui.unitTo, - input = ui.input - ) - } - is UnitConverterUIState.Loading -> {} - } - - ui - } - .stateIn(viewModelScope, UnitConverterUIState.Loading) - - val leftSideUIState = combine( - _unitFrom, - _leftQuery, - _leftUnits, - _leftUnitGroup, - userPrefsRepository.converterPrefs, - unitsRepo.units - ) { unitFrom, query, units, unitGroup, prefs, _ -> - unitFrom ?: return@combine LeftSideUIState.Loading - - return@combine LeftSideUIState.Ready( - unitFrom = unitFrom, - sorting = prefs.unitConverterSorting, - shownUnitGroups = prefs.shownUnitGroups, - favorites = prefs.unitConverterFavoritesOnly, - query = query, - units = units, - unitGroup = unitGroup - ) - } - .mapLatest { - if (it !is LeftSideUIState.Ready) return@mapLatest it - - filterUnitsLeft( - query = it.query, - unitGroup = it.unitGroup, - favoritesOnly = it.favorites, - sorting = it.sorting, - shownUnitGroups = it.shownUnitGroups, - ) - it - } - .stateIn(viewModelScope, SharingStarted.Lazily, LeftSideUIState.Loading) - - val rightSideUIState = combine( - _unitFrom, - _unitTo, - _input1, - _calculation, - _rightQuery, - _rightUnits, - userPrefsRepository.converterPrefs, - _currenciesState, - unitsRepo.units, - ) { unitFrom, unitTo, input, calculation, query, units, prefs, currenciesState, _ -> - unitFrom ?: return@combine RightSideUIState.Loading - unitTo ?: return@combine RightSideUIState.Loading - - return@combine RightSideUIState.Ready( - unitFrom = unitFrom, - unitTo = unitTo, - sorting = prefs.unitConverterSorting, - favorites = prefs.unitConverterFavoritesOnly, - input = (calculation?.toPlainString() ?: input.text).replace(Token.Operator.minus, "-"), - scale = prefs.precision, - outputFormat = prefs.outputFormat, - formatterSymbols = AllFormatterSymbols.getById(prefs.separator), - currencyRateUpdateState = currenciesState, - query = query, - units = units, - ) - } - .mapLatest { - if (it !is RightSideUIState.Ready) return@mapLatest it - - filterUnitsRight( - query = it.query, - unitGroup = it.unitFrom.group, - favoritesOnly = it.favorites, - sorting = it.sorting, - ) - it - } - .stateIn(viewModelScope, SharingStarted.Lazily, RightSideUIState.Loading) - - fun swapUnits() { - _unitFrom - .getAndUpdate { _unitTo.value } - .also { oldUnitFrom -> _unitTo.update { oldUnitFrom } } - - _loadCurrenciesJob?.cancel() - _currenciesState.update { CurrencyRateUpdateState.Nothing } - _unitFrom.value?.let { - if (it.group == UnitGroup.CURRENCY) updateCurrencyRates(it) - } - - viewModelScope.launch { - val unitTo = _unitTo.value ?: return@launch - val unitFrom = _unitFrom.value ?: return@launch - - userPrefsRepository.updateLatestPairOfUnits(unitFrom = unitFrom, unitTo = unitTo) - } - } - - /** - * Change currently focused text field. For feet and inches input - * - * @param focusOnInput2 `true` if focus is on inches input. `false`if focus on feet input. - */ - fun updateFocused(focusOnInput2: Boolean) = _focusedOnInput2.update { focusOnInput2 } - - fun addTokens(tokens: String) { - if (_focusedOnInput2.value) { - _input2.update { - val newValue = it.addTokens(tokens) - savedStateHandle[converterInputKey2] = newValue.text - newValue - } - } else { - _input1.update { - val newValue = it.addTokens(tokens) - savedStateHandle[converterInputKey1] = newValue.text - newValue - } - } - } - - fun addBracket() { - if (_focusedOnInput2.value) { - _input2.update { - val newValue = it.addBracket() - savedStateHandle[converterInputKey2] = newValue.text - newValue - } - } else { - _input1.update { - val newValue = it.addBracket() - savedStateHandle[converterInputKey1] = newValue.text - newValue - } - } - } - - fun deleteTokens() { - if (_focusedOnInput2.value) { - _input2.update { - val newValue = it.deleteTokens() - savedStateHandle[converterInputKey2] = newValue.text - newValue - } - } else { - _input1.update { - val newValue = it.deleteTokens() - savedStateHandle[converterInputKey1] = newValue.text - newValue - } - } - } - - fun clearInput() { - _input1.update { - savedStateHandle[converterInputKey1] = "" - TextFieldValue() - } - _input2.update { - savedStateHandle[converterInputKey2] = "" - TextFieldValue() - } - } - - fun onCursorChange(selection: TextRange) = _input1.update { it.copy(selection = selection) } - - fun updateCurrencyRates(unit: AbstractUnit) { - _loadCurrenciesJob = viewModelScope.launch(Dispatchers.IO) { - try { - _currenciesState.update { CurrencyRateUpdateState.Loading } - val updateDate = unitsRepo.updateRates(unit) ?: throw Exception("Empty cache") - - // Set to fresh objects with updated basic unit values - _unitFrom.update { unitFrom -> unitFrom?.id?.let { unitsRepo.getById(it) } } - _unitTo.update { unitTo -> unitTo?.id?.let { unitsRepo.getById(it) } } - _currenciesState.update { CurrencyRateUpdateState.Ready(updateDate) } - } catch (e: Exception) { - _currenciesState.update { CurrencyRateUpdateState.Error } - } - } - } - - fun updateUnitFrom(unit: AbstractUnit) = viewModelScope.launch { - val pairId = unit.pairId - val pair: AbstractUnit = if (pairId == null) { - val collection = unitsRepo.getCollection(unit.group).sortedByDescending { it.counter } - collection.firstOrNull { it.isFavorite } ?: collection.first() - } else { - unitsRepo.getById(pairId) - } - - withContext(Dispatchers.Default) { - unitsRepo.incrementCounter(unit) - userPrefsRepository.updateLatestPairOfUnits(unitFrom = unit, unitTo = pair) - } - - _loadCurrenciesJob?.cancel() - _currenciesState.update { CurrencyRateUpdateState.Nothing } - if (unit.group == UnitGroup.CURRENCY) updateCurrencyRates(unit) - - _unitFrom.update { - // We change from something to base converter or the other way around - if ((it?.group == UnitGroup.NUMBER_BASE) xor (unit.group == UnitGroup.NUMBER_BASE)) - clearInput() - - unit - } - _unitTo.update { pair } - } - - fun updateUnitTo(unit: AbstractUnit) { - _unitTo.update { unit } - - viewModelScope.launch { - val unitTo = _unitTo.value ?: return@launch - val unitFrom = _unitFrom.value ?: return@launch - - unitsRepo.incrementCounter(unitTo) - - unitsRepo.setPair(unitFrom, unitTo) - userPrefsRepository.updateLatestPairOfUnits(unitFrom = unitFrom, unitTo = unitTo) - } - } - - fun queryChangeLeft(query: TextFieldValue) = _leftQuery.update { query } - - fun queryChangeRight(query: TextFieldValue) = _rightQuery.update { query } - - fun favoritesOnlyChange(enabled: Boolean) = viewModelScope.launch { - userPrefsRepository.updateUnitConverterFavoritesOnly(enabled) - } - - fun updateUnitGroupLeft(unitGroup: UnitGroup?) = _leftUnitGroup.update { unitGroup } - - fun favoriteUnit(unit: AbstractUnit) = viewModelScope.launch { - unitsRepo.favorite(unit) - } - - private fun filterUnitsLeft( - query: TextFieldValue, - unitGroup: UnitGroup?, - favoritesOnly: Boolean, - sorting: UnitsListSorting, - shownUnitGroups: List, - ) = viewModelScope.launch(Dispatchers.Default) { - _leftUnits.update { - unitsRepo.filterUnits( - query = query.text, - unitGroup = unitGroup, - favoritesOnly = favoritesOnly, - hideBrokenUnits = false, - sorting = sorting, - shownUnitGroups = shownUnitGroups - ) - } - } - - private fun filterUnitsRight( - query: TextFieldValue, - unitGroup: UnitGroup?, - favoritesOnly: Boolean, - sorting: UnitsListSorting, - ) = viewModelScope.launch(Dispatchers.Default) { - _rightUnits.update { - unitsRepo.filterUnits( - query = query.text, - unitGroup = unitGroup, - favoritesOnly = favoritesOnly, - hideBrokenUnits = true, - sorting = sorting, - ) - } - } - - private fun convertDefault( - unitFrom: DefaultUnit, - unitTo: DefaultUnit, - input1: TextFieldValue, - input2: TextFieldValue, - formatTime: Boolean, - ) = viewModelScope.launch(Dispatchers.Default) { - val footInchInput = unitFrom.id == UnitID.foot - - if (footInchInput) { _calculation.update { null } } - - // Calculate - val calculated1 = try { - Expression(input1.text.ifEmpty { Token.Digit._0 }).calculate() - } catch (e: ExpressionException.DivideByZero) { - _calculation.update { null } - return@launch - } catch (e: Exception) { - return@launch - } - - // Update calculation - _calculation.update { if (input1.text.isExpression()) calculated1 else null } - - // Convert - val result: ConverterResult = try { - var conversion = unitFrom.convert(unitTo, calculated1) - if (footInchInput) { - // Converted from second text field too - val inches = unitsRepo.getById(UnitID.inch) as DefaultUnit - val calculated2 = try { - Expression(input2.text.ifEmpty { Token.Digit._0 }).calculate() - } catch (e: ExpressionException.DivideByZero) { - _calculation.update { null } - return@launch - } catch (e: Exception) { - return@launch - } - conversion += inches.convert(unitTo, calculated2) - } - when { - (unitFrom.group == UnitGroup.TIME) and (formatTime) -> formatTime(calculated1.multiply(unitFrom.basicUnit)) - unitTo.id == UnitID.foot -> formatFootInch(conversion, unitTo, unitsRepo.getById(UnitID.inch) as DefaultUnit) - else -> ConverterResult.Default(conversion) - } - } catch (e: Exception) { - ConverterResult.Default(BigDecimal.ZERO) - } - - // Update result - _result.update { result } - } - - private fun convertNumberBase( - unitFrom: NumberBaseUnit, - unitTo: NumberBaseUnit, - input: TextFieldValue, - ) = viewModelScope.launch(Dispatchers.Default) { - val conversion = try { - unitFrom.convert(unitTo, input.text.ifEmpty { Token.Digit._0 }) - } catch (e: Exception) { - "" - } - - _result.update { ConverterResult.NumberBase(conversion) } - } - - init { - viewModelScope.launch(Dispatchers.Default) { - try { - val userPrefs = userPrefsRepository.converterPrefs.first() - val unitFrom = unitsRepo.getById(userPrefs.latestLeftSideUnit) - val unitTo = unitsRepo.getById(userPrefs.latestRightSideUnit) - - _unitFrom.update { unitFrom } - _unitTo.update { unitTo } - if (unitFrom.group == UnitGroup.CURRENCY) updateCurrencyRates(unitFrom) - } catch (e: NoSuchElementException) { - val unitFrom = unitsRepo.getById(UnitID.kilometer) - val unitTo = unitsRepo.getById(UnitID.mile) - - _unitFrom.update { unitFrom } - _unitTo.update { unitTo } - } - } - } -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt deleted file mode 100644 index 03b6e039..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import androidx.compose.animation.Crossfade -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.SearchPlaceholder -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.SearchBar -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.feature.converter.components.BasicUnitListItem -import com.sadellie.unitto.feature.converter.components.ChipsRow -import com.sadellie.unitto.feature.converter.components.FavoritesButton -import com.sadellie.unitto.feature.converter.components.UnitGroupHeader -import java.math.BigDecimal - -@Composable -internal fun LeftSideRoute( - viewModel: ConverterViewModel, - navigateUp: () -> Unit, - navigateToUnitGroups: () -> Unit, -) { - when ( - val uiState = viewModel.leftSideUIState.collectAsStateWithLifecycle().value - ) { - is LeftSideUIState.Loading -> EmptyScreen() - is LeftSideUIState.Ready -> LeftSideScreen( - uiState = uiState, - onQueryChange = viewModel::queryChangeLeft, - toggleFavoritesOnly = viewModel::favoritesOnlyChange, - updateUnitFrom = viewModel::updateUnitFrom, - updateUnitGroup = viewModel::updateUnitGroupLeft, - favoriteUnit = viewModel::favoriteUnit, - navigateUp = navigateUp, - navigateToUnitGroups = navigateToUnitGroups, - ) - } -} - -@Composable -private fun LeftSideScreen( - uiState: LeftSideUIState.Ready, - onQueryChange: (TextFieldValue) -> Unit, - toggleFavoritesOnly: (Boolean) -> Unit, - updateUnitFrom: (AbstractUnit) -> Unit, - updateUnitGroup: (UnitGroup?) -> Unit, - favoriteUnit: (AbstractUnit) -> Unit, - navigateUp: () -> Unit, - navigateToUnitGroups: () -> Unit, -) { - val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() - - val chipsRowLazyListState = rememberLazyListState() - - LaunchedEffect(uiState.unitFrom, uiState.shownUnitGroups) { - updateUnitGroup(uiState.unitFrom.group) - - kotlin.runCatching { - val groupToSelect = uiState.shownUnitGroups.indexOf(uiState.unitFrom.group) - if (groupToSelect > -1) { - chipsRowLazyListState.scrollToItem(groupToSelect) - } - } - } - - Scaffold( - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - Column( - Modifier.background(MaterialTheme.colorScheme.surface) - ) { - SearchBar( - query = uiState.query, - onQueryChange = onQueryChange, - navigateUp = navigateUp, - trailingIcon = { - FavoritesButton(uiState.favorites) { - toggleFavoritesOnly(!uiState.favorites) - } - }, - scrollBehavior = scrollBehavior - ) - - ChipsRow( - chosenUnitGroup = uiState.unitGroup, - items = uiState.shownUnitGroups, - selectAction = updateUnitGroup, - lazyListState = chipsRowLazyListState, - navigateToSettingsAction = navigateToUnitGroups - ) - } - } - ) { paddingValues -> - Crossfade( - targetState = uiState.units.isNotEmpty(), - modifier = Modifier.padding(paddingValues), - label = "Units list" - ) { hasUnits -> - when (hasUnits) { - true -> LazyColumn(Modifier.fillMaxSize()) { - uiState.units.forEach { (unitGroup, units) -> - item(unitGroup.name) { - UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup) - } - - items(units, { it.id }) { - BasicUnitListItem( - modifier = Modifier.animateItemPlacement(), - name = stringResource(it.displayName), - supportLabel = stringResource(it.shortName), - isFavorite = it.isFavorite, - isSelected = it.id == uiState.unitFrom.id, - onClick = { - onQueryChange(TextFieldValue()) - updateUnitFrom(it) - navigateUp() - }, - favoriteUnit = { favoriteUnit(it) } - ) - } - } - } - - false -> SearchPlaceholder( - onButtonClick = navigateToUnitGroups, - supportText = stringResource(R.string.converter_no_results_support), - buttonLabel = stringResource(R.string.open_settings_label) - ) - } - } - } -} - -@Preview -@Composable -private fun LeftSideScreenPreview() { - val units: Map> = mapOf( - UnitGroup.LENGTH to listOf( - NormalUnit(UnitID.meter, BigDecimal.valueOf(1.0E+18), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), - NormalUnit(UnitID.kilometer, BigDecimal.valueOf(1.0E+21), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), - NormalUnit(UnitID.nautical_mile, BigDecimal.valueOf(1.852E+21), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), - NormalUnit(UnitID.inch, BigDecimal.valueOf(25_400_000_000_000_000), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), - NormalUnit(UnitID.foot, BigDecimal.valueOf(304_800_000_000_002_200), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), - NormalUnit(UnitID.yard, BigDecimal.valueOf(914_400_000_000_006_400), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), - NormalUnit(UnitID.mile, BigDecimal.valueOf(1_609_344_000_000_010_500_000.0), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), - ) - ) - - LeftSideScreen( - uiState = LeftSideUIState.Ready( - unitFrom = units.values.first().first(), - units = units, - query = TextFieldValue("test"), - favorites = false, - shownUnitGroups = listOf(UnitGroup.LENGTH, UnitGroup.TEMPERATURE, UnitGroup.CURRENCY), - unitGroup = units.keys.toList().first(), - sorting = UnitsListSorting.USAGE, - ), - onQueryChange = {}, - toggleFavoritesOnly = {}, - updateUnitFrom = {}, - updateUnitGroup = {}, - favoriteUnit = {}, - navigateUp = {}, - navigateToUnitGroups = {} - ) -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideUIState.kt deleted file mode 100644 index 7ef72129..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideUIState.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit - -internal sealed class LeftSideUIState { - data object Loading : LeftSideUIState() - - data class Ready( - val unitFrom: AbstractUnit, - val query: TextFieldValue, - val units: Map> = emptyMap(), - val favorites: Boolean, - val shownUnitGroups: List, - val unitGroup: UnitGroup?, - val sorting: UnitsListSorting, - ) : LeftSideUIState() -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt deleted file mode 100644 index 32e16b2f..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import androidx.compose.animation.Crossfade -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Scaffold -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.SearchPlaceholder -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.SearchBar -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.feature.converter.components.BasicUnitListItem -import com.sadellie.unitto.feature.converter.components.FavoritesButton -import com.sadellie.unitto.feature.converter.components.UnitGroupHeader -import java.math.BigDecimal - -@Composable -internal fun RightSideRoute( - viewModel: ConverterViewModel, - navigateUp: () -> Unit, - navigateToUnitGroups: () -> Unit, -) { - when ( - val uiState = viewModel.rightSideUIState.collectAsStateWithLifecycle().value - ) { - is RightSideUIState.Loading -> EmptyScreen() - is RightSideUIState.Ready -> - RightSideScreen( - uiState = uiState, - onQueryChange = viewModel::queryChangeRight, - toggleFavoritesOnly = viewModel::favoritesOnlyChange, - updateUnitTo = viewModel::updateUnitTo, - favoriteUnit = viewModel::favoriteUnit, - navigateUp = navigateUp, - navigateToUnitGroups = navigateToUnitGroups, - ) - } -} - -@Composable -private fun RightSideScreen( - uiState: RightSideUIState.Ready, - onQueryChange: (TextFieldValue) -> Unit, - toggleFavoritesOnly: (Boolean) -> Unit, - updateUnitTo: (AbstractUnit) -> Unit, - favoriteUnit: (AbstractUnit) -> Unit, - navigateUp: () -> Unit, - navigateToUnitGroups: () -> Unit, -) { - val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() - - Scaffold( - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - SearchBar( - query = uiState.query, - onQueryChange = onQueryChange, - navigateUp = navigateUp, - trailingIcon = { - FavoritesButton(uiState.favorites) { - toggleFavoritesOnly(!uiState.favorites) - } - }, - scrollBehavior = scrollBehavior - ) - } - ) { paddingValues -> - Crossfade( - targetState = uiState.units.isNotEmpty(), - modifier = Modifier.padding(paddingValues), - label = "Units list" - ) { hasUnits -> - when (hasUnits) { - true -> LazyColumn(Modifier.fillMaxSize()) { - uiState.units.forEach { (unitGroup, units) -> - item(unitGroup.name) { - UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup) - } - - items(units, { it.id }) { - BasicUnitListItem( - modifier = Modifier.animateItemPlacement(), - name = stringResource(it.displayName), - supportLabel = formatUnitToSupportLabel( - unitFrom = uiState.unitFrom, - unitTo = it, - input = uiState.input, - shortName = stringResource(it.shortName), - scale = uiState.scale, - outputFormat = uiState.outputFormat, - formatterSymbols = uiState.formatterSymbols, - readyCurrencies = uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready, - ), - isFavorite = it.isFavorite, - isSelected = it.id == uiState.unitTo.id, - onClick = { - onQueryChange(TextFieldValue()) - updateUnitTo(it) - navigateUp() - }, - favoriteUnit = { favoriteUnit(it) } - ) - } - } - } - - false -> SearchPlaceholder( - onButtonClick = navigateToUnitGroups, - supportText = stringResource(R.string.converter_no_results_support), - buttonLabel = stringResource(R.string.open_settings_label) - ) - } - } - } -} - -private fun formatUnitToSupportLabel( - unitFrom: AbstractUnit?, - unitTo: AbstractUnit?, - input: String, - shortName: String, - scale: Int, - outputFormat: Int, - formatterSymbols: FormatterSymbols, - readyCurrencies: Boolean, -): String { - if ((unitFrom?.group == UnitGroup.CURRENCY) and !readyCurrencies) return shortName - if (input.isEmpty()) return shortName - - try { - if ((unitFrom is DefaultUnit) and (unitTo is DefaultUnit)) { - unitFrom as DefaultUnit - unitTo as DefaultUnit - - val conversion = unitFrom - .convert(unitTo, BigDecimal(input)) - .format(scale, outputFormat) - .formatExpression(formatterSymbols) - - return "$conversion $shortName" - } - - if ((unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit)) { - unitFrom as NumberBaseUnit - unitTo as NumberBaseUnit - - val conversion = unitFrom.convert(unitTo, input).uppercase() - - return "$conversion $shortName" - } - } catch (e: Exception) { - return shortName - } - - return shortName -} - -@Preview -@Composable -private fun RightSideScreenPreview() { - val units: Map> = mapOf( - UnitGroup.LENGTH to listOf( - NormalUnit(UnitID.meter, BigDecimal.valueOf(1.0E+18), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), - NormalUnit(UnitID.kilometer, BigDecimal.valueOf(1.0E+21), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), - NormalUnit(UnitID.nautical_mile, BigDecimal.valueOf(1.852E+21), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), - NormalUnit(UnitID.inch, BigDecimal.valueOf(25_400_000_000_000_000), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), - NormalUnit(UnitID.foot, BigDecimal.valueOf(304_800_000_000_002_200), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), - NormalUnit(UnitID.yard, BigDecimal.valueOf(914_400_000_000_006_400), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), - NormalUnit(UnitID.mile, BigDecimal.valueOf(1_609_344_000_000_010_500_000.0), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), - ) - ) - - RightSideScreen( - uiState = RightSideUIState.Ready( - unitFrom = units.values.first().first(), - units = units, - query = TextFieldValue(), - favorites = false, - sorting = UnitsListSorting.USAGE, - unitTo = units.values.first()[1], - input = "100", - scale = 3, - outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces, - currencyRateUpdateState = CurrencyRateUpdateState.Nothing - ), - onQueryChange = {}, - toggleFavoritesOnly = {}, - updateUnitTo = {}, - favoriteUnit = {}, - navigateUp = {}, - navigateToUnitGroups = {} - ) -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideUIState.kt deleted file mode 100644 index 1148f800..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideUIState.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit - -internal sealed class RightSideUIState { - data object Loading : RightSideUIState() - - data class Ready( - val unitFrom: AbstractUnit, - val unitTo: AbstractUnit, - val query: TextFieldValue, - val units: Map>, - val favorites: Boolean, - val sorting: UnitsListSorting, - val input: String, - val scale: Int, - val outputFormat: Int, - val formatterSymbols: FormatterSymbols, - val currencyRateUpdateState: CurrencyRateUpdateState, - ) : RightSideUIState() -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt deleted file mode 100644 index 4d9b6e2a..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2022-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter.components - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.Settings -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.AssistChip -import com.sadellie.unitto.core.ui.common.FilterChip -import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS -import com.sadellie.unitto.data.model.UnitGroup - -/** - * Row of chips with [UnitGroup]s. Temporary solution - * - * @param items All [UnitGroup]s - * @param chosenUnitGroup Currently selected [UnitGroup] - * @param selectAction Action to perform when a chip is clicked - * @param navigateToSettingsAction Action to perform when clicking settings chip at the end - * @param lazyListState Used for animated scroll when entering unit selection screen - */ -@Composable -internal fun ChipsRow( - items: List = ALL_UNIT_GROUPS, - chosenUnitGroup: UnitGroup?, - selectAction: (UnitGroup?) -> Unit, - navigateToSettingsAction: () -> Unit, - lazyListState: LazyListState -) { - LazyRow( - modifier = Modifier - .padding(bottom = 4.dp) - .fillMaxWidth(), - state = lazyListState, - contentPadding = PaddingValues(8.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(items, key = { it.name }) { item -> - val selected: Boolean = item == chosenUnitGroup - FilterChip( - selected = selected, - onClick = { selectAction(if (selected) null else item) }, - label = stringResource(item.res), - imageVector = Icons.Default.Check, - contentDescription = stringResource(R.string.checked_filter_description) - ) - } - - /** - * Usually this chip is placed at the start, but since we scroll to currently selected - * chip, user may never find it. There is higher chance that user will notice this chip when - * scrolling right (to the last one). - */ - item("settings") { - AssistChip( - onClick = navigateToSettingsAction, - imageVector = Icons.Default.Settings, - contentDescription = stringResource(R.string.open_settings_label) - ) - } - } -} - -@Preview -@Composable -fun PreviewUnittoChips() { - var selected by remember { mutableStateOf(UnitGroup.LENGTH) } - - fun selectAction(unitGroup: UnitGroup?) { - selected = unitGroup - } - - ChipsRow( - items = ALL_UNIT_GROUPS, - chosenUnitGroup = selected, - selectAction = { selectAction(it) }, - navigateToSettingsAction = {}, - lazyListState = rememberLazyListState() - ) -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt deleted file mode 100644 index 1033121b..00000000 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter.navigation - -import androidx.compose.runtime.remember -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavHostController -import androidx.navigation.navDeepLink -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.unittoComposable -import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.feature.converter.ConverterRoute -import com.sadellie.unitto.feature.converter.ConverterViewModel -import com.sadellie.unitto.feature.converter.LeftSideRoute -import com.sadellie.unitto.feature.converter.RightSideRoute - -private val graph = DrawerItem.Converter.graph -private val start = DrawerItem.Converter.start -private const val LEFT = "left" -private const val RIGHT = "right" - -fun NavGraphBuilder.converterGraph( - openDrawer: () -> Unit, - navController: NavHostController, - navigateToSettings: () -> Unit, - navigateToUnitGroups: () -> Unit, -) { - unittoNavigation( - startDestination = start, - route = graph, - deepLinks = listOf( - navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" } - ) - ) { - unittoComposable(start) { backStackEntry -> - val parentEntry = remember(backStackEntry) { - navController.getBackStackEntry(graph) - } - - val parentViewModel = hiltViewModel(parentEntry) - - ConverterRoute( - viewModel = parentViewModel, - navigateToLeftScreen = { navController.navigate(LEFT) }, - navigateToRightScreen = { navController.navigate(RIGHT) }, - navigateToSettings = navigateToSettings, - navigateToMenu = openDrawer - ) - } - - unittoComposable(LEFT) { backStackEntry -> - val parentEntry = remember(backStackEntry) { - navController.getBackStackEntry(graph) - } - - val parentViewModel = hiltViewModel(parentEntry) - - LeftSideRoute( - viewModel = parentViewModel, - navigateUp = navController::navigateUp, - navigateToUnitGroups = navigateToUnitGroups - ) - } - - unittoComposable(RIGHT) { backStackEntry -> - val parentEntry = remember(backStackEntry) { - navController.getBackStackEntry(graph) - } - - val parentViewModel = hiltViewModel(parentEntry) - - RightSideRoute( - viewModel = parentViewModel, - navigateUp = navController::navigateUp, - navigateToUnitGroups = navigateToUnitGroups - ) - } - } -} diff --git a/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt b/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt deleted file mode 100644 index fc99362e..00000000 --- a/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import android.content.Context -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment -import java.math.BigDecimal - -@RunWith(RobolectricTestRunner::class) -class ConverterUIStateKtTest { - - @Test - fun format() { - val formatterSymbols = FormatterSymbols.Spaces - var basicValue = BigDecimal.valueOf(1) - val mContext: Context = RuntimeEnvironment.getApplication().applicationContext - - fun String.formatTime() = formatTime(basicValue.multiply(BigDecimal(this))) - .format(mContext, formatterSymbols) - - // Edgy things (minus, decimals and zeros) - Assert.assertEquals("−28as", "-28".formatTime()) - Assert.assertEquals("−0.05as", "-0.05".formatTime()) - Assert.assertEquals("0", "0".formatTime()) - - basicValue = BigDecimal.valueOf(86_400_000_000_000_000_000_000.0) - Assert.assertEquals("−28d", "-28".formatTime()) - Assert.assertEquals("−1h 12m", "-0.05".formatTime()) - Assert.assertEquals("0", "0".formatTime()) - Assert.assertEquals("0", "-0".formatTime()) - - // DAYS - basicValue = BigDecimal.valueOf(86_400_000_000_000_000_000_000.0) - Assert.assertEquals("12h", "0.5".formatTime()) - Assert.assertEquals("1h 12m", "0.05".formatTime()) - Assert.assertEquals("7m 12s", "0.005".formatTime()) - Assert.assertEquals("28d", "28".formatTime()) - Assert.assertEquals("90d", "90".formatTime()) - Assert.assertEquals("90d 12h", "90.5".formatTime()) - Assert.assertEquals("90d 7m 12s", "90.005".formatTime()) - - // HOURS - basicValue = BigDecimal.valueOf(3_600_000_000_000_000_000_000.0) - Assert.assertEquals("30m", "0.5".formatTime()) - Assert.assertEquals("3m", "0.05".formatTime()) - Assert.assertEquals("18s", "0.005".formatTime()) - Assert.assertEquals("1d 4h", "28".formatTime()) - Assert.assertEquals("3d 18h", "90".formatTime()) - Assert.assertEquals("3d 18h 30m", "90.5".formatTime()) - Assert.assertEquals("3d 18h 18s", "90.005".formatTime()) - - // MINUTES - basicValue = BigDecimal.valueOf(60_000_000_000_000_000_000.0) - Assert.assertEquals("30s", "0.5".formatTime()) - Assert.assertEquals("3s", "0.05".formatTime()) - Assert.assertEquals("300ms", "0.005".formatTime()) - Assert.assertEquals("28m", "28".formatTime()) - Assert.assertEquals("1h 30m", "90".formatTime()) - Assert.assertEquals("1h 30m 30s", "90.5".formatTime()) - Assert.assertEquals("1h 30m 300ms", "90.005".formatTime()) - - // SECONDS - basicValue = BigDecimal.valueOf(1_000_000_000_000_000_000) - Assert.assertEquals("500ms", "0.5".formatTime()) - Assert.assertEquals("50ms", "0.05".formatTime()) - Assert.assertEquals("5ms", "0.005".formatTime()) - Assert.assertEquals("28s", "28".formatTime()) - Assert.assertEquals("1m 30s", "90".formatTime()) - Assert.assertEquals("1m 30s 500ms", "90.5".formatTime()) - Assert.assertEquals("1m 30s 5ms", "90.005".formatTime()) - - // MILLISECONDS - basicValue = BigDecimal.valueOf(1_000_000_000_000_000) - Assert.assertEquals("500µs", "0.5".formatTime()) - Assert.assertEquals("50µs", "0.05".formatTime()) - Assert.assertEquals("5µs", "0.005".formatTime()) - Assert.assertEquals("28ms", "28".formatTime()) - Assert.assertEquals("90ms", "90".formatTime()) - Assert.assertEquals("90ms 500µs", "90.5".formatTime()) - Assert.assertEquals("90ms 5µs", "90.005".formatTime()) - - // MICROSECONDS - basicValue = BigDecimal.valueOf(1_000_000_000_000) - Assert.assertEquals("500ns", "0.5".formatTime()) - Assert.assertEquals("50ns", "0.05".formatTime()) - Assert.assertEquals("5ns", "0.005".formatTime()) - Assert.assertEquals("28µs", "28".formatTime()) - Assert.assertEquals("90µs", "90".formatTime()) - Assert.assertEquals("90µs 500ns", "90.5".formatTime()) - Assert.assertEquals("90µs 5ns", "90.005".formatTime()) - - // NANOSECONDS - basicValue = BigDecimal.valueOf(1_000_000_000) - Assert.assertEquals("500 000 000as", "0.5".formatTime()) - Assert.assertEquals("50 000 000as", "0.05".formatTime()) - Assert.assertEquals("5 000 000as", "0.005".formatTime()) - Assert.assertEquals("28ns", "28".formatTime()) - Assert.assertEquals("90ns", "90".formatTime()) - Assert.assertEquals("90ns 500 000 000as", "90.5".formatTime()) - Assert.assertEquals("90ns 5 000 000as", "90.005".formatTime()) - - // ATTOSECONDS - basicValue = BigDecimal.valueOf(1) - Assert.assertEquals("0.5as", "0.5".formatTime()) - Assert.assertEquals("0.05as", "0.05".formatTime()) - Assert.assertEquals("0.005as", "0.005".formatTime()) - Assert.assertEquals("28as", "28".formatTime()) - Assert.assertEquals("90as", "90".formatTime()) - Assert.assertEquals("90.5as", "90.5".formatTime()) - Assert.assertEquals("90.005as", "90.005".formatTime()) - } -} diff --git a/feature/datecalculator/build.gradle.kts b/feature/datecalculator/build.gradle.kts index 1709569a..3d0d412f 100644 --- a/feature/datecalculator/build.gradle.kts +++ b/feature/datecalculator/build.gradle.kts @@ -24,7 +24,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.datecalculator" +android.namespace = "app.myzel394.numberhub.feature.datecalculator" dependencies { implementation(project(":data:common")) diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/DateCalculatorScreen.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/DateCalculatorScreen.kt similarity index 78% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/DateCalculatorScreen.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/DateCalculatorScreen.kt index d9d84fa7..06d8cbad 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/DateCalculatorScreen.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/DateCalculatorScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator +package app.myzel394.numberhub.feature.datecalculator import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding @@ -34,29 +34,25 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.MenuButton -import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar -import com.sadellie.unitto.feature.datecalculator.addsubtract.AddSubtractPage -import com.sadellie.unitto.feature.datecalculator.difference.DateDifferencePage +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.DrawerButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithTopBar +import app.myzel394.numberhub.feature.datecalculator.addsubtract.AddSubtractPage +import app.myzel394.numberhub.feature.datecalculator.difference.DateDifferencePage import kotlinx.coroutines.launch @Composable internal fun DateCalculatorRoute( - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, + openDrawer: () -> Unit, ) { DateCalculatorScreen( - navigateToMenu = navigateToMenu, - navigateToSettings = navigateToSettings, + openDrawer = openDrawer, ) } @Composable internal fun DateCalculatorScreen( - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, + openDrawer: () -> Unit, ) { val addSubtractLabel = "${stringResource(R.string.date_calculator_add)}/${stringResource(R.string.date_calculator_subtract)}" val differenceLabel = stringResource(R.string.date_calculator_difference) @@ -69,8 +65,7 @@ internal fun DateCalculatorScreen( ScaffoldWithTopBar( modifier = Modifier, title = { Text(stringResource(R.string.date_calculator_title)) }, - navigationIcon = { MenuButton(navigateToMenu) }, - actions = { SettingsButton(navigateToSettings) }, + navigationIcon = { DrawerButton(openDrawer) }, ) { paddingValues -> Column( modifier = Modifier.padding(paddingValues), @@ -86,14 +81,14 @@ internal fun DateCalculatorScreen( pagerState.animateScrollToPage(index) } }, - text = { Text(tab) } + text = { Text(tab) }, ) } } HorizontalPager( state = pagerState, - verticalAlignment = Alignment.Top + verticalAlignment = Alignment.Top, ) { page -> when (page) { 0 -> AddSubtractPage() @@ -111,7 +106,6 @@ internal fun DateCalculatorScreen( @Composable private fun DateCalculatorScreenPreview() { DateCalculatorScreen( - navigateToMenu = {}, - navigateToSettings = {}, + openDrawer = {}, ) } diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/ZonedDateTimeUtils.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/ZonedDateTimeUtils.kt similarity index 95% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/ZonedDateTimeUtils.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/ZonedDateTimeUtils.kt index 07888eff..5702775d 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/ZonedDateTimeUtils.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/ZonedDateTimeUtils.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator +package app.myzel394.numberhub.feature.datecalculator import java.time.ZonedDateTime import java.time.temporal.ChronoUnit diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractPage.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractPage.kt similarity index 92% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractPage.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractPage.kt index 6c2ee122..7a581475 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractPage.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractPage.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.addsubtract +package app.myzel394.numberhub.feature.datecalculator.addsubtract import android.annotation.SuppressLint import android.content.ActivityNotFoundException @@ -67,14 +67,14 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.textfield.ExpressionTransformer -import com.sadellie.unitto.core.ui.showToast -import com.sadellie.unitto.feature.datecalculator.ZonedDateTimeUtils -import com.sadellie.unitto.feature.datecalculator.components.DateTimeDialogs -import com.sadellie.unitto.feature.datecalculator.components.DateTimeSelectorBlock -import com.sadellie.unitto.feature.datecalculator.components.DialogState -import com.sadellie.unitto.feature.datecalculator.components.TimeUnitTextField +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.textfield.ExpressionTransformer +import app.myzel394.numberhub.core.ui.showToast +import app.myzel394.numberhub.feature.datecalculator.ZonedDateTimeUtils +import app.myzel394.numberhub.feature.datecalculator.components.DateTimeDialogs +import app.myzel394.numberhub.feature.datecalculator.components.DateTimeSelectorBlock +import app.myzel394.numberhub.feature.datecalculator.components.DialogState +import app.myzel394.numberhub.feature.datecalculator.components.TimeUnitTextField import java.time.ZonedDateTime @Composable @@ -98,7 +98,7 @@ internal fun AddSubtractPage( @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable private fun AddSubtractView( - uiState: AddSubtractState, + uiState: AddSubtractUIState, updateStart: (ZonedDateTime) -> Unit, updateYears: (TextFieldValue) -> Unit, updateMonths: (TextFieldValue) -> Unit, @@ -124,7 +124,7 @@ private fun AddSubtractView( FloatingActionButton( onClick = { mContext.createEvent(uiState.start, uiState.result) - } + }, ) { Icon( imageVector = Icons.Default.Event, @@ -132,7 +132,7 @@ private fun AddSubtractView( ) } }, - contentWindowInsets = WindowInsets(0, 0, 0, 0) + contentWindowInsets = WindowInsets(0, 0, 0, 0), ) { Column( modifier = Modifier @@ -140,17 +140,16 @@ private fun AddSubtractView( .padding(horizontal = 16.dp, vertical = 16.dp), verticalArrangement = Arrangement.spacedBy(12.dp), ) { - AnimatedContent( targetState = showResult, label = "Reveal result", transitionSpec = { fadeIn() togetherWith fadeOut() using SizeTransform() }, - modifier = Modifier.clip(RoundedCornerShape(32.dp)) + modifier = Modifier.clip(RoundedCornerShape(32.dp)), ) { show -> FlowRow( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), ) { DateTimeSelectorBlock( modifier = Modifier @@ -184,7 +183,7 @@ private fun AddSubtractView( selected = uiState.addition, onClick = { updateAddition(true) }, shape = SegmentedButtonDefaults.itemShape(index = 0, count = 2), - icon = {} + icon = {}, ) { Icon(Icons.Outlined.Add, stringResource(R.string.date_calculator_add)) } @@ -192,11 +191,11 @@ private fun AddSubtractView( selected = !uiState.addition, onClick = { updateAddition(false) }, shape = SegmentedButtonDefaults.itemShape(index = 1, count = 2), - icon = {} + icon = {}, ) { Icon( Icons.Outlined.Remove, - stringResource(R.string.date_calculator_subtract) + stringResource(R.string.date_calculator_subtract), ) } } @@ -206,10 +205,10 @@ private fun AddSubtractView( .fillMaxWidth() .background( MaterialTheme.colorScheme.secondaryContainer, - RoundedCornerShape(32.dp) + RoundedCornerShape(32.dp), ) .padding(16.dp, 24.dp), - verticalArrangement = Arrangement.spacedBy(4.dp) + verticalArrangement = Arrangement.spacedBy(4.dp), ) { TimeUnitTextField( modifier = Modifier.fillMaxWidth(), @@ -221,7 +220,7 @@ private fun AddSubtractView( Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { TimeUnitTextField( modifier = Modifier.weight(1f), @@ -242,7 +241,7 @@ private fun AddSubtractView( Row( modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { TimeUnitTextField( modifier = Modifier.weight(1f), @@ -258,7 +257,7 @@ private fun AddSubtractView( onValueChange = updateMinutes, label = stringResource(R.string.date_calculator_minutes), expressionFormatter = expressionTransformer, - imeAction = ImeAction.Done + imeAction = ImeAction.Done, ) } } @@ -296,10 +295,10 @@ private fun Context.createEvent(start: ZonedDateTime, end: ZonedDateTime) { @Composable fun AddSubtractViewPreview() { AddSubtractView( - uiState = AddSubtractState( + uiState = AddSubtractUIState( years = TextFieldValue("12"), start = ZonedDateTimeUtils.nowWithMinutes(), - result = ZonedDateTimeUtils.nowWithMinutes().plusSeconds(1) + result = ZonedDateTimeUtils.nowWithMinutes().plusSeconds(1), ), updateStart = {}, updateYears = {}, diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractUIState.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractUIState.kt similarity index 77% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractUIState.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractUIState.kt index dfa33347..7cf2aefe 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractUIState.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractUIState.kt @@ -16,14 +16,15 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.addsubtract +package app.myzel394.numberhub.feature.datecalculator.addsubtract import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.feature.datecalculator.ZonedDateTimeUtils +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.feature.datecalculator.ZonedDateTimeUtils import java.time.ZonedDateTime -internal data class AddSubtractState( +internal data class AddSubtractUIState( val start: ZonedDateTime = ZonedDateTimeUtils.nowWithMinutes(), val result: ZonedDateTime = ZonedDateTimeUtils.nowWithMinutes(), val years: TextFieldValue = TextFieldValue(), @@ -32,6 +33,6 @@ internal data class AddSubtractState( val hours: TextFieldValue = TextFieldValue(), val minutes: TextFieldValue = TextFieldValue(), val addition: Boolean = true, - val formatterSymbols: FormatterSymbols = FormatterSymbols.Spaces, + val formatterSymbols: FormatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), val allowVibration: Boolean = false, ) diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractViewModel.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractViewModel.kt similarity index 88% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractViewModel.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractViewModel.kt index 2e2d8703..44f06679 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/addsubtract/AddSubtractViewModel.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/addsubtract/AddSubtractViewModel.kt @@ -16,14 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.addsubtract +package app.myzel394.numberhub.feature.datecalculator.addsubtract import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -39,18 +38,18 @@ import javax.inject.Inject @HiltViewModel internal class AddSubtractViewModel @Inject constructor( - userPreferencesRepository: UserPreferencesRepository + userPreferencesRepository: UserPreferencesRepository, ) : ViewModel() { - private val _uiState = MutableStateFlow(AddSubtractState()) + private val _uiState = MutableStateFlow(AddSubtractUIState()) - val uiState: StateFlow = _uiState + val uiState: StateFlow = _uiState .combine(userPreferencesRepository.addSubtractPrefs) { uiState, userPrefs -> return@combine uiState.copy( - formatterSymbols = AllFormatterSymbols.getById(userPrefs.separator), + formatterSymbols = userPrefs.formatterSymbols, ) } .onEach { updateResult() } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), AddSubtractState()) + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), AddSubtractUIState()) fun updateStart(newValue: ZonedDateTime) = _uiState.update { it.copy(start = newValue) } diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeDialogs.kt similarity index 89% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeDialogs.kt index fe5f9990..86a7f221 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeDialogs.kt @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.components +package app.myzel394.numberhub.feature.datecalculator.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.datetimepicker.DatePickerDialog -import com.sadellie.unitto.core.ui.common.datetimepicker.TimePickerDialog +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.datetimepicker.DatePickerDialog +import app.myzel394.numberhub.core.ui.common.datetimepicker.TimePickerDialog import java.time.ZonedDateTime @Composable @@ -68,7 +68,7 @@ internal fun DateTimeDialogs( onConfirm = { updateDate(it) updateDialogState(DialogState.NONE) - } + }, ) } diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeResultBlock.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeResultBlock.kt similarity index 90% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeResultBlock.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeResultBlock.kt index 5513126f..4047d5cc 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeResultBlock.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeResultBlock.kt @@ -16,12 +16,11 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.components +package app.myzel394.numberhub.feature.datecalculator.components import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -30,34 +29,34 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.PagedIsland -import com.sadellie.unitto.feature.datecalculator.difference.ZonedDateTimeDifference +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.PagedIsland +import app.myzel394.numberhub.feature.datecalculator.difference.ZonedDateTimeDifference import java.math.BigDecimal @Composable internal fun DateTimeResultBlock( modifier: Modifier = Modifier, diff: ZonedDateTimeDifference.Default, - format: (BigDecimal) -> String + format: (BigDecimal) -> String, ) { val focusManager = LocalFocusManager.current PagedIsland( modifier = modifier, - pagerState = rememberPagerState { 6 }, + pageCount = 6, onClick = { focusManager.clearFocus() }, - backgroundColor = MaterialTheme.colorScheme.tertiaryContainer + backgroundColor = MaterialTheme.colorScheme.tertiaryContainer, ) { currentPage -> - when(currentPage) { + when (currentPage) { 0 -> { Column( modifier = Modifier - .fillMaxWidth() + .fillMaxWidth(), ) { Text( text = stringResource(R.string.date_calculator_difference), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) SelectionContainer { Column { @@ -94,7 +93,7 @@ internal fun DateTimeResultBlock( Column { Text( text = stringResource(R.string.date_calculator_years), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) SelectionContainer { DateText(diff.sumYears, format) @@ -106,7 +105,7 @@ internal fun DateTimeResultBlock( Column { Text( text = stringResource(R.string.date_calculator_months), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) SelectionContainer { DateText(diff.sumMonths, format) @@ -118,7 +117,7 @@ internal fun DateTimeResultBlock( Column { Text( text = stringResource(R.string.date_calculator_days), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) SelectionContainer { DateText(diff.sumDays, format) @@ -130,7 +129,7 @@ internal fun DateTimeResultBlock( Column { Text( text = stringResource(R.string.date_calculator_hours), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) SelectionContainer { DateText(diff.sumHours, format) @@ -142,7 +141,7 @@ internal fun DateTimeResultBlock( Column { Text( text = stringResource(R.string.date_calculator_minutes), - style = MaterialTheme.typography.labelMedium + style = MaterialTheme.typography.labelMedium, ) SelectionContainer { DateText(diff.sumMinutes, format) @@ -160,7 +159,7 @@ private fun DateText( format: (BigDecimal) -> String, ) = Text( text = "${stringResource(id)}: ${format(value)}", - style = MaterialTheme.typography.displaySmall + style = MaterialTheme.typography.displaySmall, ) @Composable @@ -169,7 +168,7 @@ private fun DateText( format: (BigDecimal) -> String, ) = Text( text = format(value), - style = MaterialTheme.typography.displaySmall + style = MaterialTheme.typography.displaySmall, ) @Preview @@ -189,6 +188,6 @@ private fun DateTimeResultBlockPreview() { sumHours = BigDecimal.ZERO, sumMinutes = BigDecimal("46080"), ), - format = { it.toPlainString() } + format = { it.toPlainString() }, ) } diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeSelectorBlock.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeSelectorBlock.kt similarity index 85% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeSelectorBlock.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeSelectorBlock.kt index bede241c..bc5a423f 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeSelectorBlock.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/DateTimeSelectorBlock.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.components +package app.myzel394.numberhub.feature.datecalculator.components import android.text.format.DateFormat import androidx.compose.animation.AnimatedContent @@ -44,13 +44,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.LocalLocale -import com.sadellie.unitto.core.ui.common.ProvideColor -import com.sadellie.unitto.core.ui.common.squashable -import com.sadellie.unitto.core.ui.datetime.formatDateWeekDayMonthYear -import com.sadellie.unitto.core.ui.datetime.formatTimeAmPm -import com.sadellie.unitto.core.ui.datetime.formatTimeShort -import com.sadellie.unitto.feature.datecalculator.ZonedDateTimeUtils +import app.myzel394.numberhub.core.ui.LocalLocale +import app.myzel394.numberhub.core.ui.common.ProvideColor +import app.myzel394.numberhub.core.ui.common.squashable +import app.myzel394.numberhub.core.ui.datetime.formatDateWeekDayMonthYear +import app.myzel394.numberhub.core.ui.datetime.formatTimeAmPm +import app.myzel394.numberhub.core.ui.datetime.formatTimeShort +import app.myzel394.numberhub.feature.datecalculator.ZonedDateTimeUtils import java.time.ZonedDateTime @Composable @@ -68,7 +68,7 @@ internal fun DateTimeSelectorBlock( val is24Hour = DateFormat.is24HourFormat(LocalContext.current) ProvideColor( - MaterialTheme.colorScheme.contentColorFor(containerColor) + MaterialTheme.colorScheme.contentColorFor(containerColor), ) { Column( modifier = Modifier @@ -76,12 +76,12 @@ internal fun DateTimeSelectorBlock( onClick = onClick, onLongClick = onLongClick, interactionSource = remember { MutableInteractionSource() }, - cornerRadiusRange = 8.dp..32.dp + cornerRadiusRange = 8.dp..32.dp, ) .background(containerColor) .then(modifier) .padding(16.dp), - horizontalAlignment = Alignment.Start + horizontalAlignment = Alignment.Start, ) { Text( text = title, @@ -93,22 +93,22 @@ internal fun DateTimeSelectorBlock( modifier = Modifier.clickable( indication = rememberRipple(), interactionSource = remember { MutableInteractionSource() }, - onClick = onTimeClick - ) + onClick = onTimeClick, + ), ) { AnimatedContent( targetState = dateTime, transitionSpec = { slideInVertically { height -> height } + fadeIn() togetherWith - slideOutVertically { height -> -height } + fadeOut() using - SizeTransform() + slideOutVertically { height -> -height } + fadeOut() using + SizeTransform() }, label = "Animated time", ) { time -> Text( text = time.formatTimeShort(locale, is24Hour), style = MaterialTheme.typography.displaySmall, - maxLines = 1 + maxLines = 1, ) } @@ -117,15 +117,15 @@ internal fun DateTimeSelectorBlock( targetState = dateTime, transitionSpec = { slideInVertically { height -> height } + fadeIn() togetherWith - slideOutVertically { height -> -height } + fadeOut() using - SizeTransform() + slideOutVertically { height -> -height } + fadeOut() using + SizeTransform() }, label = "Animated am/pm", ) { time -> Text( text = time.formatTimeAmPm(locale), style = MaterialTheme.typography.bodyLarge, - maxLines = 1 + maxLines = 1, ) } } @@ -135,8 +135,8 @@ internal fun DateTimeSelectorBlock( targetState = dateTime, transitionSpec = { slideInVertically { height -> height } + fadeIn() togetherWith - slideOutVertically { height -> -height } + fadeOut() using - SizeTransform() + slideOutVertically { height -> -height } + fadeOut() using + SizeTransform() }, label = "Animated date", ) { date -> @@ -144,11 +144,11 @@ internal fun DateTimeSelectorBlock( modifier = Modifier.clickable( indication = rememberRipple(), interactionSource = remember { MutableInteractionSource() }, - onClick = onDateClick + onClick = onDateClick, ), text = date.formatDateWeekDayMonthYear(locale), style = MaterialTheme.typography.bodySmall, - maxLines = 1 + maxLines = 1, ) } } diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/TimeUnitTextField.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/TimeUnitTextField.kt similarity index 92% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/TimeUnitTextField.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/TimeUnitTextField.kt index 6d4f44ef..b16dbcd3 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/TimeUnitTextField.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/components/TimeUnitTextField.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.components +package app.myzel394.numberhub.feature.datecalculator.components import androidx.compose.animation.AnimatedContent import androidx.compose.material3.MaterialTheme @@ -27,7 +27,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.VisualTransformation -import com.sadellie.unitto.core.ui.common.textfield.OutlinedDecimalTextField +import app.myzel394.numberhub.core.ui.common.textfield.OutlinedDecimalTextField @Composable internal fun TimeUnitTextField( @@ -51,6 +51,6 @@ internal fun TimeUnitTextField( unfocusedTextColor = MaterialTheme.colorScheme.onSecondaryContainer, ), expressionFormatter = expressionFormatter, - imeAction = imeAction + imeAction = imeAction, ) } diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DateDifferencePage.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DateDifferencePage.kt similarity index 85% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DateDifferencePage.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DateDifferencePage.kt index 0d89011d..c62911cb 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DateDifferencePage.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DateDifferencePage.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.difference +package app.myzel394.numberhub.feature.datecalculator.difference import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.background @@ -40,16 +40,17 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.feature.datecalculator.ZonedDateTimeUtils -import com.sadellie.unitto.feature.datecalculator.components.DateTimeDialogs -import com.sadellie.unitto.feature.datecalculator.components.DateTimeResultBlock -import com.sadellie.unitto.feature.datecalculator.components.DateTimeSelectorBlock -import com.sadellie.unitto.feature.datecalculator.components.DialogState +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.feature.datecalculator.ZonedDateTimeUtils +import app.myzel394.numberhub.feature.datecalculator.components.DateTimeDialogs +import app.myzel394.numberhub.feature.datecalculator.components.DateTimeResultBlock +import app.myzel394.numberhub.feature.datecalculator.components.DateTimeSelectorBlock +import app.myzel394.numberhub.feature.datecalculator.components.DialogState import java.math.BigDecimal import java.time.ZonedDateTime import java.time.temporal.ChronoUnit @@ -63,7 +64,7 @@ internal fun DateDifferencePage( is DifferenceUIState.Ready -> DateDifferenceView( uiState = uiState, setStartDate = viewModel::setStartDate, - setEndDate = viewModel::setEndDate + setEndDate = viewModel::setEndDate, ) } } @@ -80,7 +81,7 @@ private fun DateDifferenceView( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), ) { FlowRow( modifier = Modifier @@ -88,7 +89,7 @@ private fun DateDifferenceView( .fillMaxWidth(), maxItemsInEachRow = 2, verticalArrangement = Arrangement.spacedBy(8.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { DateTimeSelectorBlock( modifier = Modifier @@ -101,7 +102,7 @@ private fun DateDifferenceView( onLongClick = { setStartDate(ZonedDateTimeUtils.nowWithMinutes()) }, onTimeClick = { dialogState = DialogState.FROM_TIME }, onDateClick = { dialogState = DialogState.FROM_DATE }, - containerColor = MaterialTheme.colorScheme.secondaryContainer + containerColor = MaterialTheme.colorScheme.secondaryContainer, ) DateTimeSelectorBlock( @@ -115,14 +116,14 @@ private fun DateDifferenceView( onLongClick = { setEndDate(ZonedDateTimeUtils.nowWithMinutes()) }, onTimeClick = { dialogState = DialogState.TO_TIME }, onDateClick = { dialogState = DialogState.TO_DATE }, - containerColor = MaterialTheme.colorScheme.secondaryContainer + containerColor = MaterialTheme.colorScheme.secondaryContainer, ) } AnimatedContent( targetState = uiState.result, label = "Result reveal", - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), ) { result -> when (result) { is ZonedDateTimeDifference.Default -> { @@ -134,7 +135,7 @@ private fun DateDifferenceView( format = { it.format(uiState.precision, uiState.outputFormat) .formatExpression(uiState.formatterSymbols) - } + }, ) } ZonedDateTimeDifference.Zero -> Unit @@ -163,7 +164,6 @@ private fun DateDifferenceView( ) } - @Preview @Composable fun DateDifferenceViewPreview() { @@ -185,7 +185,7 @@ fun DateDifferenceViewPreview() { ), precision = 3, outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), ), setStartDate = {}, setEndDate = {}, diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DateDifferenceViewModel.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DateDifferenceViewModel.kt similarity index 60% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DateDifferenceViewModel.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DateDifferenceViewModel.kt index f0ef5e91..81ae841e 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DateDifferenceViewModel.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DateDifferenceViewModel.kt @@ -16,14 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.difference +package app.myzel394.numberhub.feature.datecalculator.difference import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.feature.datecalculator.ZonedDateTimeUtils +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.feature.datecalculator.ZonedDateTimeUtils import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -39,46 +38,47 @@ import javax.inject.Inject internal class DateDifferenceViewModel @Inject constructor( userPrefsRepository: UserPreferencesRepository, ) : ViewModel() { - private val _start = MutableStateFlow(ZonedDateTimeUtils.nowWithMinutes()) - private val _end = MutableStateFlow(ZonedDateTimeUtils.nowWithMinutes()) - private val _result = MutableStateFlow(ZonedDateTimeDifference.Zero) + private val start = MutableStateFlow(ZonedDateTimeUtils.nowWithMinutes()) + private val end = MutableStateFlow(ZonedDateTimeUtils.nowWithMinutes()) + private val result = MutableStateFlow(ZonedDateTimeDifference.Zero) val uiState: StateFlow = combine( userPrefsRepository.formattingPrefs, - _start, - _end, - _result + start, + end, + result, ) { prefs, start, end, result -> - return@combine DifferenceUIState.Ready( - start = start, - end = end, - result = result, - precision = prefs.digitsPrecision, - outputFormat = prefs.outputFormat, - formatterSymbols = AllFormatterSymbols.getById(prefs.separator) - ) - } + return@combine DifferenceUIState.Ready( + start = start, + end = end, + result = result, + precision = prefs.digitsPrecision, + outputFormat = prefs.outputFormat, + formatterSymbols = prefs.formatterSymbols, + ) + } .mapLatest { ui -> updateResult( start = ui.start, - end = ui.end + end = ui.end, ) ui } .stateIn( - viewModelScope, DifferenceUIState.Loading + viewModelScope, + DifferenceUIState.Loading, ) - fun setStartDate(newValue: ZonedDateTime) = _start.update { newValue } + fun setStartDate(newValue: ZonedDateTime) = start.update { newValue } - fun setEndDate(newValue: ZonedDateTime) = _end.update { newValue } + fun setEndDate(newValue: ZonedDateTime) = end.update { newValue } private fun updateResult( start: ZonedDateTime, - end: ZonedDateTime + end: ZonedDateTime, ) = viewModelScope.launch(Dispatchers.Default) { - _result.update { + result.update { try { start - end } catch (e: Exception) { diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DifferenceUIState.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DifferenceUIState.kt similarity index 89% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DifferenceUIState.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DifferenceUIState.kt index ef43dbab..7463c3f1 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/DifferenceUIState.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/DifferenceUIState.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.difference +package app.myzel394.numberhub.feature.datecalculator.difference -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.FormatterSymbols import java.time.ZonedDateTime internal sealed class DifferenceUIState { diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/ZonedDateTimeDifference.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/ZonedDateTimeDifference.kt similarity index 96% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/ZonedDateTimeDifference.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/ZonedDateTimeDifference.kt index bfd9ed61..6c4fa504 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/difference/ZonedDateTimeDifference.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/difference/ZonedDateTimeDifference.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.difference +package app.myzel394.numberhub.feature.datecalculator.difference -import com.sadellie.unitto.core.base.MAX_PRECISION +import app.myzel394.numberhub.core.base.MAX_PRECISION import java.math.BigDecimal import java.math.RoundingMode import java.time.ZonedDateTime @@ -49,7 +49,7 @@ internal sealed class ZonedDateTimeDifference { * @return [ZonedDateTimeDifference.Default] (_always positive_) or [ZonedDateTimeDifference.Zero] */ internal infix operator fun ZonedDateTime.minus( - zonedDateTime: ZonedDateTime + zonedDateTime: ZonedDateTime, ): ZonedDateTimeDifference = this.minus(zonedDateTime = zonedDateTime, scale = MAX_PRECISION) /** @@ -64,7 +64,7 @@ internal infix operator fun ZonedDateTime.minus( */ internal fun ZonedDateTime.minus( zonedDateTime: ZonedDateTime, - scale: Int + scale: Int, ): ZonedDateTimeDifference { // https://stackoverflow.com/a/25760725 diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/navigation/DateCalculatorNavigation.kt b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/navigation/DateCalculatorNavigation.kt similarity index 68% rename from feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/navigation/DateCalculatorNavigation.kt rename to feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/navigation/DateCalculatorNavigation.kt index 767b8819..7ed5265e 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/navigation/DateCalculatorNavigation.kt +++ b/feature/datecalculator/src/main/java/app/myzel394/numberhub/feature/datecalculator/navigation/DateCalculatorNavigation.kt @@ -16,33 +16,31 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.navigation +package app.myzel394.numberhub.feature.datecalculator.navigation import androidx.navigation.NavGraphBuilder import androidx.navigation.navDeepLink -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.unittoComposable -import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.feature.datecalculator.DateCalculatorRoute +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.unittoComposable +import app.myzel394.numberhub.core.ui.unittoNavigation +import app.myzel394.numberhub.feature.datecalculator.DateCalculatorRoute private val graph = DrawerItem.DateCalculator.graph private val start = DrawerItem.DateCalculator.start fun NavGraphBuilder.dateCalculatorGraph( - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit + openDrawer: () -> Unit, ) { unittoNavigation( startDestination = start, route = graph, deepLinks = listOf( - navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" } - ) + navDeepLink { uriPattern = "app://app.myzel394.numberhub/$graph" }, + ), ) { unittoComposable(start) { DateCalculatorRoute( - navigateToMenu = navigateToMenu, - navigateToSettings = navigateToSettings + openDrawer = openDrawer, ) } } diff --git a/feature/datecalculator/src/test/java/com/sadellie/unitto/feature/datecalculator/difference/ZonedDateTimeDifferenceKtTest.kt b/feature/datecalculator/src/test/java/app/myzel394/numberhub/feature/datecalculator/difference/ZonedDateTimeDifferenceKtTest.kt similarity index 85% rename from feature/datecalculator/src/test/java/com/sadellie/unitto/feature/datecalculator/difference/ZonedDateTimeDifferenceKtTest.kt rename to feature/datecalculator/src/test/java/app/myzel394/numberhub/feature/datecalculator/difference/ZonedDateTimeDifferenceKtTest.kt index d509842b..e661afa9 100644 --- a/feature/datecalculator/src/test/java/com/sadellie/unitto/feature/datecalculator/difference/ZonedDateTimeDifferenceKtTest.kt +++ b/feature/datecalculator/src/test/java/app/myzel394/numberhub/feature/datecalculator/difference/ZonedDateTimeDifferenceKtTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.datecalculator.difference +package app.myzel394.numberhub.feature.datecalculator.difference import org.junit.Assert.assertEquals import org.junit.Test @@ -40,20 +40,20 @@ class ZonedDateTimeDifferenceKtTest { val date2: ZonedDateTime = ZonedDateTime.parse("2023-05-02T12:00+01:00[Europe/Paris]", formatter) assertEquals( - ZonedDateTimeDifference. - Default( - years = 0, - months = 0, - days = 1, - hours = 0, - minutes = 0, - sumYears = BigDecimal("0.003"), - sumMonths = BigDecimal("0.033"), - sumDays = BigDecimal("1.000"), - sumHours = BigDecimal("24.000"), - sumMinutes = BigDecimal("1440.000"), - ), - date1.minus(date2, 3) + ZonedDateTimeDifference + .Default( + years = 0, + months = 0, + days = 1, + hours = 0, + minutes = 0, + sumYears = BigDecimal("0.003"), + sumMonths = BigDecimal("0.033"), + sumDays = BigDecimal("1.000"), + sumHours = BigDecimal("24.000"), + sumMinutes = BigDecimal("1440.000"), + ), + date1.minus(date2, 3), ) } @@ -75,7 +75,7 @@ class ZonedDateTimeDifferenceKtTest { sumHours = BigDecimal("744.000"), sumMinutes = BigDecimal("44640.000"), ), - date1.minus(date2, 3) + date1.minus(date2, 3), ) } @@ -97,7 +97,7 @@ class ZonedDateTimeDifferenceKtTest { sumHours = BigDecimal("24.000"), sumMinutes = BigDecimal("1440.000"), ), - date1.minus(date2, 3) + date1.minus(date2, 3), ) } @@ -119,7 +119,7 @@ class ZonedDateTimeDifferenceKtTest { sumHours = BigDecimal("744.000"), sumMinutes = BigDecimal("44640.000"), ), - date1.minus(date2, 3) + date1.minus(date2, 3), ) } @@ -141,7 +141,7 @@ class ZonedDateTimeDifferenceKtTest { sumHours = BigDecimal("720.000"), sumMinutes = BigDecimal("43200.000"), ), - date1.minus(date2, 3) + date1.minus(date2, 3), ) } } diff --git a/feature/glance/build.gradle.kts b/feature/glance/build.gradle.kts index 61134fdd..b49e1710 100644 --- a/feature/glance/build.gradle.kts +++ b/feature/glance/build.gradle.kts @@ -24,7 +24,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.glance" +android.namespace = "app.myzel394.numberhub.feature.glance" dependencies { implementation(libs.androidx.glance.glance) diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/CalculatorWidget.kt similarity index 84% rename from feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt rename to feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/CalculatorWidget.kt index a73df471..e4c401ad 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidget.kt +++ b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/CalculatorWidget.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.glance.glance +package app.myzel394.numberhub.feature.glance.glance import android.content.Context import android.util.Log @@ -54,13 +54,12 @@ import androidx.glance.text.Text import androidx.glance.text.TextAlign import androidx.glance.text.TextStyle import androidx.glance.unit.ColorProvider -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.data.model.userprefs.CalculatorPreferences -import com.sadellie.unitto.feature.glance.R +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.model.userprefs.CalculatorPreferences +import app.myzel394.numberhub.feature.glance.R import dagger.hilt.EntryPoint import dagger.hilt.EntryPoints import dagger.hilt.InstallIn @@ -75,7 +74,7 @@ class CalculatorWidget : GlanceAppWidget() { } override val sizeMode = SizeMode.Responsive( - setOf(SMALL, BIG) + setOf(SMALL, BIG), ) override val stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition @@ -120,7 +119,7 @@ private fun LoadingUI() { .appWidgetBackground() .background(GlanceTheme.colors.background) .fillMaxSize(), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { IconButton( glanceModifier = GlanceModifier, @@ -139,23 +138,23 @@ private fun ReadyUI( val input = glancePrefs[CalculatorWidget.inputPrefKey] ?: "" val output = glancePrefs[CalculatorWidget.outputPrefKey] ?: "" val equalClicked = glancePrefs[CalculatorWidget.equalClickedPrefKey] ?: false - val formatterSymbols = AllFormatterSymbols.getById(appPrefs.separator) + val formatterSymbols = appPrefs.formatterSymbols fun runCalculateAction( input: String, - equalClicked: Boolean = false + equalClicked: Boolean = false, ): Action = updateInputAction( input = input, equalClicked = equalClicked, precision = appPrefs.precision, - outputFormat = appPrefs.outputFormat + outputFormat = appPrefs.outputFormat, ) Column( modifier = GlanceModifier .appWidgetBackground() .background(GlanceTheme.colors.background) - .fillMaxSize() + .fillMaxSize(), ) { val uiSectionModifier = GlanceModifier.fillMaxWidth() @@ -164,7 +163,7 @@ private fun ReadyUI( modifier = uiSectionModifier .background(GlanceTheme.colors.surfaceVariant), output = output, - formatterSymbols = formatterSymbols + formatterSymbols = formatterSymbols, ) } @@ -174,7 +173,7 @@ private fun ReadyUI( .defaultWeight(), input = input, formatterSymbols = formatterSymbols, - output = output + output = output, ) GlanceKeyboard( @@ -183,7 +182,7 @@ private fun ReadyUI( runCalculateAction( // Clear input if equal is clicked and new token is a Digit (if (equalClicked and Token.Digit.allWithDot.contains(it)) "" else input) - .addToken(it) + .addToken(it), ) }, clearInputAction = { @@ -201,7 +200,7 @@ private fun ReadyUI( runCalculateAction(output, true) }, useDot = formatterSymbols.fractional == Token.Digit.dot, - middleZero = appPrefs.middleZero + middleZero = appPrefs.middleZero, ) } } @@ -213,7 +212,7 @@ private fun ActionButtons( formatterSymbols: FormatterSymbols, ) { Row( - modifier = modifier + modifier = modifier, ) { val buttonModifier = GlanceModifier.fillMaxWidth().defaultWeight() @@ -223,14 +222,14 @@ private fun ActionButtons( iconRes = R.drawable.content_copy, onClick = copyAction( output = output, - fractional = formatterSymbols.fractional - ) + fractional = formatterSymbols.fractional, + ), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primary, iconRes = R.drawable.open_in_new, - onClick = launchAction(LocalContext.current) + onClick = launchAction(LocalContext.current), ) } } @@ -244,7 +243,7 @@ private fun TextFields( ) { Column( modifier = modifier, - verticalAlignment = Alignment.Bottom + verticalAlignment = Alignment.Bottom, ) { val textModifier = GlanceModifier.fillMaxWidth() @@ -255,8 +254,8 @@ private fun TextFields( style = TextStyle( fontSize = 36.sp, textAlign = TextAlign.End, - color = GlanceTheme.colors.onSurfaceVariant - ) + color = GlanceTheme.colors.onSurfaceVariant, + ), ) Text( text = output.formatExpression(formatterSymbols), @@ -265,8 +264,8 @@ private fun TextFields( style = TextStyle( fontSize = 36.sp, textAlign = TextAlign.End, - color = GlanceTheme.colors.onSurfaceVariant.withAlpha(alpha = 0.5f) - ) + color = GlanceTheme.colors.onSurfaceVariant.withAlpha(alpha = 0.5f), + ), ) } } @@ -291,25 +290,25 @@ private fun GlanceKeyboard( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.tertiaryContainer, iconRes = R.drawable.clear, - onClick = clearInputAction() + onClick = clearInputAction(), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.brackets, - onClick = addBracketAction() + onClick = addBracketAction(), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.percent, - onClick = addTokenAction(Token.Operator.percent) + onClick = addTokenAction(Token.Operator.percent), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.divide, - onClick = addTokenAction(Token.Operator.divide) + onClick = addTokenAction(Token.Operator.divide), ) } Row(rowModifier) { @@ -319,25 +318,25 @@ private fun GlanceKeyboard( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key7, - onClick = addTokenAction(Token.Digit._7) + onClick = addTokenAction(Token.Digit._7), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key8, - onClick = addTokenAction(Token.Digit._8) + onClick = addTokenAction(Token.Digit._8), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key9, - onClick = addTokenAction(Token.Digit._9) + onClick = addTokenAction(Token.Digit._9), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.multiply, - onClick = addTokenAction(Token.Operator.multiply) + onClick = addTokenAction(Token.Operator.multiply), ) } Row(rowModifier) { @@ -347,25 +346,25 @@ private fun GlanceKeyboard( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key4, - onClick = addTokenAction(Token.Digit._4) + onClick = addTokenAction(Token.Digit._4), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key5, - onClick = addTokenAction(Token.Digit._5) + onClick = addTokenAction(Token.Digit._5), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key6, - onClick = addTokenAction(Token.Digit._6) + onClick = addTokenAction(Token.Digit._6), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.minus, - onClick = addTokenAction(Token.Operator.minus) + onClick = addTokenAction(Token.Operator.minus), ) } Row(rowModifier) { @@ -375,25 +374,25 @@ private fun GlanceKeyboard( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key1, - onClick = addTokenAction(Token.Digit._1) + onClick = addTokenAction(Token.Digit._1), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key2, - onClick = addTokenAction(Token.Digit._2) + onClick = addTokenAction(Token.Digit._2), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key3, - onClick = addTokenAction(Token.Digit._3) + onClick = addTokenAction(Token.Digit._3), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.plus, - onClick = addTokenAction(Token.Operator.plus) + onClick = addTokenAction(Token.Operator.plus), ) } Row(rowModifier) { @@ -404,39 +403,39 @@ private fun GlanceKeyboard( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = if (useDot) R.drawable.dot else R.drawable.comma, - onClick = addTokenAction(Token.Digit.dot) + onClick = addTokenAction(Token.Digit.dot), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key0, - onClick = addTokenAction(Token.Digit._0) + onClick = addTokenAction(Token.Digit._0), ) } else { IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.key0, - onClick = addTokenAction(Token.Digit._0) + onClick = addTokenAction(Token.Digit._0), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = if (useDot) R.drawable.dot else R.drawable.comma, - onClick = addTokenAction(Token.Digit.dot) + onClick = addTokenAction(Token.Digit.dot), ) } IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.inverseOnSurface, iconRes = R.drawable.backspace, - onClick = deleteTokenAction() + onClick = deleteTokenAction(), ) IconButton( glanceModifier = buttonModifier, containerColor = GlanceTheme.colors.primaryContainer, iconRes = R.drawable.equal, - onClick = equalAction() + onClick = equalAction(), ) } } @@ -446,5 +445,5 @@ private fun ColorProvider.withAlpha(alpha: Float): ColorProvider = ColorProvider( this .getColor(LocalContext.current) - .copy(alpha = alpha) + .copy(alpha = alpha), ) diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidgetReceiver.kt b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/CalculatorWidgetReceiver.kt similarity index 94% rename from feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidgetReceiver.kt rename to feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/CalculatorWidgetReceiver.kt index 70dc2910..2bccd495 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/CalculatorWidgetReceiver.kt +++ b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/CalculatorWidgetReceiver.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.glance.glance +package app.myzel394.numberhub.feature.glance.glance import androidx.glance.appwidget.GlanceAppWidget import androidx.glance.appwidget.GlanceAppWidgetReceiver diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/IconButton.kt similarity index 90% rename from feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt rename to feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/IconButton.kt index 128e8fc3..cd44aadd 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/IconButton.kt +++ b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/IconButton.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.glance.glance +package app.myzel394.numberhub.feature.glance.glance import android.content.Context import android.os.Build @@ -43,7 +43,7 @@ import androidx.glance.layout.fillMaxWidth import androidx.glance.layout.height import androidx.glance.layout.padding import androidx.glance.unit.ColorProvider -import com.sadellie.unitto.feature.glance.R +import app.myzel394.numberhub.feature.glance.R @Composable internal fun IconButton( @@ -57,7 +57,7 @@ internal fun IconButton( modifier = glanceModifier .height(48.dp) .padding(4.dp), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { Image( modifier = GlanceModifier @@ -66,12 +66,12 @@ internal fun IconButton( .cornerRadius( context = LocalContext.current, cornerRadius = 24.dp, - color = containerColor + color = containerColor, ) .padding(horizontal = 16.dp, vertical = 8.dp), provider = ImageProvider(iconRes), contentDescription = null, - colorFilter = ColorFilter.tint(contentColor) + colorFilter = ColorFilter.tint(contentColor), ) } } @@ -101,8 +101,8 @@ fun GlanceModifier.cornerRadius( // fucking .toIcon(context) // stupid - .setTint(color.getColor(context).toArgb()) - ) - ) - else -> this.background(color) - } + .setTint(color.getColor(context).toArgb()), + ), + ) + else -> this.background(color) +} diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/StringUtils.kt b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/StringUtils.kt similarity index 85% rename from feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/StringUtils.kt rename to feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/StringUtils.kt index 947371a2..d5ddb6ef 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/StringUtils.kt +++ b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/StringUtils.kt @@ -16,12 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.glance.glance +package app.myzel394.numberhub.feature.glance.glance import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.core.ui.common.textfield.addBracket -import com.sadellie.unitto.core.ui.common.textfield.addTokens +import app.myzel394.numberhub.core.ui.common.textfield.addBracket +import app.myzel394.numberhub.core.ui.common.textfield.addTokens internal fun String.addToken(token: String): String = TextFieldValue(this, TextRange(length)).addTokens(token).text diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/UpdateInputAction.kt b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/UpdateInputAction.kt similarity index 88% rename from feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/UpdateInputAction.kt rename to feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/UpdateInputAction.kt index 5bd7c286..d6e06d03 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/UpdateInputAction.kt +++ b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/UpdateInputAction.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.glance.glance +package app.myzel394.numberhub.feature.glance.glance import android.content.ClipData import android.content.ClipboardManager @@ -30,9 +30,9 @@ import androidx.glance.action.actionStartActivity import androidx.glance.appwidget.action.ActionCallback import androidx.glance.appwidget.action.actionRunCallback import androidx.glance.appwidget.state.updateAppWidgetState -import com.sadellie.unitto.core.base.Token -import com.sadellie.unitto.data.common.format -import com.sadellie.unitto.data.common.isExpression +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.data.common.format +import app.myzel394.numberhub.data.common.isExpression import io.github.sadellie.evaluatto.Expression import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -41,7 +41,7 @@ internal class UpdateInputAction : ActionCallback { override suspend fun onAction( context: Context, glanceId: GlanceId, - parameters: ActionParameters + parameters: ActionParameters, ) = withContext(Dispatchers.Default) { // Get new input val input = parameters[CalculatorWidget.inputKey] ?: return@withContext @@ -89,7 +89,7 @@ internal class RestartWidget : ActionCallback { override suspend fun onAction( context: Context, glanceId: GlanceId, - parameters: ActionParameters + parameters: ActionParameters, ) { CalculatorWidget().update(context, glanceId) } @@ -99,38 +99,38 @@ internal fun updateInputAction( input: String, equalClicked: Boolean, precision: Int, - outputFormat: Int + outputFormat: Int, ): Action = actionRunCallback( actionParametersOf( CalculatorWidget.inputKey to input, CalculatorWidget.equalClickedKey to equalClicked, CalculatorWidget.precisionKey to precision, - CalculatorWidget.outputFormatKey to outputFormat - ) + CalculatorWidget.outputFormatKey to outputFormat, + ), ) internal fun copyAction( output: String, - fractional: String + fractional: String, ): Action = actionRunCallback( actionParametersOf( - CalculatorWidget.outputKey to output.replace(Token.Digit.dot, fractional) - ) + CalculatorWidget.outputKey to output.replace(Token.Digit.dot, fractional), + ), ) internal fun launchAction( - mContext: Context + mContext: Context, ): Action = actionStartActivity( ComponentName( mContext, - "com.sadellie.unitto.MainActivity" - ) + "app.myzel394.numberhub.MainActivity", + ), ) private fun calculate( input: String, precision: Int, - outputFormat: Int + outputFormat: Int, ): String { if (input.isEmpty()) throw Exception() if (!input.isExpression()) throw Exception() diff --git a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/WidgetTheme.kt b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/WidgetTheme.kt similarity index 86% rename from feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/WidgetTheme.kt rename to feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/WidgetTheme.kt index 16d900d6..24f8ec5e 100644 --- a/feature/glance/src/main/java/com/sadellie/unitto/feature/glance/glance/WidgetTheme.kt +++ b/feature/glance/src/main/java/app/myzel394/numberhub/feature/glance/glance/WidgetTheme.kt @@ -16,14 +16,14 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.glance.glance +package app.myzel394.numberhub.feature.glance.glance import android.os.Build import androidx.compose.runtime.Composable import androidx.glance.GlanceTheme import androidx.glance.material3.ColorProviders -import com.sadellie.unitto.core.ui.theme.DarkThemeColors -import com.sadellie.unitto.core.ui.theme.LightThemeColors +import app.myzel394.numberhub.core.ui.theme.DarkThemeColors +import app.myzel394.numberhub.core.ui.theme.LightThemeColors @Composable internal fun WidgetTheme(content: @Composable () -> Unit) = @@ -33,7 +33,7 @@ internal fun WidgetTheme(content: @Composable () -> Unit) = } } else { GlanceTheme( - colors = ColorProviders(light = LightThemeColors, dark = DarkThemeColors) + colors = ColorProviders(light = LightThemeColors, dark = DarkThemeColors), ) { content() } diff --git a/feature/settings/build.gradle.kts b/feature/settings/build.gradle.kts index 9a36944c..4abb0ffe 100644 --- a/feature/settings/build.gradle.kts +++ b/feature/settings/build.gradle.kts @@ -24,7 +24,7 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.settings" +android.namespace = "app.myzel394.numberhub.feature.settings" dependencies { implementation(libs.com.github.sadellie.themmo) @@ -37,5 +37,4 @@ dependencies { implementation(project(":data:model")) implementation(project(":data:licenses")) implementation(project(":data:userprefs")) - implementation(project(":feature:glance")) } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsScreen.kt similarity index 72% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsScreen.kt index af3f9665..81710470 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings +package app.myzel394.numberhub.feature.settings import android.content.ActivityNotFoundException import android.content.Context @@ -50,7 +50,9 @@ import androidx.compose.material.icons.filled.RateReview import androidx.compose.material.icons.filled.SwapHoriz import androidx.compose.material.icons.filled.Vibration import androidx.compose.material.icons.filled._123 +import androidx.compose.material.icons.outlined.CheckCircle import androidx.compose.material.icons.outlined.NewReleases +import androidx.compose.material3.AlertDialog import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem @@ -58,12 +60,14 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -73,22 +77,24 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.BuildConfig -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.Header -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.core.ui.showToast -import com.sadellie.unitto.feature.settings.components.AnnoyingBox -import com.sadellie.unitto.feature.settings.navigation.aboutRoute -import com.sadellie.unitto.feature.settings.navigation.calculatorSettingsRoute -import com.sadellie.unitto.feature.settings.navigation.converterSettingsRoute -import com.sadellie.unitto.feature.settings.navigation.displayRoute -import com.sadellie.unitto.feature.settings.navigation.formattingRoute -import com.sadellie.unitto.feature.settings.navigation.startingScreenRoute +import app.myzel394.numberhub.core.base.BuildConfig +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.LocalWindowSize +import app.myzel394.numberhub.core.ui.WindowWidthSizeClass +import app.myzel394.numberhub.core.ui.common.DrawerButton +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.Header +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.openLink +import app.myzel394.numberhub.core.ui.showToast +import app.myzel394.numberhub.feature.settings.components.AnnoyingBox +import app.myzel394.numberhub.feature.settings.navigation.ABOUT_ROUTE +import app.myzel394.numberhub.feature.settings.navigation.CALCULATOR_SETTINGS_ROUTE +import app.myzel394.numberhub.feature.settings.navigation.CONVERTER_SETTINGS_ROUTE +import app.myzel394.numberhub.feature.settings.navigation.DISPLAY_ROUTE +import app.myzel394.numberhub.feature.settings.navigation.FORMATTING_ROUTE +import app.myzel394.numberhub.feature.settings.navigation.STARTING_SCREEN_ROUTE import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.time.ZonedDateTime @@ -97,7 +103,7 @@ import java.time.format.DateTimeFormatter @Composable internal fun SettingsRoute( viewModel: SettingsViewModel = hiltViewModel(), - navigateUp: () -> Unit, + openDrawer: () -> Unit, navControllerAction: (String) -> Unit, ) { val mContext = LocalContext.current @@ -115,13 +121,14 @@ internal fun SettingsRoute( is SettingsUIState.Ready -> SettingsScreen( uiState = uiState, - navigateUp = navigateUp, + openDrawer = openDrawer, navControllerAction = navControllerAction, + onHasSeenNewAppAnnouncement = viewModel::updateHasSeenNewAppAnnouncement, updateLastReadChangelog = viewModel::updateLastReadChangelog, updateVibrations = viewModel::updateVibrations, clearCache = viewModel::clearCache, backup = viewModel::backup, - restore = viewModel::restore + restore = viewModel::restore, ) } } @@ -129,10 +136,11 @@ internal fun SettingsRoute( @Composable private fun SettingsScreen( uiState: SettingsUIState.Ready, - navigateUp: () -> Unit, + openDrawer: () -> Unit, navControllerAction: (String) -> Unit, updateLastReadChangelog: (String) -> Unit, updateVibrations: (Boolean) -> Unit, + onHasSeenNewAppAnnouncement: (Boolean) -> Unit, clearCache: () -> Unit, backup: (Context, Uri) -> Unit, restore: (Context, Uri) -> Unit, @@ -142,14 +150,14 @@ private fun SettingsScreen( // Pass picked file uri to BackupManager val restoreLauncher = rememberLauncherForActivityResult( - ActivityResultContracts.OpenDocument() + ActivityResultContracts.OpenDocument(), ) { pickedUri -> if (pickedUri != null) restore(mContext, pickedUri) } // Pass picked file uri to BackupManager val backupLauncher = rememberLauncherForActivityResult( - ActivityResultContracts.CreateDocument(backupMimeType) + ActivityResultContracts.CreateDocument(BACKUP_MIME_TYPE), ) { pickedUri -> if (pickedUri != null) backup(mContext, pickedUri) } @@ -158,39 +166,87 @@ private fun SettingsScreen( ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_title), - navigationIcon = { NavigateUpButton(navigateUp) }, + navigationIcon = { + if (LocalWindowSize.current.widthSizeClass != WindowWidthSizeClass.Expanded) { + DrawerButton(openDrawer) + } + }, actions = { IconButton( onClick = { showMenu = !showMenu }, - content = { Icon(Icons.Default.MoreVert, null) } + content = { Icon(Icons.Default.MoreVert, null) }, ) DropdownMenu( expanded = showMenu, - onDismissRequest = { showMenu = false } + onDismissRequest = { showMenu = false }, ) { DropdownMenuItem( onClick = { showMenu = false backupLauncher.launchSafely(backupFileName()) }, - text = { Text(stringResource(R.string.settings_back_up)) } + text = { Text(stringResource(R.string.settings_back_up)) }, ) DropdownMenuItem( onClick = { showMenu = false - restoreLauncher.launchSafely(arrayOf(backupMimeType)) + restoreLauncher.launchSafely(arrayOf(BACKUP_MIME_TYPE)) }, - text = { Text(stringResource(R.string.settings_restore)) } + text = { Text(stringResource(R.string.settings_restore)) }, ) } - } + }, ) { padding -> Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) - .padding(padding) + .padding(padding), ) { + var showNewAppInfo by rememberSaveable { + mutableStateOf(false) + } + + if (showNewAppInfo) { + AlertDialog( + icon = { + Icon(Icons.Outlined.CheckCircle, null) + }, + title = { + Text(stringResource(R.string.settings_numberhub_newApp)) + }, + text = { + Text(stringResource(R.string.settings_numberhub_newApp_announcement)) + }, + confirmButton = { + TextButton(onClick = { showNewAppInfo = false }) { + Text(stringResource(R.string.ok_label)) + } + }, + onDismissRequest = { showNewAppInfo = false }, + ) + } + + AnimatedVisibility( + visible = !uiState.hasSeenNewAppAnnouncement, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut(), + ) { + val title = stringResource(R.string.settings_numberhub_newApp) + AnnoyingBox( + modifier = Modifier + .padding(16.dp, 8.dp) + .fillMaxWidth(), + imageVector = Icons.Outlined.CheckCircle, + imageVectorContentDescription = title, + title = title, + support = stringResource(R.string.settings_numberhub_newApp_message), + ) { + showNewAppInfo = true + //onHasSeenNewAppAnnouncement(true) + } + } + AnimatedVisibility( visible = uiState.showUpdateChangelog, enter = expandVertically() + fadeIn(), @@ -215,35 +271,35 @@ private fun SettingsScreen( icon = Icons.Default.Palette, headlineText = stringResource(R.string.settings_display), supportingText = stringResource(R.string.settings_display_support), - modifier = Modifier.clickable { navControllerAction(displayRoute) } + modifier = Modifier.clickable { navControllerAction(DISPLAY_ROUTE) }, ) ListItem( icon = Icons.Default.Home, headlineText = stringResource(R.string.settings_starting_screen), supportingText = stringResource(R.string.settings_starting_screen_support), - modifier = Modifier.clickable { navControllerAction(startingScreenRoute) } + modifier = Modifier.clickable { navControllerAction(STARTING_SCREEN_ROUTE) }, ) ListItem( icon = Icons.Default._123, headlineText = stringResource(R.string.settings_formatting), supportingText = stringResource(R.string.settings_formatting_support), - modifier = Modifier.clickable { navControllerAction(formattingRoute) } + modifier = Modifier.clickable { navControllerAction(FORMATTING_ROUTE) }, ) ListItem( icon = Icons.Default.Calculate, headlineText = stringResource(R.string.calculator_title), supportingText = stringResource(R.string.settings_calculator_support), - modifier = Modifier.clickable { navControllerAction(calculatorSettingsRoute) } + modifier = Modifier.clickable { navControllerAction(CALCULATOR_SETTINGS_ROUTE) }, ) ListItem( icon = Icons.Default.SwapHoriz, headlineText = stringResource(R.string.unit_converter_title), supportingText = stringResource(R.string.settings_converter_support), - modifier = Modifier.clickable { navControllerAction(converterSettingsRoute) } + modifier = Modifier.clickable { navControllerAction(CONVERTER_SETTINGS_ROUTE) }, ) Header(stringResource(R.string.settings_additional)) @@ -252,9 +308,9 @@ private fun SettingsScreen( icon = Icons.Default.Vibration, headlineText = stringResource(R.string.settings_vibrations), supportingText = stringResource(R.string.settings_vibrations_support), - modifier = Modifier.clickable { navControllerAction(converterSettingsRoute) }, + modifier = Modifier.clickable { navControllerAction(CONVERTER_SETTINGS_ROUTE) }, switchState = uiState.enableVibrations, - onSwitchChange = updateVibrations + onSwitchChange = updateVibrations, ) AnimatedVisibility( @@ -265,7 +321,10 @@ private fun SettingsScreen( ListItem( headlineText = stringResource(R.string.settings_clear_cache), icon = Icons.Default.Cached, - modifier = Modifier.clickable { clearCache(); showToast(mContext, "👌") }, + modifier = Modifier.clickable { + clearCache() + showToast(mContext, "👌") + }, ) } @@ -273,7 +332,7 @@ private fun SettingsScreen( ListItem( icon = Icons.Default.RateReview, headlineText = stringResource(R.string.settings_rate_this_app), - modifier = Modifier.clickable { openLink(mContext, BuildConfig.STORE_LINK) } + modifier = Modifier.clickable { openLink(mContext, BuildConfig.STORE_LINK) }, ) } @@ -281,7 +340,7 @@ private fun SettingsScreen( icon = Icons.Default.Info, headlineText = stringResource(R.string.settings_about_unitto), supportingText = stringResource(R.string.settings_about_unitto_support), - modifier = Modifier.clickable { navControllerAction(aboutRoute) } + modifier = Modifier.clickable { navControllerAction(ABOUT_ROUTE) }, ) } } @@ -289,7 +348,7 @@ private fun SettingsScreen( AnimatedVisibility( visible = uiState.backupInProgress, enter = fadeIn(), - exit = fadeOut() + exit = fadeOut(), ) { Scaffold { padding -> Box( @@ -317,7 +376,7 @@ private fun backupFileName(): String { return "${ZonedDateTime.now().format(formatter)}.unitto" } -private const val backupMimeType = "application/octet-stream" +private const val BACKUP_MIME_TYPE = "application/octet-stream" @Preview @Composable @@ -329,15 +388,19 @@ private fun PreviewSettingsScreen() { enableVibrations = false, cacheSize = 2, backupInProgress = false, - showUpdateChangelog = true - ) + showUpdateChangelog = true, + hasSeenNewAppAnnouncement = false, + ), ) } SettingsScreen( uiState = uiState, - navigateUp = {}, + openDrawer = {}, navControllerAction = {}, + onHasSeenNewAppAnnouncement = { + uiState = uiState.copy(hasSeenNewAppAnnouncement = true) + }, updateLastReadChangelog = { uiState = uiState.copy(showUpdateChangelog = false) }, @@ -358,6 +421,6 @@ private fun PreviewSettingsScreen() { delay(2000) uiState = uiState.copy(backupInProgress = false) } - } + }, ) } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsUIState.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsUIState.kt similarity index 91% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsUIState.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsUIState.kt index 82d3a861..1c0b2ccf 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsUIState.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsUIState.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings +package app.myzel394.numberhub.feature.settings internal sealed class SettingsUIState { data object Loading : SettingsUIState() @@ -26,5 +26,6 @@ internal sealed class SettingsUIState { val cacheSize: Int, val backupInProgress: Boolean, val showUpdateChangelog: Boolean, + val hasSeenNewAppAnnouncement: Boolean, ) : SettingsUIState() } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsViewModel.kt similarity index 77% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsViewModel.kt index 500c71f3..3a30540a 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/SettingsViewModel.kt @@ -16,19 +16,19 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings +package app.myzel394.numberhub.feature.settings import android.content.Context import android.net.Uri import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.base.BuildConfig -import com.sadellie.unitto.data.backup.BackupManager -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.database.CurrencyRatesDao -import com.sadellie.unitto.data.database.UnittoDatabase -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.core.base.BuildConfig +import app.myzel394.numberhub.data.backup.BackupManager +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.database.CurrencyRatesDao +import app.myzel394.numberhub.data.database.UnittoDatabase +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -44,24 +44,25 @@ import javax.inject.Inject internal class SettingsViewModel @Inject constructor( private val userPrefsRepository: UserPreferencesRepository, private val currencyRatesDao: CurrencyRatesDao, - private val database: UnittoDatabase + private val database: UnittoDatabase, ) : ViewModel() { private val _showErrorToast = MutableSharedFlow() val showErrorToast = _showErrorToast.asSharedFlow() - private val _backupInProgress = MutableStateFlow(false) + private val backupInProgress = MutableStateFlow(false) private var backupJob: Job? = null val uiState = combine( userPrefsRepository.generalPrefs, currencyRatesDao.size(), - _backupInProgress, + backupInProgress, ) { prefs, cacheSize, backupInProgress -> SettingsUIState.Ready( enableVibrations = prefs.enableVibrations, cacheSize = cacheSize, backupInProgress = backupInProgress, - showUpdateChangelog = prefs.lastReadChangelog != BuildConfig.VERSION_CODE + showUpdateChangelog = prefs.lastReadChangelog != BuildConfig.VERSION_CODE, + hasSeenNewAppAnnouncement = prefs.hasSeenNewAppAnnouncement, ) } .stateIn(viewModelScope, SettingsUIState.Loading) @@ -72,14 +73,14 @@ internal class SettingsViewModel @Inject constructor( ) { backupJob?.cancel() backupJob = viewModelScope.launch(Dispatchers.IO) { - _backupInProgress.update { true } + backupInProgress.update { true } try { BackupManager().backup(context, uri, database) } catch (e: Exception) { _showErrorToast.emit(true) Log.e(TAG, "$e") } - _backupInProgress.update { false } + backupInProgress.update { false } } } @@ -89,17 +90,21 @@ internal class SettingsViewModel @Inject constructor( ) { backupJob?.cancel() backupJob = viewModelScope.launch(Dispatchers.IO) { - _backupInProgress.update { true } + backupInProgress.update { true } try { BackupManager().restore(context, uri, database) } catch (e: Exception) { _showErrorToast.emit(true) Log.e(TAG, "$e") } - _backupInProgress.update { false } + backupInProgress.update { false } } } + fun updateHasSeenNewAppAnnouncement(value: Boolean) = viewModelScope.launch { + userPrefsRepository.updateHasSeenNewAppAnnouncement(value) + } + /** * @see UserPreferencesRepository.updateLastReadChangelog */ @@ -119,4 +124,4 @@ internal class SettingsViewModel @Inject constructor( } } -private const val TAG = "SettingsViewModel" \ No newline at end of file +private const val TAG = "SettingsViewModel" diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/about/AboutScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/about/AboutScreen.kt similarity index 72% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/about/AboutScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/about/AboutScreen.kt index 0b979aed..a8109481 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/about/AboutScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/about/AboutScreen.kt @@ -16,9 +16,8 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.about +package app.myzel394.numberhub.feature.settings.about -import android.widget.Toast import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.lazy.LazyColumn @@ -42,44 +41,31 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.BuildConfig -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.core.ui.showToast -import com.sadellie.unitto.data.model.userprefs.AboutPreferences -import com.sadellie.unitto.data.userprefs.AboutPreferencesImpl +import app.myzel394.numberhub.core.base.BuildConfig +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.openLink @Composable internal fun AboutRoute( - viewModel: AboutViewModel = hiltViewModel(), navigateUpAction: () -> Unit, navigateToThirdParty: () -> Unit, + navigateToEasterEgg: () -> Unit, ) { - when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) { - null -> EmptyScreen() - else -> { - AboutScreen( - prefs = prefs, - navigateUpAction = navigateUpAction, - navigateToThirdParty = navigateToThirdParty, - enableToolsExperiment = viewModel::enableToolsExperiment - ) - } - } + AboutScreen( + navigateUpAction = navigateUpAction, + navigateToThirdParty = navigateToThirdParty, + navigateToEasterEgg = navigateToEasterEgg, + ) } @Composable private fun AboutScreen( - prefs: AboutPreferences, navigateUpAction: () -> Unit, navigateToThirdParty: () -> Unit, - enableToolsExperiment: () -> Unit, + navigateToEasterEgg: () -> Unit, ) { val mContext = LocalContext.current var aboutItemClick: Int by rememberSaveable { mutableIntStateOf(0) } @@ -87,7 +73,7 @@ private fun AboutScreen( ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_about_unitto), - navigationIcon = { NavigateUpButton(navigateUpAction) } + navigationIcon = { NavigateUpButton(navigateUpAction) }, ) { padding -> LazyColumn(contentPadding = padding) { // CURRENCY RATE NOTE @@ -95,7 +81,7 @@ private fun AboutScreen( ListItem( icon = Icons.AutoMirrored.Filled.Help, headlineText = stringResource(R.string.settings_currency_rates_note_title), - modifier = Modifier.clickable { showDialog = true } + modifier = Modifier.clickable { showDialog = true }, ) } @@ -107,9 +93,9 @@ private fun AboutScreen( modifier = Modifier.clickable { openLink( mContext, - "https://sadellie.github.io/unitto/terms" + "https://sadellie.github.io/unitto/terms", ) - } + }, ) } @@ -121,9 +107,9 @@ private fun AboutScreen( modifier = Modifier.clickable { openLink( mContext, - "https://sadellie.github.io/unitto/privacy" + "https://sadellie.github.io/unitto/privacy", ) - } + }, ) } @@ -135,9 +121,9 @@ private fun AboutScreen( modifier = Modifier.clickable { openLink( mContext, - "https://github.com/sadellie/unitto" + "https://github.com/sadellie/unitto", ) - } + }, ) } @@ -146,7 +132,7 @@ private fun AboutScreen( ListItem( icon = Icons.Default.Copyright, headlineText = stringResource(R.string.settings_third_party_licenses), - modifier = Modifier.clickable { navigateToThirdParty() } + modifier = Modifier.clickable { navigateToThirdParty() }, ) } @@ -157,17 +143,12 @@ private fun AboutScreen( headlineText = stringResource(R.string.settings_version_name), supportingText = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})", modifier = Modifier.combinedClickable { - if (prefs.enableToolsExperiment) { - showToast(mContext, "Experiments features are already enabled!", Toast.LENGTH_LONG) - return@combinedClickable - } - aboutItemClick++ - if (aboutItemClick < 7) return@combinedClickable - - enableToolsExperiment() - showToast(mContext, "Experimental features enabled!", Toast.LENGTH_LONG) - } + if (aboutItemClick > 5) { + aboutItemClick = 0 + navigateToEasterEgg() + } + }, ) } } @@ -186,7 +167,7 @@ private fun AboutScreen( Text(stringResource(R.string.ok_label)) } }, - onDismissRequest = { showDialog = false } + onDismissRequest = { showDialog = false }, ) } } @@ -195,11 +176,8 @@ private fun AboutScreen( @Composable fun PreviewAboutScreen() { AboutScreen( - prefs = AboutPreferencesImpl( - enableToolsExperiment = false - ), navigateUpAction = {}, navigateToThirdParty = {}, - enableToolsExperiment = {} + navigateToEasterEgg = {}, ) } diff --git a/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/bouncingemoji/BouncingEmoji.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/bouncingemoji/BouncingEmoji.kt new file mode 100644 index 00000000..e4f114d6 --- /dev/null +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/bouncingemoji/BouncingEmoji.kt @@ -0,0 +1,244 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.settings.bouncingemoji + +import androidx.annotation.FloatRange +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.animation.togetherWith +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithTopBar +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlin.math.absoluteValue +import kotlin.math.roundToInt +import kotlin.random.Random + +@Composable +internal fun BouncingEmojiRoute( + navigateUpAction: () -> Unit, +) { + ScaffoldWithTopBar( + title = { AnimatedText("Bouncy boy") }, + navigationIcon = { NavigateUpButton(navigateUpAction) }, + ) { paddingValues -> + BouncingEmojiScreen( + modifier = Modifier + .padding(paddingValues) + .fillMaxSize(), + ) + } +} + +/** + * @param modifier [Modifier] that will be applied to the surrounding [BoxWithConstraints]. + * @param initialX Initial horizontal position. 0 means left, 1 means right. + * @param initialY Initial vertical position. 0 means top, 1 means bottom. + */ +@Composable +private fun BouncingEmojiScreen( + modifier: Modifier, + @FloatRange(0.0, 1.0) initialX: Float = Random.nextFloat(), + @FloatRange(0.0, 1.0) initialY: Float = Random.nextFloat(), +) { + val density = LocalDensity.current + var speed by remember { mutableFloatStateOf(1f) } + + CompositionLocalProvider( + value = LocalDensity provides Density(density.density, fontScale = 1f), + ) { + BoxWithConstraints( + modifier = modifier.clickable { + speed = Random.nextFloat() + }, + ) { + val width = constraints.maxWidth + val height = constraints.maxHeight + val ballSize = 96.dp + val ballSizePx = with(LocalDensity.current) { ballSize.toPx().roundToInt() } + + var x by rememberSaveable { mutableFloatStateOf((width - ballSizePx) * initialX) } + var y by rememberSaveable { mutableFloatStateOf((height - ballSizePx) * initialY) } + + val animatedX = animateFloatAsState(x, label = "X position") + val animatedY = animateFloatAsState(y, label = "Y position") + + var xSpeed by rememberSaveable { mutableFloatStateOf(10f) } + var ySpeed by rememberSaveable { mutableFloatStateOf(10f) } + + var bounces by remember { mutableFloatStateOf(0f) } + var edgeHits by rememberSaveable { mutableFloatStateOf(0f) } + var emoji by remember { mutableStateOf("❤") } + var mood by remember { mutableStateOf("prepare for impact") } + + Column( + modifier = Modifier.offset { + IntOffset( + animatedX.value.roundToInt(), + animatedY.value.roundToInt(), + ) + }, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Box( + modifier = Modifier + .background(MaterialTheme.colorScheme.primaryContainer, CircleShape) + .size(ballSize), + contentAlignment = Alignment.Center, + ) { + AnimatedText(emoji, MaterialTheme.typography.displayMedium) + } + AnimatedText(mood) + } + + Column { + AnimatedText("Speed: ${xSpeed.absoluteValue * speed}") + AnimatedText("Bounces: $bounces") + AnimatedText("Edge hits: $edgeHits") + AnimatedText("Luck: ${edgeHits / bounces}") + } + + LaunchedEffect( + key1 = Unit, + key2 = speed, + ) { + while (isActive) { + x += xSpeed * speed + y += ySpeed * speed + + val rightBounce = x > width - ballSizePx + val leftBounce = x < 0 + val bottomBounce = y > height - ballSizePx + val topBounce = y < 0 + var bouncedEdges = 0 + + if (rightBounce || leftBounce) { + xSpeed = -xSpeed + bouncedEdges++ + } + + if (topBounce || bottomBounce) { + ySpeed = -ySpeed + bouncedEdges++ + } + + // Count edge hit as 1 bounce + when (bouncedEdges) { + 2 -> { + edgeHits++ + bounces++ + mood = winnerMood.random() + emoji = winnerEmoji.random() + } + 1 -> { + bounces++ + mood = looserMood.random() + emoji = looserEmoji.random() + } + } + + delay(1) + } + } + } + } +} + +@Composable +private fun AnimatedText( + text: String, + style: TextStyle = LocalTextStyle.current, +) { + AnimatedContent( + targetState = text, + transitionSpec = { + slideInVertically { height -> height } + fadeIn() togetherWith + slideOutVertically { height -> -height } + fadeOut() + }, + label = "Text animation", + ) { + Text( + text = it, + style = style, + color = MaterialTheme.colorScheme.onBackground, + ) + } +} + +private val looserEmoji by lazy { + listOf("🤡", "😭", "👿", "💀", "💩") +} + +private val winnerEmoji by lazy { + listOf("🤠", "🤑", "😎", "🥇") +} + +private val looserMood by lazy { + listOf("sus", "bruh", "no cap", "fr fr", "vibing", "oof", "F", "mood", "L+ratio", "yeet") +} + +private val winnerMood by lazy { + listOf("ayoo", "W", "skill", "sheeesh", "bro is cheating") +} + +@Preview +@Composable +private fun PreviewBouncingEmojiScreen() { + BouncingEmojiScreen( + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + .size(400.dp, 550.dp), + initialX = 0.5f, + initialY = 0.5f, + ) +} diff --git a/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/calculator/CalculatorSettingsScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/calculator/CalculatorSettingsScreen.kt new file mode 100644 index 00000000..9f0a5661 --- /dev/null +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/calculator/CalculatorSettingsScreen.kt @@ -0,0 +1,99 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.settings.calculator + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Timer +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.data.model.userprefs.CalculatorPreferences +import app.myzel394.numberhub.data.userprefs.CalculatorPreferencesImpl + +@Composable +internal fun CalculatorSettingsRoute( + viewModel: CalculatorSettingsViewModel = hiltViewModel(), + navigateUpAction: () -> Unit, +) { + when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) { + null -> EmptyScreen() + else -> { + CalculatorSettingsScreen( + prefs = prefs, + navigateUpAction = navigateUpAction, + updatePartialHistoryView = viewModel::updatePartialHistoryView, + ) + } + } +} + +@Composable +private fun CalculatorSettingsScreen( + prefs: CalculatorPreferences, + navigateUpAction: () -> Unit, + updatePartialHistoryView: (Boolean) -> Unit, +) { + ScaffoldWithLargeTopBar( + title = stringResource(R.string.calculator_title), + navigationIcon = { NavigateUpButton(navigateUpAction) }, + ) { padding -> + Column(Modifier.padding(padding)) { + ListItem( + headlineText = stringResource(R.string.settings_partial_history_view), + icon = Icons.Default.Timer, + supportingText = stringResource(R.string.settings_partial_history_view_support), + switchState = prefs.partialHistoryView, + onSwitchChange = updatePartialHistoryView, + ) + } + } +} + +@Preview +@Composable +private fun PreviewCalculatorSettingsScreenStandard() { + CalculatorSettingsScreen( + prefs = CalculatorPreferencesImpl( + radianMode = true, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), + middleZero = false, + acButton = false, + additionalButtons = false, + inverseMode = false, + partialHistoryView = false, + precision = 3, + outputFormat = OutputFormat.PLAIN, + ), + navigateUpAction = {}, + updatePartialHistoryView = {}, + ) +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/about/AboutViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/calculator/CalculatorSettingsViewModel.kt similarity index 70% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/about/AboutViewModel.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/calculator/CalculatorSettingsViewModel.kt index bf6c145b..64ee1140 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/about/AboutViewModel.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/calculator/CalculatorSettingsViewModel.kt @@ -16,24 +16,24 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.about +package app.myzel394.numberhub.feature.settings.calculator import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -internal class AboutViewModel @Inject constructor( +internal class CalculatorSettingsViewModel @Inject constructor( private val userPrefsRepository: UserPreferencesRepository, ) : ViewModel() { - val prefs = userPrefsRepository.aboutPrefs + val prefs = userPrefsRepository.calculatorPrefs .stateIn(viewModelScope, null) - fun enableToolsExperiment() = viewModelScope.launch { - userPrefsRepository.updateToolsExperiment(true) + fun updatePartialHistoryView(enabled: Boolean) = viewModelScope.launch { + userPrefsRepository.updatePartialHistoryView(enabled) } } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/AlertDialogWithList.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/AlertDialogWithList.kt similarity index 93% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/AlertDialogWithList.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/AlertDialogWithList.kt index 332e0224..2024ef76 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/AlertDialogWithList.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/AlertDialogWithList.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.components +package app.myzel394.numberhub.feature.settings.components import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -38,7 +38,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R /** * Alert dialog that has a list of options in it @@ -58,7 +58,7 @@ internal fun AlertDialogWithList( selectAction: (T) -> Unit, dismissAction: () -> Unit, supportText: String? = null, - dismissButtonLabel: String = stringResource(R.string.cancel_label) + dismissButtonLabel: String = stringResource(R.string.cancel_label), ) { AlertDialog( onDismissRequest = dismissAction, @@ -78,7 +78,7 @@ internal fun AlertDialogWithList( onClick = { selectAction(option) dismissAction() - } + }, ) } } @@ -88,7 +88,7 @@ internal fun AlertDialogWithList( TextButton(onClick = dismissAction) { Text(text = dismissButtonLabel, color = MaterialTheme.colorScheme.primary) } - } + }, ) } @@ -103,7 +103,7 @@ internal fun AlertDialogWithList( private fun CustomDialogContentListItem( label: String, selected: Boolean = false, - onClick: () -> Unit + onClick: () -> Unit, ) { Row( modifier = Modifier @@ -111,9 +111,9 @@ private fun CustomDialogContentListItem( .clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(), - onClick = onClick + onClick = onClick, ), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { RadioButton(selected, onClick) Text(label) diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/AnnoyingBox.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/AnnoyingBox.kt similarity index 89% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/AnnoyingBox.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/AnnoyingBox.kt index 7c2f9204..136531e9 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/AnnoyingBox.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/AnnoyingBox.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.components +package app.myzel394.numberhub.feature.settings.components import androidx.compose.foundation.background import androidx.compose.foundation.interaction.MutableInteractionSource @@ -38,7 +38,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.ui.common.squashable +import app.myzel394.numberhub.core.ui.common.squashable @Composable internal fun AnnoyingBox( @@ -54,23 +54,23 @@ internal fun AnnoyingBox( .squashable( onClick = onClick, interactionSource = remember { MutableInteractionSource() }, - cornerRadiusRange = 15..25 + cornerRadiusRange = 15..25, ) .background(MaterialTheme.colorScheme.secondaryContainer) .padding(16.dp, 8.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Icon( modifier = Modifier.size(24.dp), imageVector = imageVector, contentDescription = imageVectorContentDescription, - tint = MaterialTheme.colorScheme.onSurfaceVariant + tint = MaterialTheme.colorScheme.onSurfaceVariant, ) Column( modifier = Modifier .weight(1f) - .padding(vertical = 8.dp) + .padding(vertical = 8.dp), ) { Text( text = title, @@ -94,6 +94,6 @@ fun PreviewAnnoyingBox() { imageVector = Icons.Default.Accessibility, imageVectorContentDescription = "", title = "Title text", - support = "Lorem ipsum or something" + support = "Lorem ipsum or something", ) {} } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorSelector.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/ColorSelector.kt similarity index 92% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorSelector.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/ColorSelector.kt index 76b04c07..c0f1932a 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/ColorSelector.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/ColorSelector.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.components +package app.myzel394.numberhub.feature.settings.components import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween @@ -51,7 +51,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R @Composable internal fun ColorSelector( @@ -71,14 +71,14 @@ internal fun ColorSelector( LazyRow( modifier = modifier, state = listState, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { // Default, Unitto colors item(defaultColor.value.toLong()) { ColorCheckbox( color = defaultColor, selected = Color.Unspecified == selected, - onClick = { onItemClick(Color.Unspecified) } + onClick = { onItemClick(Color.Unspecified) }, ) } @@ -87,7 +87,7 @@ internal fun ColorSelector( ColorCheckbox( color = it, selected = it == selected, - onClick = { onItemClick(it) } + onClick = { onItemClick(it) }, ) } } @@ -98,7 +98,7 @@ internal fun ColorSelector( private fun ColorCheckbox( color: Color, selected: Boolean, - onClick: () -> Unit + onClick: () -> Unit, ) { Box( modifier = Modifier @@ -106,7 +106,7 @@ private fun ColorCheckbox( .clip(RoundedCornerShape(25)) .clickable(onClick = onClick) .background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp)), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { Box( modifier = Modifier diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/MonetModeSelector.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/MonetModeSelector.kt similarity index 85% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/MonetModeSelector.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/MonetModeSelector.kt index cb80296e..68e780ea 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/components/MonetModeSelector.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/components/MonetModeSelector.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.components +package app.myzel394.numberhub.feature.settings.components import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween @@ -56,7 +56,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R import io.github.sadellie.themmo.Themmo import io.github.sadellie.themmo.ThemmoController import io.github.sadellie.themmo.core.MonetMode @@ -81,7 +81,7 @@ internal fun MonetModeSelector( LazyRow( modifier = modifier, state = listState, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { items(monetModes) { monetMode -> Themmo( @@ -93,13 +93,13 @@ internal fun MonetModeSelector( dynamicThemeEnabled = false, amoledThemeEnabled = false, customColor = customColor, - monetMode = monetMode + monetMode = monetMode, ) - } + }, ) { MonetModeCheckbox( selected = monetMode == selected, - onClick = { onItemClick(monetMode) } + onClick = { onItemClick(monetMode) }, ) } } @@ -109,7 +109,7 @@ internal fun MonetModeSelector( @Composable private fun MonetModeCheckbox( selected: Boolean, - onClick: () -> Unit + onClick: () -> Unit, ) { Box( modifier = Modifier @@ -117,7 +117,7 @@ private fun MonetModeCheckbox( .clip(RoundedCornerShape(25)) .clickable(onClick = onClick) .background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp)), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { Box( modifier = Modifier @@ -127,17 +127,21 @@ private fun MonetModeCheckbox( .clip(CircleShape) .background(MaterialTheme.colorScheme.secondary) .border(1.dp, MaterialTheme.colorScheme.outline, CircleShape), - contentAlignment = Alignment.BottomStart + contentAlignment = Alignment.BottomStart, ) { // Is this bad? Yes. Does it work? Also yes. - Box(modifier = Modifier - .fillMaxHeight(0.5f) - .fillMaxWidth() - .background(MaterialTheme.colorScheme.primary)) - Box(modifier = Modifier - .fillMaxHeight(0.5f) - .fillMaxWidth(0.5f) - .background(MaterialTheme.colorScheme.secondaryContainer)) + Box( + modifier = Modifier + .fillMaxHeight(0.5f) + .fillMaxWidth() + .background(MaterialTheme.colorScheme.primary), + ) + Box( + modifier = Modifier + .fillMaxHeight(0.5f) + .fillMaxWidth(0.5f) + .background(MaterialTheme.colorScheme.secondaryContainer), + ) } AnimatedVisibility( visible = selected, @@ -150,7 +154,7 @@ private fun MonetModeCheckbox( tint = MaterialTheme.colorScheme.inverseOnSurface, modifier = Modifier .background(MaterialTheme.colorScheme.inverseSurface, CircleShape) - .padding(4.dp) + .padding(4.dp), ) } } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/converter/ConverterSettingsScreen.kt similarity index 81% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/converter/ConverterSettingsScreen.kt index ffd84316..2b82e9d6 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/converter/ConverterSettingsScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.converter +package app.myzel394.numberhub.feature.settings.converter import androidx.compose.foundation.clickable import androidx.compose.foundation.lazy.LazyColumn @@ -34,18 +34,19 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.Separator -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.userprefs.ConverterPreferences -import com.sadellie.unitto.data.userprefs.ConverterPreferencesImpl -import com.sadellie.unitto.feature.settings.components.AlertDialogWithList +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.userprefs.ConverterPreferences +import app.myzel394.numberhub.data.userprefs.ConverterPreferencesImpl +import app.myzel394.numberhub.feature.settings.components.AlertDialogWithList @Composable internal fun ConverterSettingsRoute( @@ -61,7 +62,7 @@ internal fun ConverterSettingsRoute( navigateUpAction = navigateUpAction, navigateToUnitsGroup = navigateToUnitsGroup, updateUnitConverterFormatTime = viewModel::updateUnitConverterFormatTime, - updateUnitConverterSorting = viewModel::updateUnitConverterSorting + updateUnitConverterSorting = viewModel::updateUnitConverterSorting, ) } } @@ -79,7 +80,7 @@ private fun ConverterSettingsScreen( ScaffoldWithLargeTopBar( title = stringResource(R.string.unit_converter_title), - navigationIcon = { NavigateUpButton(navigateUpAction) } + navigationIcon = { NavigateUpButton(navigateUpAction) }, ) { padding -> LazyColumn(contentPadding = padding) { item("unit group") { @@ -87,7 +88,7 @@ private fun ConverterSettingsScreen( icon = Icons.AutoMirrored.Filled.Rule, headlineText = stringResource(R.string.settings_unit_groups_title), supportingText = stringResource(R.string.settings_unit_groups_support), - modifier = Modifier.clickable { navigateToUnitsGroup() } + modifier = Modifier.clickable { navigateToUnitsGroup() }, ) } @@ -96,7 +97,7 @@ private fun ConverterSettingsScreen( icon = Icons.AutoMirrored.Filled.Sort, headlineText = stringResource(R.string.settings_units_sorting), supportingText = stringResource(R.string.settings_units_sorting_support), - modifier = Modifier.clickable { showDialog = true } + modifier = Modifier.clickable { showDialog = true }, ) } @@ -106,7 +107,7 @@ private fun ConverterSettingsScreen( headlineText = stringResource(R.string.settings_format_time), supportingText = stringResource(R.string.settings_format_time_support), switchState = prefs.unitConverterFormatTime, - onSwitchChange = updateUnitConverterFormatTime + onSwitchChange = updateUnitConverterFormatTime, ) } } @@ -123,7 +124,7 @@ private fun ConverterSettingsScreen( ), selectedItemIndex = prefs.unitConverterSorting, selectAction = updateUnitConverterSorting, - dismissAction = { showDialog = false } + dismissAction = { showDialog = false }, ) } } @@ -133,13 +134,13 @@ private fun ConverterSettingsScreen( private fun PreviewConverterSettingsScreen() { ConverterSettingsScreen( prefs = ConverterPreferencesImpl( - separator = Separator.SPACE, + formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD), middleZero = false, precision = 3, outputFormat = OutputFormat.PLAIN, unitConverterFormatTime = false, unitConverterSorting = UnitsListSorting.USAGE, - shownUnitGroups = ALL_UNIT_GROUPS, + shownUnitGroups = UnitGroup.entries, unitConverterFavoritesOnly = false, enableToolsExperiment = false, latestLeftSideUnit = "kilometer", @@ -149,6 +150,6 @@ private fun PreviewConverterSettingsScreen() { navigateUpAction = {}, navigateToUnitsGroup = {}, updateUnitConverterFormatTime = {}, - updateUnitConverterSorting = {} + updateUnitConverterSorting = {}, ) } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/converter/ConverterSettingsViewModel.kt similarity index 85% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/converter/ConverterSettingsViewModel.kt index f6c2bf36..00f4fe6a 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/converter/ConverterSettingsViewModel.kt @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.converter +package app.myzel394.numberhub.feature.settings.converter import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.converter.UnitsListSorting +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/Color.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/Color.kt similarity index 98% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/Color.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/Color.kt index 8b170c94..318ae215 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/Color.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/Color.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.display +package app.myzel394.numberhub.feature.settings.display import androidx.compose.ui.graphics.Color diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/DisplayScreen.kt similarity index 89% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/DisplayScreen.kt index 56407e45..05df4994 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/DisplayScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.display +package app.myzel394.numberhub.feature.settings.display import android.os.Build import androidx.annotation.RequiresApi @@ -55,18 +55,18 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.Header -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.SegmentedButton -import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.common.icons.IconPack -import com.sadellie.unitto.core.ui.common.icons.iconpack.Clear -import com.sadellie.unitto.feature.settings.components.ColorSelector -import com.sadellie.unitto.feature.settings.components.MonetModeSelector +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.Header +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.common.SegmentedButton +import app.myzel394.numberhub.core.ui.common.SegmentedButtonsRow +import app.myzel394.numberhub.core.ui.common.icons.IconPack +import app.myzel394.numberhub.core.ui.common.icons.iconpack.Clear +import app.myzel394.numberhub.feature.settings.components.ColorSelector +import app.myzel394.numberhub.feature.settings.components.MonetModeSelector import io.github.sadellie.themmo.Themmo import io.github.sadellie.themmo.ThemmoController import io.github.sadellie.themmo.core.MonetMode @@ -122,7 +122,7 @@ internal fun DisplayRoute( updateAcButton = viewModel::updateAcButton, middleZero = prefs.middleZero, updateMiddleZero = viewModel::updateMiddleZero, - navigateToLanguages = navigateToLanguages + navigateToLanguages = navigateToLanguages, ) } } @@ -151,13 +151,13 @@ private fun DisplayScreen( ) { ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_display), - navigationIcon = { NavigateUpButton(navigateUp) } + navigationIcon = { NavigateUpButton(navigateUp) }, ) { paddingValues -> Column( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) - .padding(paddingValues) + .padding(paddingValues), ) { ListItem( leadingContent = { @@ -173,26 +173,26 @@ private fun DisplayScreen( Row( Modifier .horizontalScroll(rememberScrollState()) - .wrapContentWidth() + .wrapContentWidth(), ) { SegmentedButtonsRow(modifier = Modifier.padding(56.dp, 8.dp, 24.dp, 2.dp)) { SegmentedButton( label = stringResource(R.string.settings_auto), onClick = { onThemeChange(ThemingMode.AUTO) }, selected = ThemingMode.AUTO == currentThemingMode, - icon = Icons.Outlined.HdrAuto + icon = Icons.Outlined.HdrAuto, ) SegmentedButton( label = stringResource(R.string.settings_light_mode), onClick = { onThemeChange(ThemingMode.FORCE_LIGHT) }, selected = ThemingMode.FORCE_LIGHT == currentThemingMode, - icon = Icons.Outlined.LightMode + icon = Icons.Outlined.LightMode, ) SegmentedButton( label = stringResource(R.string.settings_dark_mode), onClick = { onThemeChange(ThemingMode.FORCE_DARK) }, selected = ThemingMode.FORCE_DARK == currentThemingMode, - icon = Icons.Outlined.DarkMode + icon = Icons.Outlined.DarkMode, ) } } @@ -207,7 +207,7 @@ private fun DisplayScreen( headlineText = stringResource(R.string.settings_amoled_dark), supportingText = stringResource(R.string.settings_amoled_dark_support), switchState = isAmoledThemeEnabled, - onSwitchChange = onAmoledThemeChange + onSwitchChange = onAmoledThemeChange, ) } @@ -217,7 +217,7 @@ private fun DisplayScreen( headlineText = stringResource(R.string.settings_dynamic_colors), supportingText = stringResource(R.string.settings_dynamic_colors_support), switchState = isDynamicThemeEnabled, - onSwitchChange = onDynamicThemeChange + onSwitchChange = onDynamicThemeChange, ) AnimatedVisibility( @@ -233,7 +233,7 @@ private fun DisplayScreen( selected = selectedColor, onItemClick = onColorChange, colors = colorSchemes, - defaultColor = Color(0xFF186c31) + defaultColor = Color(0xFF186c31), ) }, modifier = Modifier.padding(start = 40.dp), @@ -257,7 +257,7 @@ private fun DisplayScreen( themingMode = currentThemingMode, ) }, - modifier = Modifier.padding(start = 40.dp) + modifier = Modifier.padding(start = 40.dp), ) } } @@ -269,7 +269,7 @@ private fun DisplayScreen( headlineText = stringResource(R.string.settings_system_font), supportingText = stringResource(R.string.settings_system_font_support), switchState = systemFont, - onSwitchChange = updateSystemFont + onSwitchChange = updateSystemFont, ) ListItem( @@ -277,7 +277,7 @@ private fun DisplayScreen( headlineText = stringResource(R.string.settings_ac_button), supportingText = stringResource(R.string.settings_ac_button_support), switchState = acButton, - onSwitchChange = updateAcButton + onSwitchChange = updateAcButton, ) ListItem( @@ -285,14 +285,14 @@ private fun DisplayScreen( headlineText = stringResource(R.string.settings_middle_zero), supportingText = stringResource(R.string.settings_middle_zero_support), switchState = middleZero, - onSwitchChange = updateMiddleZero + onSwitchChange = updateMiddleZero, ) ListItem( icon = Icons.Default.Language, headlineText = stringResource(R.string.settings_language), supportingText = stringResource(R.string.settings_language_support), - modifier = Modifier.clickable { navigateToLanguages() } + modifier = Modifier.clickable { navigateToLanguages() }, ) } } @@ -321,7 +321,7 @@ private fun Preview() { updateAcButton = {}, middleZero = false, updateMiddleZero = {}, - navigateToLanguages = {} + navigateToLanguages = {}, ) } } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/DisplayViewModel.kt similarity index 90% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/DisplayViewModel.kt index 102281db..61095019 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/display/DisplayViewModel.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/display/DisplayViewModel.kt @@ -16,13 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.display +package app.myzel394.numberhub.feature.settings.display import androidx.compose.ui.graphics.Color import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import io.github.sadellie.themmo.core.MonetMode import io.github.sadellie.themmo.core.ThemingMode @@ -31,7 +31,7 @@ import javax.inject.Inject @HiltViewModel class DisplayViewModel @Inject constructor( - private val userPrefsRepository: UserPreferencesRepository + private val userPrefsRepository: UserPreferencesRepository, ) : ViewModel() { val prefs = userPrefsRepository.displayPrefs diff --git a/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingScreen.kt new file mode 100644 index 00000000..27af094f --- /dev/null +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingScreen.kt @@ -0,0 +1,305 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.settings.formatting + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.rememberScrollState +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Architecture +import androidx.compose.material.icons.filled.EMobiledata +import androidx.compose.material.icons.filled._123 +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import app.myzel394.numberhub.core.base.FormatterSymbols +import app.myzel394.numberhub.core.base.MAX_PRECISION +import app.myzel394.numberhub.core.base.OutputFormat +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.base.Token +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.PagedIsland +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.common.SegmentedButton +import app.myzel394.numberhub.core.ui.common.SegmentedButtonsRow +import app.myzel394.numberhub.core.ui.common.Slider +import app.myzel394.numberhub.core.ui.common.textfield.formatExpression +import app.myzel394.numberhub.core.ui.theme.LocalNumberTypography +import app.myzel394.numberhub.data.common.format +import kotlin.math.ceil +import kotlin.math.roundToInt + +@Composable +fun FormattingRoute( + viewModel: FormattingViewModel = hiltViewModel(), + navigateUpAction: () -> Unit, +) { + when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { + null -> EmptyScreen() + else -> { + FormattingScreen( + navigateUpAction = navigateUpAction, + uiState = uiState, + onPrecisionChange = viewModel::updatePrecision, + updateFormatterSymbols = viewModel::updateFormatterSymbols, + onOutputFormatChange = viewModel::updateOutputFormat, + ) + } + } +} + +@Composable +fun FormattingScreen( + navigateUpAction: () -> Unit, + uiState: FormattingUIState, + onPrecisionChange: (Int) -> Unit, + updateFormatterSymbols: (grouping: String, fractional: String) -> Unit, + onOutputFormatChange: (Int) -> Unit, + // 16th is a MAX_PRECISION (1000) + precisions: ClosedFloatingPointRange = 0f..16f, +) { + val resources = LocalContext.current.resources + + val precisionText: String by remember(uiState.precision, uiState.formatterSymbols) { + derivedStateOf { + return@derivedStateOf if (uiState.precision >= precisions.endInclusive) { + resources.getString( + R.string.settings_precision_max, + MAX_PRECISION.toString().formatExpression(uiState.formatterSymbols), + ) + } else { + uiState.precision.toString() + } + } + } + + ScaffoldWithLargeTopBar( + title = stringResource(R.string.settings_formatting), + navigationIcon = { NavigateUpButton(navigateUpAction) }, + ) { paddingValues -> + Column( + modifier = Modifier + .padding(paddingValues), + ) { + PagedIsland( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + pageCount = 2, + ) { currentPage -> + val preview = when (currentPage) { + 0 -> "123456.${"789123456".repeat(ceil(uiState.precision.toDouble() / 9.0).toInt())}" + 1 -> "0.${"1".padStart(uiState.precision, '0')}" + else -> "" + } + .toBigDecimalOrNull() + ?.format(uiState.precision, uiState.outputFormat) + ?.formatExpression(uiState.formatterSymbols) + ?: "" + + Text( + text = preview, + style = LocalNumberTypography.current.displayMedium, + maxLines = 1, + modifier = Modifier + .fillMaxWidth() + .horizontalScroll(rememberScrollState()), + textAlign = TextAlign.End, + color = MaterialTheme.colorScheme.onSecondaryContainer, + ) + } + + ListItem( + leadingContent = { + Icon( + Icons.Default.Architecture, + stringResource(R.string.settings_precision), + ) + }, + headlineContent = { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Text(stringResource(R.string.settings_precision)) + Text(precisionText) + } + }, + supportingContent = { + Text(stringResource(R.string.settings_precision_support)) + }, + ) + + Slider( + modifier = Modifier.padding(start = 56.dp, end = 16.dp), + value = uiState.precision.toFloat(), + valueRange = precisions, + onValueChange = { onPrecisionChange(it.roundToInt()) }, + ) + + ListItem( + leadingContent = { + Icon(Icons.Default._123, stringResource(R.string.settings_thousands_separator)) + }, + headlineContent = { Text(stringResource(R.string.settings_thousands_separator)) }, + ) + + Row( + Modifier + .horizontalScroll(rememberScrollState()) + .wrapContentWidth() + .padding(start = 56.dp), + ) { + SegmentedButtonsRow { + SegmentedButton( + label = stringResource(R.string.settings_space), + onClick = { updateFormatterSymbols(Token.SPACE, uiState.formatterSymbols.fractional) }, + selected = uiState.formatterSymbols.grouping == Token.SPACE, + ) + SegmentedButton( + label = stringResource(R.string.settings_period), + onClick = { updateFormatterSymbols(Token.PERIOD, Token.COMMA) }, + selected = uiState.formatterSymbols.grouping == Token.PERIOD, + ) + SegmentedButton( + label = stringResource(R.string.comma), + onClick = { updateFormatterSymbols(Token.COMMA, Token.PERIOD) }, + selected = uiState.formatterSymbols.grouping == Token.COMMA, + ) + } + } + + AnimatedVisibility( + visible = uiState.formatterSymbols.grouping == Token.SPACE, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut(), + ) { + Column( + modifier = Modifier.padding(start = 40.dp), + ) { + ListItem( + modifier = Modifier, + headlineContent = { Text(stringResource(R.string.settings_decimal_separator)) }, + ) + Row( + Modifier + .horizontalScroll(rememberScrollState()) + .wrapContentWidth() + .padding(start = 16.dp), + ) { + SegmentedButtonsRow { + SegmentedButton( + label = stringResource(R.string.settings_period), + onClick = { updateFormatterSymbols(Token.SPACE, Token.PERIOD) }, + selected = uiState.formatterSymbols.fractional == Token.PERIOD, + ) + SegmentedButton( + label = stringResource(R.string.comma), + onClick = { updateFormatterSymbols(Token.SPACE, Token.COMMA) }, + selected = uiState.formatterSymbols.fractional == Token.COMMA, + ) + } + } + } + } + + ListItem( + leadingContent = { + Icon(Icons.Default.EMobiledata, stringResource(R.string.settings_precision)) + }, + headlineContent = { Text(stringResource(R.string.settings_exponential_notation)) }, + supportingContent = { Text(stringResource(R.string.settings_exponential_notation_support)) }, + ) + + Row( + Modifier + .horizontalScroll(rememberScrollState()) + .wrapContentWidth() + .padding(start = 56.dp), + ) { + SegmentedButtonsRow { + SegmentedButton( + label = stringResource(R.string.settings_auto), + onClick = { onOutputFormatChange(OutputFormat.ALLOW_ENGINEERING) }, + selected = OutputFormat.ALLOW_ENGINEERING == uiState.outputFormat, + ) + SegmentedButton( + label = stringResource(R.string.enabled_label), + onClick = { onOutputFormatChange(OutputFormat.FORCE_ENGINEERING) }, + selected = OutputFormat.FORCE_ENGINEERING == uiState.outputFormat, + ) + SegmentedButton( + label = stringResource(R.string.disabled_label), + onClick = { onOutputFormatChange(OutputFormat.PLAIN) }, + selected = OutputFormat.PLAIN == uiState.outputFormat, + ) + } + } + } + } +} + +@Preview +@Composable +private fun PreviewFormattingScreen() { + var currentPrecision by remember { mutableIntStateOf(6) } + var currentFormatterSymbols by remember { mutableStateOf(FormatterSymbols(Token.SPACE, Token.PERIOD)) } + var currentOutputFormat by remember { mutableIntStateOf(OutputFormat.PLAIN) } + + FormattingScreen( + uiState = FormattingUIState( + precision = 16, + outputFormat = OutputFormat.PLAIN, + formatterSymbols = currentFormatterSymbols, + ), + onPrecisionChange = { currentPrecision = it }, + updateFormatterSymbols = updateFormatterSymbols@{ grouping, fractional -> + currentFormatterSymbols = FormatterSymbols(grouping, fractional) + }, + onOutputFormatChange = { currentOutputFormat = it }, + navigateUpAction = {}, + ) +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingUIState.kt similarity index 85% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingUIState.kt index 65d1f826..0fd6b87c 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingUIState.kt @@ -16,13 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.formatting +package app.myzel394.numberhub.feature.settings.formatting -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols +import app.myzel394.numberhub.core.base.FormatterSymbols data class FormattingUIState( val precision: Int, - val separator: Int, val outputFormat: Int, val formatterSymbols: FormatterSymbols, ) diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingViewModel.kt similarity index 72% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingViewModel.kt index 64741259..3a1f119a 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/formatting/FormattingViewModel.kt @@ -16,14 +16,13 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.formatting +package app.myzel394.numberhub.feature.settings.formatting import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.core.base.MAX_PRECISION +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -31,16 +30,15 @@ import javax.inject.Inject @HiltViewModel class FormattingViewModel @Inject constructor( - private val userPreferencesRepository: UserPreferencesRepository + private val userPreferencesRepository: UserPreferencesRepository, ) : ViewModel() { - private val _prefs = userPreferencesRepository.formattingPrefs + private val prefs = userPreferencesRepository.formattingPrefs - val uiState = _prefs.map { mainPrefs -> + val uiState = prefs.map { mainPrefs -> FormattingUIState( precision = mainPrefs.digitsPrecision, - separator = mainPrefs.separator, outputFormat = mainPrefs.outputFormat, - formatterSymbols = AllFormatterSymbols.getById(mainPrefs.separator) + formatterSymbols = mainPrefs.formatterSymbols, ) } .stateIn(viewModelScope, null) @@ -55,10 +53,10 @@ class FormattingViewModel @Inject constructor( } /** - * @see UserPreferencesRepository.updateSeparator + * @see UserPreferencesRepository.updateFormatterSymbols */ - fun updateSeparator(separator: Int) = viewModelScope.launch { - userPreferencesRepository.updateSeparator(separator) + fun updateFormatterSymbols(grouping: String, fractional: String) = viewModelScope.launch { + userPreferencesRepository.updateFormatterSymbols(grouping, fractional) } /** diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/language/LanguageScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/language/LanguageScreen.kt similarity index 81% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/language/LanguageScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/language/LanguageScreen.kt index 7119ffc6..5a0e8b9c 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/language/LanguageScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/language/LanguageScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.language +package app.myzel394.numberhub.feature.settings.language import androidx.appcompat.app.AppCompatDelegate import androidx.compose.foundation.clickable @@ -35,19 +35,19 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.os.LocaleListCompat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.feature.settings.components.AnnoyingBox +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.openLink +import app.myzel394.numberhub.feature.settings.components.AnnoyingBox @Composable internal fun LanguageRoute( navigateUp: () -> Unit, ) { LanguageScreen( - navigateUp = navigateUp + navigateUp = navigateUp, ) } @@ -61,8 +61,11 @@ private fun LanguageScreen( } fun changeLanguage(langKey: String) { - val selectedLocale = if (langKey == "") LocaleListCompat.getEmptyLocaleList() - else LocaleListCompat.forLanguageTags(langKey) + val selectedLocale = if (langKey == "") { + LocaleListCompat.getEmptyLocaleList() + } else { + LocaleListCompat.forLanguageTags(langKey) + } AppCompatDelegate.setApplicationLocales(selectedLocale) navigateUp() @@ -70,7 +73,7 @@ private fun LanguageScreen( ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_language), - navigationIcon = { NavigateUpButton(navigateUp) } + navigationIcon = { NavigateUpButton(navigateUp) }, ) { padding -> LazyColumn(contentPadding = padding) { item("translate") { @@ -79,7 +82,7 @@ private fun LanguageScreen( imageVector = Icons.Default.Translate, imageVectorContentDescription = stringResource(R.string.settings_translate_app), title = stringResource(R.string.settings_translate_app), - support = stringResource(R.string.settings_translate_app_support) + support = stringResource(R.string.settings_translate_app_support), ) { openLink(mContext, "https://poeditor.com/join/project/T4zjmoq8dx") } @@ -95,9 +98,9 @@ private fun LanguageScreen( leadingContent = { RadioButton( selected = currentLangKey == key, - onClick = { changeLanguage(key) } + onClick = { changeLanguage(key) }, ) - } + }, ) } } @@ -109,6 +112,6 @@ private fun LanguageScreen( @Composable fun LanguageScreenPreview() { LanguageScreen( - navigateUp = {} + navigateUp = {}, ) } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/language/Languages.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/language/Languages.kt similarity index 93% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/language/Languages.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/language/Languages.kt index bfdb0882..1b56728b 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/language/Languages.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/language/Languages.kt @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.language +package app.myzel394.numberhub.feature.settings.language -import com.sadellie.unitto.core.base.R +import app.myzel394.numberhub.core.base.R internal val languages by lazy { mapOf( diff --git a/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/navigation/SettingsNavigation.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/navigation/SettingsNavigation.kt new file mode 100644 index 00000000..2a3338c2 --- /dev/null +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/navigation/SettingsNavigation.kt @@ -0,0 +1,143 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.settings.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.navDeepLink +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.unittoComposable +import app.myzel394.numberhub.core.ui.unittoNavigation +import app.myzel394.numberhub.core.ui.unittoStackedComposable +import app.myzel394.numberhub.feature.settings.SettingsRoute +import app.myzel394.numberhub.feature.settings.about.AboutRoute +import app.myzel394.numberhub.feature.settings.bouncingemoji.BouncingEmojiRoute +import app.myzel394.numberhub.feature.settings.calculator.CalculatorSettingsRoute +import app.myzel394.numberhub.feature.settings.converter.ConverterSettingsRoute +import app.myzel394.numberhub.feature.settings.display.DisplayRoute +import app.myzel394.numberhub.feature.settings.formatting.FormattingRoute +import app.myzel394.numberhub.feature.settings.language.LanguageRoute +import app.myzel394.numberhub.feature.settings.startingscreen.StartingScreenRoute +import app.myzel394.numberhub.feature.settings.thirdparty.ThirdPartyLicensesScreen +import app.myzel394.numberhub.feature.settings.unitgroups.UnitGroupsRoute +import io.github.sadellie.themmo.ThemmoController + +private val graph = DrawerItem.Settings.graph +private val start = DrawerItem.Settings.start +internal const val DISPLAY_ROUTE = "display_route" +internal const val LANGUAGE_ROUTE = "language_route" +internal const val STARTING_SCREEN_ROUTE = "starting_screen_route" +internal const val UNITS_GROUP_ROUTE = "units_group_route" +internal const val THIRD_PARTY_ROUTE = "third_party_route" +internal const val ABOUT_ROUTE = "about_route" +internal const val FORMATTING_ROUTE = "formatting_route" +internal const val CALCULATOR_SETTINGS_ROUTE = "calculator_settings_route" +internal const val CONVERTER_SETTINGS_ROUTE = "converter_settings_route" +internal const val BOUNCING_EMOJI_ROUTE = "bouncing_emoji_route" + +fun NavController.navigateToUnitGroups() { + navigate(UNITS_GROUP_ROUTE) +} + +fun NavGraphBuilder.settingGraph( + openDrawer: () -> Unit, + navController: NavHostController, + themmoController: ThemmoController, +) { + unittoNavigation( + startDestination = start, + route = graph, + deepLinks = listOf( + navDeepLink { uriPattern = "app://app.myzel394.numberhub/$graph" }, + ), + ) { + unittoComposable(start) { + SettingsRoute( + openDrawer = openDrawer, + navControllerAction = navController::navigate, + ) + } + + unittoStackedComposable(DISPLAY_ROUTE) { + DisplayRoute( + navigateUp = navController::navigateUp, + themmoController = themmoController, + navigateToLanguages = { navController.navigate(LANGUAGE_ROUTE) }, + ) + } + + unittoStackedComposable(LANGUAGE_ROUTE) { + LanguageRoute( + navigateUp = navController::navigateUp, + ) + } + + unittoStackedComposable(STARTING_SCREEN_ROUTE) { + StartingScreenRoute( + navigateUp = navController::navigateUp, + ) + } + + unittoStackedComposable(FORMATTING_ROUTE) { + FormattingRoute( + navigateUpAction = navController::navigateUp, + ) + } + + unittoStackedComposable(CALCULATOR_SETTINGS_ROUTE) { + CalculatorSettingsRoute( + navigateUpAction = navController::navigateUp, + ) + } + + unittoStackedComposable(CONVERTER_SETTINGS_ROUTE) { + ConverterSettingsRoute( + navigateUpAction = navController::navigateUp, + navigateToUnitsGroup = { navController.navigate(UNITS_GROUP_ROUTE) }, + ) + } + + unittoStackedComposable(UNITS_GROUP_ROUTE) { + UnitGroupsRoute( + navigateUpAction = navController::navigateUp, + ) + } + + unittoStackedComposable(ABOUT_ROUTE) { + AboutRoute( + navigateUpAction = navController::navigateUp, + navigateToThirdParty = { navController.navigate(THIRD_PARTY_ROUTE) }, + navigateToEasterEgg = { navController.navigate(BOUNCING_EMOJI_ROUTE) }, + ) + } + + unittoStackedComposable(THIRD_PARTY_ROUTE) { + ThirdPartyLicensesScreen( + navigateUpAction = navController::navigateUp, + ) + } + + unittoStackedComposable(BOUNCING_EMOJI_ROUTE) { + BouncingEmojiRoute( + navigateUpAction = navController::navigateUp, + ) + } + } +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/startingscreen/StartingScreenScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/startingscreen/StartingScreenScreen.kt similarity index 83% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/startingscreen/StartingScreenScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/startingscreen/StartingScreenScreen.kt index e8afadd5..54ca350c 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/startingscreen/StartingScreenScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/startingscreen/StartingScreenScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.startingscreen +package app.myzel394.numberhub.feature.settings.startingscreen import android.os.Build import androidx.compose.foundation.clickable @@ -35,18 +35,18 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.addShortcut -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.addShortcut +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.model.DrawerItem @Composable internal fun StartingScreenRoute( viewModel: StartingScreenViewModel = hiltViewModel(), - navigateUp: () -> Unit + navigateUp: () -> Unit, ) { when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) { null -> EmptyScreen() @@ -54,7 +54,7 @@ internal fun StartingScreenRoute( StartingScreenScreen( startingScreen = prefs.startingScreen, updateStartingScreen = viewModel::updateStartingScreen, - navigateUp = navigateUp + navigateUp = navigateUp, ) } } @@ -64,13 +64,13 @@ internal fun StartingScreenRoute( private fun StartingScreenScreen( startingScreen: String, updateStartingScreen: (String) -> Unit, - navigateUp: () -> Unit + navigateUp: () -> Unit, ) { val mContext = LocalContext.current ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_starting_screen), - navigationIcon = { NavigateUpButton(navigateUp) } + navigationIcon = { NavigateUpButton(navigateUp) }, ) { padding -> LazyColumn(contentPadding = padding) { items(DrawerItem.main, { it.graph }) { destination -> @@ -82,18 +82,18 @@ private fun StartingScreenScreen( leadingContent = { RadioButton( selected = destination.graph == startingScreen, - onClick = { updateStartingScreen(destination.graph) } + onClick = { updateStartingScreen(destination.graph) }, ) }, trailingContent = trail@{ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return@trail IconButton( - onClick = { mContext.addShortcut(destination) } + onClick = { mContext.addShortcut(destination) }, ) { Icon(Icons.Default.AppShortcut, null) } - } + }, ) } } @@ -106,6 +106,6 @@ private fun StartingScreenPreview() { StartingScreenScreen( startingScreen = DrawerItem.Converter.graph, updateStartingScreen = {}, - navigateUp = {} + navigateUp = {}, ) } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/startingscreen/StartingScreenViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/startingscreen/StartingScreenViewModel.kt similarity index 87% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/startingscreen/StartingScreenViewModel.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/startingscreen/StartingScreenViewModel.kt index c7a8714a..56a757c9 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/startingscreen/StartingScreenViewModel.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/startingscreen/StartingScreenViewModel.kt @@ -16,12 +16,12 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.startingscreen +package app.myzel394.numberhub.feature.settings.startingscreen import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/thirdparty/ThirdPartyLicensesScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/thirdparty/ThirdPartyLicensesScreen.kt similarity index 84% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/thirdparty/ThirdPartyLicensesScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/thirdparty/ThirdPartyLicensesScreen.kt index 5336dd87..183ec3d0 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/thirdparty/ThirdPartyLicensesScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/thirdparty/ThirdPartyLicensesScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.thirdparty +package app.myzel394.numberhub.feature.settings.thirdparty import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -36,11 +36,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.data.licenses.ALL_THIRD_PARTY +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.core.ui.openLink +import app.myzel394.numberhub.data.licenses.ALL_THIRD_PARTY /** * Screen with used third party libraries @@ -50,13 +50,13 @@ import com.sadellie.unitto.data.licenses.ALL_THIRD_PARTY @Stable @Composable internal fun ThirdPartyLicensesScreen( - navigateUpAction: () -> Unit = {} + navigateUpAction: () -> Unit = {}, ) { val mContext = LocalContext.current ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_third_party_licenses), - navigationIcon = { NavigateUpButton(navigateUpAction) } + navigationIcon = { NavigateUpButton(navigateUpAction) }, ) { padding -> LazyColumn( verticalArrangement = Arrangement.spacedBy(16.dp), @@ -64,35 +64,35 @@ internal fun ThirdPartyLicensesScreen( start = 16.dp, end = 16.dp, top = padding.calculateTopPadding(), - bottom = 24.dp - ) + bottom = 24.dp, + ), ) { items(ALL_THIRD_PARTY) { OutlinedCard( - Modifier.clickable { it.website?.let { url -> openLink(mContext, url) } } + Modifier.clickable { it.website?.let { url -> openLink(mContext, url) } }, ) { Column( modifier = Modifier .fillMaxWidth() - .padding(12.dp) + .padding(12.dp), ) { Text( text = it.name, - style = MaterialTheme.typography.titleLarge + style = MaterialTheme.typography.titleLarge, ) Text( modifier = Modifier.padding(top = 4.dp, bottom = 12.dp), text = it.dev ?: "", - style = MaterialTheme.typography.bodyLarge + style = MaterialTheme.typography.bodyLarge, ) Text( text = it.description ?: "", - style = MaterialTheme.typography.bodyMedium + style = MaterialTheme.typography.bodyMedium, ) Text( modifier = Modifier.align(Alignment.End), text = it.license ?: "", - style = MaterialTheme.typography.labelLarge + style = MaterialTheme.typography.labelLarge, ) } } diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsScreen.kt similarity index 57% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsScreen.kt index 29413f26..a9e18624 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.unitgroups +package app.myzel394.numberhub.feature.settings.unitgroups import androidx.compose.animation.animateColor import androidx.compose.animation.core.animateDp @@ -40,18 +40,23 @@ import androidx.compose.material3.ListItemDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.Header -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.Header +import app.myzel394.numberhub.core.ui.common.NavigateUpButton +import app.myzel394.numberhub.core.ui.common.ScaffoldWithLargeTopBar +import app.myzel394.numberhub.data.model.converter.UnitGroup import org.burnoutcrew.reorderable.ReorderableItem import org.burnoutcrew.reorderable.detectReorder import org.burnoutcrew.reorderable.detectReorderAfterLongPress @@ -59,43 +64,79 @@ import org.burnoutcrew.reorderable.rememberReorderableLazyListState import org.burnoutcrew.reorderable.reorderable @Composable -internal fun UnitGroupsScreen( +internal fun UnitGroupsRoute( viewModel: UnitGroupsViewModel = hiltViewModel(), navigateUpAction: () -> Unit, +) { + when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { + UnitGroupsUIState.Loading -> EmptyScreen() + is UnitGroupsUIState.Ready -> UnitGroupsScreen( + uiState = uiState, + navigateUpAction = navigateUpAction, + updateShownUnitGroups = viewModel::updateShownUnitGroups, + addShownUnitGroup = viewModel::addShownUnitGroup, + removeShownUnitGroup = viewModel::removeShownUnitGroup, + ) + } +} + +@Composable +private fun UnitGroupsScreen( + uiState: UnitGroupsUIState.Ready, + navigateUpAction: () -> Unit, + updateShownUnitGroups: (List) -> Unit, + addShownUnitGroup: (UnitGroup) -> Unit, + removeShownUnitGroup: (UnitGroup) -> Unit, ) { ScaffoldWithLargeTopBar( title = stringResource(R.string.settings_unit_groups_title), - navigationIcon = { NavigateUpButton(navigateUpAction) } + navigationIcon = { NavigateUpButton(navigateUpAction) }, ) { paddingValues -> - - val shownUnits = viewModel.shownUnitGroups.collectAsState() - val hiddenUnits = viewModel.hiddenUnitGroups.collectAsState() - + val copiedShownList = rememberUpdatedState(uiState.shownUnitGroups) as MutableState val state = rememberReorderableLazyListState( - onMove = viewModel::onMove, - canDragOver = { from, _ -> viewModel.canDragOver(from) }, - onDragEnd = { _, _ -> viewModel.onDragEnd() } + onMove = { from, to -> + copiedShownList.value = copiedShownList.value + .toMutableList() + .apply { + // -1 for list header + add(to.index - 1, removeAt(from.index - 1)) + } + }, + canDragOver = { draggedOver, _ -> + // offset by 1 for list header + draggedOver.index in 1..(copiedShownList.value.lastIndex + 1) + }, + onDragEnd = onDragEnd@{ from, to -> + if (from == to) return@onDragEnd + updateShownUnitGroups(copiedShownList.value) + }, ) LazyColumn( state = state.listState, modifier = Modifier .padding(paddingValues) - .reorderable(state) + .reorderable(state), ) { item(key = "enabled") { Header( text = stringResource(R.string.enabled_label), - paddingValues = PaddingValues(horizontal = 16.dp, vertical = 12.dp) + paddingValues = PaddingValues(horizontal = 16.dp, vertical = 12.dp), ) } - items(shownUnits.value, { it }) { item -> + items(copiedShownList.value, { it }) { item -> ReorderableItem(state, key = item) { isDragging -> val transition = updateTransition(isDragging, label = "draggedTransition") val background by transition.animateColor(label = "background") { if (it) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surface } + val textColor by transition.animateColor(label = "background") { + if (it) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurface + } + val iconColor by transition.animateColor(label = "background") { + if (it) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.outline + } val itemPadding by transition.animateDp(label = "itemPadding") { if (it) 16.dp else 0.dp } @@ -105,35 +146,36 @@ internal fun UnitGroupsScreen( modifier = Modifier .padding(horizontal = itemPadding) .clip(CircleShape) - .clickable { viewModel.hideUnitGroup(item) } + .clickable { removeShownUnitGroup(item) } .detectReorderAfterLongPress(state), colors = ListItemDefaults.colors( - containerColor = background + containerColor = background, + headlineColor = textColor, + leadingIconColor = iconColor, + trailingIconColor = iconColor, ), leadingContent = { Icon( - Icons.Default.RemoveCircle, - stringResource(R.string.settings_disable_unit_group_description), - tint = MaterialTheme.colorScheme.outline, + imageVector = Icons.Default.RemoveCircle, + contentDescription = stringResource(R.string.settings_disable_unit_group_description), modifier = Modifier.clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(false), - onClick = { viewModel.hideUnitGroup(item) } - ) + onClick = { removeShownUnitGroup(item) }, + ), ) }, trailingContent = { Icon( - Icons.Default.DragHandle, - stringResource(R.string.settings_reorder_unit_group_description), - tint = MaterialTheme.colorScheme.outline, + imageVector = Icons.Default.DragHandle, + contentDescription = stringResource(R.string.settings_reorder_unit_group_description), modifier = Modifier .clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(false), - onClick = {} + onClick = {}, ) - .detectReorder(state) + .detectReorder(state), ) }, ) @@ -144,15 +186,15 @@ internal fun UnitGroupsScreen( Header( text = stringResource(R.string.disabled_label), modifier = Modifier.animateItemPlacement(), - paddingValues = PaddingValues(horizontal = 16.dp, vertical = 12.dp) + paddingValues = PaddingValues(horizontal = 16.dp, vertical = 12.dp), ) } - items(hiddenUnits.value, { it }) { + items(uiState.hiddenUnitGroups, { it }) { ListItem( modifier = Modifier .background(MaterialTheme.colorScheme.surface) - .clickable { viewModel.returnUnitGroup(it) } + .clickable { addShownUnitGroup(it) } .animateItemPlacement(), headlineContent = { Text(stringResource(it.res)) }, trailingContent = { @@ -163,12 +205,29 @@ internal fun UnitGroupsScreen( modifier = Modifier.clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(false), - onClick = { viewModel.returnUnitGroup(it) } - ) + onClick = { addShownUnitGroup(it) }, + ), ) - } + }, ) } } } } + +@Preview +@Composable +private fun PreviewUnitGroupsScreen() { + val shownUnitGroups = UnitGroup.entries.take(4) + + UnitGroupsScreen( + uiState = UnitGroupsUIState.Ready( + shownUnitGroups = shownUnitGroups, + hiddenUnitGroups = UnitGroup.entries - shownUnitGroups.toSet(), + ), + navigateUpAction = {}, + updateShownUnitGroups = {}, + addShownUnitGroup = {}, + removeShownUnitGroup = {}, + ) +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsUIState.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsUIState.kt similarity index 64% rename from feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsUIState.kt rename to feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsUIState.kt index 899cb51e..498d5e88 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsUIState.kt +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsUIState.kt @@ -1,6 +1,6 @@ /* * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev + * Copyright (c) 2024 Elshan Agaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,14 +16,15 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.settings.calculator +package app.myzel394.numberhub.feature.settings.unitgroups -internal sealed class CalculatorSettingsUIState { - data object Loading : CalculatorSettingsUIState() +import app.myzel394.numberhub.data.model.converter.UnitGroup - data object RPN : CalculatorSettingsUIState() +internal sealed class UnitGroupsUIState { + data object Loading : UnitGroupsUIState() - data class Standard( - val partialHistoryView: Boolean, - ) : CalculatorSettingsUIState() + data class Ready( + val shownUnitGroups: List, + val hiddenUnitGroups: List, + ) : UnitGroupsUIState() } diff --git a/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsViewModel.kt b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsViewModel.kt new file mode 100644 index 00000000..16c26bfa --- /dev/null +++ b/feature/settings/src/main/java/app/myzel394/numberhub/feature/settings/unitgroups/UnitGroupsViewModel.kt @@ -0,0 +1,71 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package app.myzel394.numberhub.feature.settings.unitgroups + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.converter.UnitGroup +import app.myzel394.numberhub.data.model.repository.UserPreferencesRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +internal class UnitGroupsViewModel @Inject constructor( + private val userPrefsRepository: UserPreferencesRepository, +) : ViewModel() { + + val uiState = userPrefsRepository.unitGroupsPrefs + .map { + UnitGroupsUIState.Ready( + shownUnitGroups = it.shownUnitGroups, + hiddenUnitGroups = UnitGroup.entries - it.shownUnitGroups.toSet(), + ) + } + .stateIn(viewModelScope, UnitGroupsUIState.Loading) + + /** + * @see UserPreferencesRepository.removeShownUnitGroup + */ + fun removeShownUnitGroup(unitGroup: UnitGroup) { + viewModelScope.launch { + userPrefsRepository.removeShownUnitGroup(unitGroup) + } + } + + /** + * @see UserPreferencesRepository.addShownUnitGroup + */ + fun addShownUnitGroup(unitGroup: UnitGroup) { + viewModelScope.launch { + userPrefsRepository.addShownUnitGroup(unitGroup) + } + } + + /** + * @see UserPreferencesRepository.updateShownUnitGroups + */ + fun updateShownUnitGroups(unitGroups: List) { + viewModelScope.launch { + userPrefsRepository.updateShownUnitGroups(unitGroups) + } + } +} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt deleted file mode 100644 index ee25cc90..00000000 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsScreen.kt +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.settings.calculator - -import androidx.compose.animation.Crossfade -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Timer -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar - -@Composable -internal fun CalculatorSettingsRoute( - viewModel: CalculatorSettingsViewModel = hiltViewModel(), - navigateUpAction: () -> Unit, -) { - when (val prefs = viewModel.uiState.collectAsStateWithLifecycle().value) { - CalculatorSettingsUIState.Loading -> EmptyScreen() - else -> { - CalculatorSettingsScreen( - uiState = prefs, - navigateUpAction = navigateUpAction, - updatePartialHistoryView = viewModel::updatePartialHistoryView, - updateRpnMode = viewModel::updateRpnMode, - ) - } - } -} - -// TODO Translate -@Composable -private fun CalculatorSettingsScreen( - uiState: CalculatorSettingsUIState, - navigateUpAction: () -> Unit, - updatePartialHistoryView: (Boolean) -> Unit, - updateRpnMode: (Boolean) -> Unit, -) { - ScaffoldWithLargeTopBar( - title = stringResource(R.string.calculator_title), - navigationIcon = { NavigateUpButton(navigateUpAction) } - ) { padding -> - Column(Modifier.padding(padding)) { -// SingleChoiceSegmentedButtonRow( -// modifier = Modifier -// .fillMaxWidth() -// .padding(16.dp) -// ) { -// SegmentedButton( -// selected = uiState is CalculatorSettingsUIState.Standard, -// onClick = { updateRpnMode(false) }, -// shape = SegmentedButtonDefaults.itemShape(index = 0, count = 2), -// ) { -// Text("Standard") -// } -// SegmentedButton( -// selected = uiState == CalculatorSettingsUIState.RPN, -// onClick = { updateRpnMode(true) }, -// shape = SegmentedButtonDefaults.itemShape(index = 1, count = 2), -// ) { -// Text("RPN") -// } -// } - - Crossfade( - targetState = uiState, - label = "Mode switch" - ) { state -> - when (state) { - is CalculatorSettingsUIState.Standard -> { - Column { - ListItem( - headlineText = stringResource(R.string.settings_partial_history_view), - icon = Icons.Default.Timer, - supportingText = stringResource(R.string.settings_partial_history_view_support), - switchState = state.partialHistoryView, - onSwitchChange = updatePartialHistoryView - ) - } - } - - else -> Unit - } - } - } - } -} - -@Preview -@Composable -private fun PreviewCalculatorSettingsScreenStandard() { - CalculatorSettingsScreen( - uiState = CalculatorSettingsUIState.Standard( - partialHistoryView = true, - ), - navigateUpAction = {}, - updatePartialHistoryView = {}, - updateRpnMode = {} - ) -} - -@Preview -@Composable -private fun PreviewCalculatorSettingsScreenRPN() { - CalculatorSettingsScreen( - uiState = CalculatorSettingsUIState.RPN, - navigateUpAction = {}, - updatePartialHistoryView = {}, - updateRpnMode = {} - ) -} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt deleted file mode 100644 index 41b4c69a..00000000 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/calculator/CalculatorSettingsViewModel.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.settings.calculator - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.launch -import javax.inject.Inject - -@HiltViewModel -internal class CalculatorSettingsViewModel @Inject constructor( - private val userPrefsRepository: UserPreferencesRepository, -) : ViewModel() { - val uiState = combine( - userPrefsRepository.appPrefs, - userPrefsRepository.calculatorPrefs, - ) { app, calc -> - if (app.rpnMode) { - CalculatorSettingsUIState.RPN - } else { - CalculatorSettingsUIState.Standard( - partialHistoryView = calc.partialHistoryView, - ) - } - } - .stateIn(viewModelScope, CalculatorSettingsUIState.Loading) - - fun updatePartialHistoryView(enabled: Boolean) = viewModelScope.launch { - userPrefsRepository.updatePartialHistoryView(enabled) - } - - fun updateRpnMode(enabled: Boolean) = viewModelScope.launch { - userPrefsRepository.updateRpnMode(enabled) - } -} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt deleted file mode 100644 index 724d728a..00000000 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.settings.formatting - -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.rememberScrollState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Architecture -import androidx.compose.material.icons.filled.EMobiledata -import androidx.compose.material.icons.filled._123 -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.core.base.OutputFormat -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.base.Separator -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.NavigateUpButton -import com.sadellie.unitto.core.ui.common.PagedIsland -import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.core.ui.common.SegmentedButton -import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow -import com.sadellie.unitto.core.ui.common.Slider -import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols -import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.core.ui.theme.LocalNumberTypography -import com.sadellie.unitto.data.common.format -import kotlin.math.ceil -import kotlin.math.roundToInt - -@Composable -fun FormattingRoute( - viewModel: FormattingViewModel = hiltViewModel(), - navigateUpAction: () -> Unit, -) { - when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { - null -> EmptyScreen() - else -> { - FormattingScreen( - navigateUpAction = navigateUpAction, - uiState = uiState, - onPrecisionChange = viewModel::updatePrecision, - onSeparatorChange = viewModel::updateSeparator, - onOutputFormatChange = viewModel::updateOutputFormat, - ) - } - } -} - -@Composable -fun FormattingScreen( - navigateUpAction: () -> Unit, - uiState: FormattingUIState, - onPrecisionChange: (Int) -> Unit, - onSeparatorChange: (Int) -> Unit, - onOutputFormatChange: (Int) -> Unit, - precisions: ClosedFloatingPointRange = 0f..16f, // 16th is a MAX_PRECISION (1000) -) { - val resources = LocalContext.current.resources - - val precisionText: String by remember(uiState.precision, uiState.formatterSymbols) { - derivedStateOf { - return@derivedStateOf if (uiState.precision >= precisions.endInclusive) { - resources.getString( - R.string.settings_precision_max, - MAX_PRECISION.toString().formatExpression(uiState.formatterSymbols) - ) - } else { - uiState.precision.toString() - } - } - } - - ScaffoldWithLargeTopBar( - title = stringResource(R.string.settings_formatting), - navigationIcon = { NavigateUpButton(navigateUpAction) }, - ) { paddingValues -> - LazyColumn( - modifier = Modifier - .padding(paddingValues) - ) { - item("preview") { - PagedIsland( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - pagerState = rememberPagerState { 2 }, - ) { currentPage -> - val preview = when (currentPage) { - 0 -> "123456.${"789123456".repeat(ceil(uiState.precision.toDouble() / 9.0).toInt())}" - 1 -> "0.${"1".padStart(uiState.precision, '0')}" - else -> "" - } - .toBigDecimalOrNull() - ?.format(uiState.precision, uiState.outputFormat) - ?.formatExpression(uiState.formatterSymbols) - ?: "" - - Text( - text = preview, - style = LocalNumberTypography.current.displayMedium, - maxLines = 1, - modifier = Modifier - .fillMaxWidth() - .horizontalScroll(rememberScrollState()), - textAlign = TextAlign.End, - color = MaterialTheme.colorScheme.onSecondaryContainer - ) - } - } - - item("precision_label") { - ListItem( - leadingContent = { - Icon( - Icons.Default.Architecture, - stringResource(R.string.settings_precision) - ) - }, - headlineContent = { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() - ) { - Text(stringResource(R.string.settings_precision)) - Text(precisionText) - } - }, - supportingContent = { - Text(stringResource(R.string.settings_precision_support)) - } - ) - } - - item("precision_slider") { - Slider( - modifier = Modifier.padding(start = 56.dp, end = 16.dp), - value = uiState.precision.toFloat(), - valueRange = precisions, - onValueChange = { onPrecisionChange(it.roundToInt()) }, - ) - } - - item("separator_label") { - ListItem( - leadingContent = { - Icon(Icons.Default._123, stringResource(R.string.settings_separator)) - }, - headlineContent = { Text(stringResource(R.string.settings_separator)) }, - supportingContent = { Text(stringResource(R.string.settings_separator_support)) }, - ) - } - - item("separator") { - Row( - Modifier - .horizontalScroll(rememberScrollState()) - .wrapContentWidth() - .padding(start = 56.dp) - ) { - SegmentedButtonsRow { - SegmentedButton( - label = stringResource(R.string.settings_space), - onClick = { onSeparatorChange(Separator.SPACE) }, - selected = Separator.SPACE == uiState.separator - ) - SegmentedButton( - label = stringResource(R.string.settings_period), - onClick = { onSeparatorChange(Separator.PERIOD) }, - selected = Separator.PERIOD == uiState.separator - ) - SegmentedButton( - label = stringResource(R.string.comma), - onClick = { onSeparatorChange(Separator.COMMA) }, - selected = Separator.COMMA == uiState.separator - ) - } - } - } - - item("output_format_label") { - ListItem( - leadingContent = { - Icon(Icons.Default.EMobiledata, stringResource(R.string.settings_precision)) - }, - headlineContent = { Text(stringResource(R.string.settings_exponential_notation)) }, - supportingContent = { Text(stringResource(R.string.settings_exponential_notation_support)) } - ) - } - - item("output_format") { - Row( - Modifier - .horizontalScroll(rememberScrollState()) - .wrapContentWidth() - .padding(start = 56.dp) - ) { - SegmentedButtonsRow { - SegmentedButton( - label = stringResource(R.string.settings_auto), - onClick = { onOutputFormatChange(OutputFormat.ALLOW_ENGINEERING) }, - selected = OutputFormat.ALLOW_ENGINEERING == uiState.outputFormat - ) - SegmentedButton( - label = stringResource(R.string.enabled_label), - onClick = { onOutputFormatChange(OutputFormat.FORCE_ENGINEERING) }, - selected = OutputFormat.FORCE_ENGINEERING == uiState.outputFormat - ) - SegmentedButton( - label = stringResource(R.string.disabled_label), - onClick = { onOutputFormatChange(OutputFormat.PLAIN) }, - selected = OutputFormat.PLAIN == uiState.outputFormat - ) - } - } - } - } - } -} - -@Preview -@Composable -private fun PreviewFormattingScreen() { - var currentPrecision by remember { mutableIntStateOf(6) } - var currentSeparator by remember { mutableIntStateOf(Separator.COMMA) } - var currentOutputFormat by remember { mutableIntStateOf(OutputFormat.PLAIN) } - - FormattingScreen( - uiState = FormattingUIState( - precision = 16, - separator = Separator.SPACE, - outputFormat = OutputFormat.PLAIN, - formatterSymbols = FormatterSymbols.Spaces - ), - onPrecisionChange = { currentPrecision = it }, - onSeparatorChange = { currentSeparator = it }, - onOutputFormatChange = { currentOutputFormat = it }, - navigateUpAction = {}, - ) -} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt deleted file mode 100644 index fcb77b70..00000000 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/navigation/SettingsNavigation.kt +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.settings.navigation - -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavHostController -import androidx.navigation.navDeepLink -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.core.ui.unittoStackedComposable -import com.sadellie.unitto.feature.settings.SettingsRoute -import com.sadellie.unitto.feature.settings.about.AboutRoute -import com.sadellie.unitto.feature.settings.calculator.CalculatorSettingsRoute -import com.sadellie.unitto.feature.settings.converter.ConverterSettingsRoute -import com.sadellie.unitto.feature.settings.display.DisplayRoute -import com.sadellie.unitto.feature.settings.formatting.FormattingRoute -import com.sadellie.unitto.feature.settings.language.LanguageRoute -import com.sadellie.unitto.feature.settings.startingscreen.StartingScreenRoute -import com.sadellie.unitto.feature.settings.thirdparty.ThirdPartyLicensesScreen -import com.sadellie.unitto.feature.settings.unitgroups.UnitGroupsScreen -import io.github.sadellie.themmo.ThemmoController - -private val graph = DrawerItem.Settings.graph -private val start = DrawerItem.Settings.start -internal const val displayRoute = "display_route" -internal const val languageRoute = "language_route" -internal const val startingScreenRoute = "starting_screen_route" -internal const val unitsGroupRoute = "units_group_route" -internal const val thirdPartyRoute = "third_party_route" -internal const val aboutRoute = "about_route" -internal const val formattingRoute = "formatting_route" -internal const val calculatorSettingsRoute = "calculator_settings_route" -internal const val converterSettingsRoute = "converter_settings_route" - -fun NavController.navigateToSettings() { - navigate(DrawerItem.Settings.start) -} - -fun NavController.navigateToUnitGroups() { - navigate(unitsGroupRoute) -} - -fun NavGraphBuilder.settingGraph( - themmoController: ThemmoController, - navController: NavHostController, -) { - unittoNavigation( - startDestination = start, - route = graph, - deepLinks = listOf( - navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" } - ) - ) { - unittoStackedComposable(start) { - SettingsRoute( - navigateUp = navController::navigateUp, - navControllerAction = navController::navigate - ) - } - - unittoStackedComposable(displayRoute) { - DisplayRoute( - navigateUp = navController::navigateUp, - themmoController = themmoController, - navigateToLanguages = { navController.navigate(languageRoute) } - ) - } - - unittoStackedComposable(languageRoute) { - LanguageRoute( - navigateUp = navController::navigateUp, - ) - } - - unittoStackedComposable(startingScreenRoute) { - StartingScreenRoute( - navigateUp = navController::navigateUp, - ) - } - - unittoStackedComposable(formattingRoute) { - FormattingRoute( - navigateUpAction = navController::navigateUp - ) - } - - unittoStackedComposable(calculatorSettingsRoute) { - CalculatorSettingsRoute( - navigateUpAction = navController::navigateUp, - ) - } - - unittoStackedComposable(converterSettingsRoute) { - ConverterSettingsRoute( - navigateUpAction = navController::navigateUp, - navigateToUnitsGroup = { navController.navigate(unitsGroupRoute) } - ) - } - - unittoStackedComposable(unitsGroupRoute) { - UnitGroupsScreen( - navigateUpAction = navController::navigateUp, - ) - } - - unittoStackedComposable(aboutRoute) { - AboutRoute( - navigateUpAction = navController::navigateUp, - navigateToThirdParty = { navController.navigate(thirdPartyRoute) } - ) - } - - unittoStackedComposable(thirdPartyRoute) { - ThirdPartyLicensesScreen( - navigateUpAction = navController::navigateUp, - ) - } - } -} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsRepository .kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsRepository .kt deleted file mode 100644 index e4d258ae..00000000 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsRepository .kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.settings.unitgroups - -import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS -import com.sadellie.unitto.data.model.UnitGroup -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.burnoutcrew.reorderable.ItemPosition -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Repository that holds information about shown and hidden [UnitGroup]s and provides methods to - * show/hide [UnitGroup]s. - */ -@Singleton -class UnitGroupsRepository @Inject constructor() { - - /** - * Mutex is need needed because we work with flow (sync stuff). - */ - private val mutex = Mutex() - - /** - * Currently shown [UnitGroup]s. - */ - var shownUnitGroups = MutableStateFlow(listOf()) - private set - - /** - * Currently hidden [UnitGroup]s. - */ - var hiddenUnitGroups = MutableStateFlow(listOf()) - private set - - /** - * Sets [shownUnitGroups] and updates [hiddenUnitGroups] as a side effect. [hiddenUnitGroups] is - * everything from [ALL_UNIT_GROUPS] that was not in [shownUnitGroups]. - * - * @param list List of [UnitGroup]s that need to be shown. - */ - suspend fun updateShownGroups(list: List) { - mutex.withLock { - shownUnitGroups.value = list - hiddenUnitGroups.value = ALL_UNIT_GROUPS - list.toSet() - } - } - - /** - * Moves [UnitGroup] from [shownUnitGroups] to [hiddenUnitGroups] - * - * @param unitGroup [UnitGroup] to hide. - */ - suspend fun markUnitGroupAsHidden(unitGroup: UnitGroup) { - mutex.withLock { - shownUnitGroups.value = shownUnitGroups.value - unitGroup - // Newly hidden unit will appear at the top of the list - hiddenUnitGroups.value = listOf(unitGroup) + hiddenUnitGroups.value - } - } - - /** - * Moves [UnitGroup] from [hiddenUnitGroups] to [shownUnitGroups] - * - * @param unitGroup [UnitGroup] to show. - */ - suspend fun markUnitGroupAsShown(unitGroup: UnitGroup) { - mutex.withLock { - hiddenUnitGroups.value = hiddenUnitGroups.value - unitGroup - shownUnitGroups.value = shownUnitGroups.value + unitGroup - } - } - - /** - * Moves [UnitGroup] in [shownUnitGroups] from one index to another (reorder). - * - * @param from Position from which we need to move from - * @param to Position where to put [UnitGroup] - */ - suspend fun moveShownUnitGroups(from: ItemPosition, to: ItemPosition) { - mutex.withLock { - shownUnitGroups.value = shownUnitGroups.value.toMutableList().apply { - val initialIndex = shownUnitGroups.value.indexOfFirst { it == from.key } - /** - * No such item. Happens when dragging item and clicking "remove" while item is - * still being dragged. - */ - if (initialIndex == -1) return - - add( - shownUnitGroups.value.indexOfFirst { it == to.key }, - removeAt(initialIndex) - ) - } - } - } -} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt deleted file mode 100644 index 47245de9..00000000 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.settings.unitgroups - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import org.burnoutcrew.reorderable.ItemPosition -import javax.inject.Inject - -@HiltViewModel -class UnitGroupsViewModel @Inject constructor( - private val userPrefsRepository: UserPreferencesRepository, - private val unitGroupsRepository: UnitGroupsRepository, -) : ViewModel() { - val shownUnitGroups = unitGroupsRepository.shownUnitGroups - val hiddenUnitGroups = unitGroupsRepository.hiddenUnitGroups - - /** - * @see UnitGroupsRepository.markUnitGroupAsHidden - * @see UserPreferencesRepository.updateShownUnitGroups - */ - fun hideUnitGroup(unitGroup: UnitGroup) { - viewModelScope.launch { - unitGroupsRepository.markUnitGroupAsHidden(unitGroup) - userPrefsRepository.updateShownUnitGroups(unitGroupsRepository.shownUnitGroups.value) - } - } - - /** - * @see UnitGroupsRepository.markUnitGroupAsShown - * @see UserPreferencesRepository.updateShownUnitGroups - */ - fun returnUnitGroup(unitGroup: UnitGroup) { - viewModelScope.launch { - unitGroupsRepository.markUnitGroupAsShown(unitGroup) - userPrefsRepository.updateShownUnitGroups(unitGroupsRepository.shownUnitGroups.value) - } - } - - /** - * @see UnitGroupsRepository.moveShownUnitGroups - */ - fun onMove(from: ItemPosition, to: ItemPosition) { - viewModelScope.launch { - unitGroupsRepository.moveShownUnitGroups(from, to) - } - } - - /** - * @see UserPreferencesRepository.updateShownUnitGroups - */ - fun onDragEnd() { - viewModelScope.launch { - userPrefsRepository.updateShownUnitGroups(unitGroupsRepository.shownUnitGroups.value) - } - } - - /** - * Prevent from dragging over non-draggable items (headers and hidden) - * - * @param pos Position we are dragging over. - * @return True if can drag over given item. - */ - fun canDragOver(pos: ItemPosition) = shownUnitGroups.value.any { it == pos.key } - - init { - viewModelScope.launch { - unitGroupsRepository.updateShownGroups( - userPrefsRepository.unitGroupsPrefs.first().shownUnitGroups - ) - } - } -} diff --git a/feature/timezone/build.gradle.kts b/feature/timezone/build.gradle.kts index 40d7989f..8c6cce73 100644 --- a/feature/timezone/build.gradle.kts +++ b/feature/timezone/build.gradle.kts @@ -24,12 +24,11 @@ plugins { id("unitto.android.library.jacoco") } -android.namespace = "com.sadellie.unitto.feature.timezone" +android.namespace = "app.myzel394.numberhub.feature.timezone" dependencies { testImplementation(libs.org.robolectric.robolectric) - implementation(libs.com.github.sadellie.themmo) implementation(libs.org.burnoutcrew.composereorderable.reorderable) implementation(libs.androidx.appcompat.appcompat) diff --git a/feature/timezone/src/androidTest/java/com/sadellie/unitto/feature/timezone/components/FavoriteTimeZonesTest.kt b/feature/timezone/src/androidTest/java/app/myzel394/numberhub/feature/timezone/components/FavoriteTimeZonesTest.kt similarity index 89% rename from feature/timezone/src/androidTest/java/com/sadellie/unitto/feature/timezone/components/FavoriteTimeZonesTest.kt rename to feature/timezone/src/androidTest/java/app/myzel394/numberhub/feature/timezone/components/FavoriteTimeZonesTest.kt index 54b9cec6..6068c9f2 100644 --- a/feature/timezone/src/androidTest/java/com/sadellie/unitto/feature/timezone/components/FavoriteTimeZonesTest.kt +++ b/feature/timezone/src/androidTest/java/app/myzel394/numberhub/feature/timezone/components/FavoriteTimeZonesTest.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone.components +package app.myzel394.numberhub.feature.timezone.components import android.icu.text.LocaleDisplayNames import android.icu.text.TimeZoneNames @@ -29,7 +29,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText -import com.sadellie.unitto.data.model.timezone.FavoriteZone +import app.myzel394.numberhub.data.model.timezone.FavoriteZone import org.junit.Rule import org.junit.Test import java.time.ZonedDateTime @@ -52,11 +52,11 @@ class FavoriteTimeZonesTest { item = FavoriteZone( timeZone = TimeZone.getTimeZone("Africa/Addis_Ababa"), position = -1, - label = "label text" + label = "label text", ), fromTime = ZonedDateTime.parse( "2023-05-01T14:00+03:00[Africa/Addis_Ababa]", - DateTimeFormatter.ISO_ZONED_DATE_TIME + DateTimeFormatter.ISO_ZONED_DATE_TIME, ), expanded = true, onClick = {}, @@ -65,11 +65,10 @@ class FavoriteTimeZonesTest { onLabelClick = {}, isDragging = false, timeZoneNames = timeZoneNames, - localeDisplayNames = localeDisplayNames + localeDisplayNames = localeDisplayNames, ) } onNodeWithText("11:00").assertExists() } - -} \ No newline at end of file +} diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneScreen.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneScreen.kt similarity index 85% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneScreen.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneScreen.kt index 3579e923..c72f9b0e 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneScreen.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import android.icu.text.LocaleDisplayNames import android.icu.text.TimeZoneNames @@ -45,18 +45,18 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.LocalLocale -import com.sadellie.unitto.core.ui.common.SearchPlaceholder -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ListItem -import com.sadellie.unitto.core.ui.common.SearchBar -import com.sadellie.unitto.core.ui.datetime.formatTime -import com.sadellie.unitto.core.ui.openLink -import com.sadellie.unitto.data.common.displayName -import com.sadellie.unitto.data.common.offset -import com.sadellie.unitto.data.common.regionName -import com.sadellie.unitto.data.model.timezone.SearchResultZone +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.LocalLocale +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ListItem +import app.myzel394.numberhub.core.ui.common.SearchBar +import app.myzel394.numberhub.core.ui.common.SearchPlaceholder +import app.myzel394.numberhub.core.ui.datetime.formatTime +import app.myzel394.numberhub.core.ui.openLink +import app.myzel394.numberhub.data.common.displayName +import app.myzel394.numberhub.data.common.offset +import app.myzel394.numberhub.data.common.regionName +import app.myzel394.numberhub.data.model.timezone.SearchResultZone import java.time.ZonedDateTime @RequiresApi(Build.VERSION_CODES.N) @@ -73,7 +73,7 @@ internal fun AddTimeZoneRoute( navigateUp = navigateUp, onQueryChange = viewModel::onQueryChange, addToFavorites = viewModel::addToFavorites, - userTime = userTime + userTime = userTime, ) } } @@ -106,7 +106,7 @@ fun AddTimeZoneScreen( Crossfade( modifier = Modifier.padding(paddingValues), targetState = uiState.list.isEmpty() and uiState.query.text.isNotEmpty(), - label = "Placeholder" + label = "Placeholder", ) { empty -> if (empty) { SearchPlaceholder( @@ -131,9 +131,9 @@ fun AddTimeZoneScreen( text = it.timeZone .offset(userTime) .formatTime(locale, is24Hour), - style = MaterialTheme.typography.headlineSmall + style = MaterialTheme.typography.headlineSmall, ) - } + }, ) } } @@ -156,23 +156,23 @@ fun PreviewAddTimeZoneScreen() { list = listOf( "UTC", "Africa/Addis_Ababa", - "ACT" + "ACT", ).map { val zone = TimeZone.getTimeZone(it) SearchResultZone( timeZone = zone, region = zone.regionName( timeZoneNames = timeZoneNames, - localeDisplayNames = localeDisplayNames + localeDisplayNames = localeDisplayNames, ), name = zone.displayName(locale), - rank = 0 + rank = 0, ) - } + }, ), navigateUp = {}, onQueryChange = {}, addToFavorites = {}, - userTime = ZonedDateTime.now() + userTime = ZonedDateTime.now(), ) } diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneUIState.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneUIState.kt similarity index 82% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneUIState.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneUIState.kt index 819d81e1..d16ce207 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneUIState.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneUIState.kt @@ -16,16 +16,16 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import androidx.compose.ui.text.input.TextFieldValue -import com.sadellie.unitto.data.model.timezone.SearchResultZone +import app.myzel394.numberhub.data.model.timezone.SearchResultZone sealed class AddTimeZoneUIState { - data object Loading: AddTimeZoneUIState() + data object Loading : AddTimeZoneUIState() data class Ready( val query: TextFieldValue, val list: List, - ): AddTimeZoneUIState() + ) : AddTimeZoneUIState() } diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneViewModel.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneViewModel.kt similarity index 79% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneViewModel.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneViewModel.kt index 8119e570..25dcc203 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/AddTimeZoneViewModel.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/AddTimeZoneViewModel.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import android.icu.util.TimeZone import android.icu.util.ULocale @@ -26,9 +26,9 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.timezone.SearchResultZone -import com.sadellie.unitto.data.timezone.TimeZonesRepository +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.timezone.SearchResultZone +import app.myzel394.numberhub.data.timezone.TimeZonesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine @@ -42,14 +42,14 @@ import javax.inject.Inject class AddTimeZoneViewModel @Inject constructor( private val timezonesRepository: TimeZonesRepository, ) : ViewModel() { - private val _query = MutableStateFlow(TextFieldValue()) - private val _result = MutableStateFlow(emptyList()) + private val query = MutableStateFlow(TextFieldValue()) + private val result = MutableStateFlow(emptyList()) val uiState = combine( - _query, - _result, + query, + result, timezonesRepository.favoriteTimeZones, - ) { query, result, _ -> + ) { query, result, _ -> return@combine AddTimeZoneUIState.Ready( query = query, list = result, @@ -57,12 +57,12 @@ class AddTimeZoneViewModel @Inject constructor( } .mapLatest { ui -> viewModelScope.launch { - _result.update { + result.update { timezonesRepository.filter( searchQuery = ui.query.text, locale = ULocale.forLanguageTag( - AppCompatDelegate.getApplicationLocales().toLanguageTags() - ) + AppCompatDelegate.getApplicationLocales().toLanguageTags(), + ), ) } } @@ -70,7 +70,7 @@ class AddTimeZoneViewModel @Inject constructor( } .stateIn(viewModelScope, AddTimeZoneUIState.Loading) - fun onQueryChange(textFieldValue: TextFieldValue) = _query.update { textFieldValue } + fun onQueryChange(textFieldValue: TextFieldValue) = query.update { textFieldValue } fun addToFavorites(timeZone: TimeZone) = viewModelScope.launch { timezonesRepository.addToFavorites(timeZone) diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneExt.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneExt.kt similarity index 95% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneExt.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneExt.kt index 2e723714..7ff79323 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneExt.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneExt.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import android.icu.util.TimeZone import android.os.Build @@ -28,6 +28,5 @@ val TimeZone.offsetSeconds @RequiresApi(Build.VERSION_CODES.N) get() = this.rawOffset / 1000L - @RequiresApi(Build.VERSION_CODES.N) fun TimeZone.timeNow(): ZonedDateTime = ZonedDateTime.now(ZoneId.of(this.id, ZoneId.SHORT_IDS)) diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneScreen.kt similarity index 90% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneScreen.kt index 60acd6c0..3231855b 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneScreen.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import android.icu.text.LocaleDisplayNames import android.icu.text.TimeZoneNames @@ -72,15 +72,14 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.MenuButton -import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar -import com.sadellie.unitto.core.ui.common.datetimepicker.TimePickerDialog -import com.sadellie.unitto.data.model.timezone.FavoriteZone -import com.sadellie.unitto.feature.timezone.components.FavoriteTimeZoneItem -import com.sadellie.unitto.feature.timezone.components.UserTimeZone +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.common.DrawerButton +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.common.ScaffoldWithTopBar +import app.myzel394.numberhub.core.ui.common.datetimepicker.TimePickerDialog +import app.myzel394.numberhub.data.model.timezone.FavoriteZone +import app.myzel394.numberhub.feature.timezone.components.FavoriteTimeZoneItem +import app.myzel394.numberhub.feature.timezone.components.UserTimeZone import kotlinx.coroutines.android.awaitFrame import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -94,8 +93,7 @@ import java.time.ZonedDateTime @Composable internal fun TimeZoneRoute( viewModel: TimeZoneViewModel = hiltViewModel(), - openMenu: () -> Unit, - navigateToSettings: () -> Unit, + openDrawer: () -> Unit, navigateToAddTimeZone: (ZonedDateTime) -> Unit, ) { when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) { @@ -103,8 +101,7 @@ internal fun TimeZoneRoute( is TimeZoneUIState.Ready -> { TimeZoneScreen( uiState = uiState, - openMenu = openMenu, - navigateToSettings = navigateToSettings, + openDrawer = openDrawer, navigateToAddTimeZone = navigateToAddTimeZone, setCurrentTime = viewModel::setCurrentTime, setSelectedTime = viewModel::setSelectedTime, @@ -112,7 +109,7 @@ internal fun TimeZoneRoute( delete = viewModel::delete, updateLabel = viewModel::updateLabel, selectTimeZone = viewModel::selectTimeZone, - setDialogState = viewModel::setDialogState + setDialogState = viewModel::setDialogState, ) } } @@ -122,8 +119,7 @@ internal fun TimeZoneRoute( @Composable private fun TimeZoneScreen( uiState: TimeZoneUIState.Ready, - openMenu: () -> Unit, - navigateToSettings: () -> Unit, + openDrawer: () -> Unit, navigateToAddTimeZone: (ZonedDateTime) -> Unit, setCurrentTime: () -> Unit, setSelectedTime: (ZonedDateTime) -> Unit, @@ -136,7 +132,7 @@ private fun TimeZoneScreen( val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) var currentUserTime by remember(uiState.customUserTime) { mutableStateOf( - uiState.customUserTime ?: uiState.userTimeZone.timeNow() + uiState.customUserTime ?: uiState.userTimeZone.timeNow(), ) } val focusRequester = remember { FocusRequester() } @@ -174,18 +170,17 @@ private fun TimeZoneScreen( val targetInOldTz = uiState.favorites.getOrNull(to - 1) ?: return@onDragEnd onDragEnd(tz, targetInOldTz.position) - } + }, ) ScaffoldWithTopBar( title = { Text(stringResource(R.string.time_zone_title)) }, - navigationIcon = { MenuButton(openMenu) }, - actions = { SettingsButton(navigateToSettings) }, + navigationIcon = { DrawerButton(openDrawer) }, floatingActionButton = { LargeFloatingActionButton( onClick = { navigateToAddTimeZone(currentUserTime) - } + }, ) { Icon( imageVector = Icons.Filled.Add, @@ -204,7 +199,7 @@ private fun TimeZoneScreen( .padding(padding) .reorderable(state), contentPadding = PaddingValues(start = 8.dp, end = 8.dp, bottom = 124.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), ) { item("user time") { UserTimeZone( @@ -214,7 +209,7 @@ private fun TimeZoneScreen( userTime = currentUserTime, onClick = { setDialogState(TimeZoneDialogState.UserTimePicker(currentUserTime)) }, onResetClick = setCurrentTime, - showReset = uiState.customUserTime != null + showReset = uiState.customUserTime != null, ) } @@ -274,11 +269,11 @@ private fun TimeZoneScreen( setSelectedTime( currentUserTime .withHour(hour) - .withMinute(minute) + .withMinute(minute), ) setDialogState(TimeZoneDialogState.Nothing) }, - onCancel = { setDialogState(TimeZoneDialogState.Nothing) } + onCancel = { setDialogState(TimeZoneDialogState.Nothing) }, ) } @@ -292,12 +287,12 @@ private fun TimeZoneScreen( .withHour(hour) .withMinute(minute) .minusSeconds(uiState.dialogState.timeZone.timeZone.offsetSeconds) - .plusSeconds(uiState.userTimeZone.offsetSeconds) + .plusSeconds(uiState.userTimeZone.offsetSeconds), ) setDialogState(TimeZoneDialogState.Nothing) }, - onCancel = { setDialogState(TimeZoneDialogState.Nothing) } + onCancel = { setDialogState(TimeZoneDialogState.Nothing) }, ) } @@ -306,8 +301,8 @@ private fun TimeZoneScreen( mutableStateOf( TextFieldValue( text = uiState.dialogState.timeZone.label, - selection = TextRange(uiState.dialogState.timeZone.label.length) - ) + selection = TextRange(uiState.dialogState.timeZone.label.length), + ), ) } AlertDialog( @@ -316,7 +311,7 @@ private fun TimeZoneScreen( OutlinedTextField( value = tfv, onValueChange = { tfv = it }, - modifier = Modifier.focusRequester(focusRequester) + modifier = Modifier.focusRequester(focusRequester), ) LaunchedEffect(Unit) { awaitFrame() @@ -329,13 +324,13 @@ private fun TimeZoneScreen( setDialogState(TimeZoneDialogState.Nothing) updateLabel(uiState.dialogState.timeZone, tfv.text) }, - content = { Text(text = stringResource(R.string.ok_label)) } + content = { Text(text = stringResource(R.string.ok_label)) }, ) }, dismissButton = { TextButton( onClick = { setDialogState(TimeZoneDialogState.Nothing) }, - content = { Text(text = stringResource(R.string.cancel_label)) } + content = { Text(text = stringResource(R.string.cancel_label)) }, ) }, onDismissRequest = { setDialogState(TimeZoneDialogState.Nothing) }, @@ -358,16 +353,15 @@ fun PreviewTimeZoneScreen() { FavoriteZone( timeZone = TimeZone.getTimeZone(tz), position = index, - label = if (tz == "ACT") "label text" else "" + label = if (tz == "ACT") "label text" else "", ) }, customUserTime = null, userTimeZone = TimeZone.getTimeZone("Africa/Addis_Ababa"), selectedTimeZone = null, - dialogState = TimeZoneDialogState.Nothing + dialogState = TimeZoneDialogState.Nothing, ), - openMenu = {}, - navigateToSettings = {}, + openDrawer = {}, navigateToAddTimeZone = {}, setCurrentTime = {}, setSelectedTime = {}, @@ -375,6 +369,6 @@ fun PreviewTimeZoneScreen() { delete = {}, updateLabel = { _, _ -> }, selectTimeZone = {}, - setDialogState = {} + setDialogState = {}, ) } diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneUIState.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneUIState.kt similarity index 93% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneUIState.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneUIState.kt index da392ea5..123f22c0 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneUIState.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneUIState.kt @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import android.icu.util.TimeZone -import com.sadellie.unitto.data.model.timezone.FavoriteZone +import app.myzel394.numberhub.data.model.timezone.FavoriteZone import java.time.ZonedDateTime internal sealed class TimeZoneUIState { diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneViewModel.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneViewModel.kt similarity index 66% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneViewModel.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneViewModel.kt index a692f57b..2694e9c8 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneViewModel.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/TimeZoneViewModel.kt @@ -16,16 +16,16 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone +package app.myzel394.numberhub.feature.timezone import android.icu.util.TimeZone import android.os.Build import androidx.annotation.RequiresApi import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.timezone.FavoriteZone -import com.sadellie.unitto.data.timezone.TimeZonesRepository +import app.myzel394.numberhub.data.common.stateIn +import app.myzel394.numberhub.data.model.timezone.FavoriteZone +import app.myzel394.numberhub.data.timezone.TimeZonesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine @@ -37,18 +37,18 @@ import javax.inject.Inject @RequiresApi(Build.VERSION_CODES.N) @HiltViewModel internal class TimeZoneViewModel @Inject constructor( - private val timezonesRepository: TimeZonesRepository -): ViewModel() { - private val _userTimeZone = MutableStateFlow(TimeZone.getDefault()) - private val _customUserTime = MutableStateFlow(null) - private val _selectedTimeZone = MutableStateFlow(null) - private val _dialogState = MutableStateFlow(TimeZoneDialogState.Nothing) + private val timezonesRepository: TimeZonesRepository, +) : ViewModel() { + private val userTimeZone = MutableStateFlow(TimeZone.getDefault()) + private val customUserTime = MutableStateFlow(null) + private val selectedTimeZone = MutableStateFlow(null) + private val dialogState = MutableStateFlow(TimeZoneDialogState.Nothing) val uiState = combine( - _customUserTime, - _userTimeZone, - _selectedTimeZone, - _dialogState, + customUserTime, + userTimeZone, + selectedTimeZone, + dialogState, timezonesRepository.favoriteTimeZones, ) { customUserTime, userTimeZone, selectedTimeZone, dialogState, favoriteTimeZones -> return@combine TimeZoneUIState.Ready( @@ -56,20 +56,20 @@ internal class TimeZoneViewModel @Inject constructor( customUserTime = customUserTime, userTimeZone = userTimeZone, selectedTimeZone = selectedTimeZone, - dialogState = dialogState + dialogState = dialogState, ) } .stateIn(viewModelScope, TimeZoneUIState.Loading) - fun setCurrentTime() = _customUserTime.update { null } + fun setCurrentTime() = customUserTime.update { null } - fun setSelectedTime(time: ZonedDateTime) = _customUserTime.update { time } + fun setSelectedTime(time: ZonedDateTime) = customUserTime.update { time } - fun setDialogState(state: TimeZoneDialogState) = _dialogState.update { state } + fun setDialogState(state: TimeZoneDialogState) = dialogState.update { state } fun onDragEnd( tz: FavoriteZone, - targetPosition: Int + targetPosition: Int, ) = viewModelScope.launch { timezonesRepository.moveTimeZone(tz, targetPosition) } @@ -78,11 +78,11 @@ internal class TimeZoneViewModel @Inject constructor( timezonesRepository.removeFromFavorites(timeZone) } - fun selectTimeZone(timeZone: FavoriteZone?) = _selectedTimeZone.update { timeZone } + fun selectTimeZone(timeZone: FavoriteZone?) = selectedTimeZone.update { timeZone } fun updateLabel( timeZone: FavoriteZone, - label: String + label: String, ) = viewModelScope.launch { timezonesRepository.updateLabel(timeZone = timeZone, label = label) } diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/components/FavoriteTimeZoneItem.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/components/FavoriteTimeZoneItem.kt similarity index 85% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/components/FavoriteTimeZoneItem.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/components/FavoriteTimeZoneItem.kt index 2508d968..9d7fd7f7 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/components/FavoriteTimeZoneItem.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/components/FavoriteTimeZoneItem.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone.components +package app.myzel394.numberhub.feature.timezone.components import android.icu.text.LocaleDisplayNames import android.icu.text.TimeZoneNames @@ -66,15 +66,15 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.LocalLocale -import com.sadellie.unitto.core.ui.common.ProvideColor -import com.sadellie.unitto.core.ui.common.ProvideStyle -import com.sadellie.unitto.core.ui.datetime.formatOffset -import com.sadellie.unitto.core.ui.datetime.formatTime -import com.sadellie.unitto.data.common.offset -import com.sadellie.unitto.data.common.regionName -import com.sadellie.unitto.data.model.timezone.FavoriteZone +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.LocalLocale +import app.myzel394.numberhub.core.ui.common.ProvideColor +import app.myzel394.numberhub.core.ui.common.ProvideStyle +import app.myzel394.numberhub.core.ui.datetime.formatOffset +import app.myzel394.numberhub.core.ui.datetime.formatTime +import app.myzel394.numberhub.data.common.offset +import app.myzel394.numberhub.data.common.regionName +import app.myzel394.numberhub.data.model.timezone.FavoriteZone import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @@ -99,7 +99,7 @@ internal fun FavoriteTimeZoneItem( val animatedAlpha by animateFloatAsState( label = "delete animation", targetValue = if (deleteAnimationRunning) 0f else 1f, - finishedListener = { if (it == 0f) onDelete() } + finishedListener = { if (it == 0f) onDelete() }, ) val regionName = remember(timeZoneNames, localeDisplayNames) { @@ -114,19 +114,19 @@ internal fun FavoriteTimeZoneItem( .graphicsLayer(alpha = animatedAlpha) .then(modifier) .clickable(enabled = !isDragging) { onClick() } - .padding(vertical = 16.dp, horizontal = 12.dp) + .padding(vertical = 16.dp, horizontal = 12.dp), ) { TimeZoneLabel( label = item.label, expanded = expanded, - onLabelClick = onLabelClick + onLabelClick = onLabelClick, ) Row( modifier = Modifier .padding() .heightIn(min = 56.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp) + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { Column( modifier = Modifier @@ -139,16 +139,16 @@ internal fun FavoriteTimeZoneItem( style = MaterialTheme.typography.bodyLarge, maxLines = 2, overflow = TextOverflow.Ellipsis, - color = MaterialTheme.colorScheme.onSurface + color = MaterialTheme.colorScheme.onSurface, ) AnimatedVisibility( visible = offsetTimeFormatted != null, - label = "Nullable offset" + label = "Nullable offset", ) { Text( text = offsetTimeFormatted ?: "", style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -157,12 +157,12 @@ internal fun FavoriteTimeZoneItem( label = "Time change", transitionSpec = { fadeIn() togetherWith fadeOut() using (SizeTransform(clip = false)) - } + }, ) { time -> Text( text = time, style = MaterialTheme.typography.headlineMedium, - color = MaterialTheme.colorScheme.onSurface + color = MaterialTheme.colorScheme.onSurface, ) } } @@ -173,13 +173,13 @@ internal fun FavoriteTimeZoneItem( title = stringResource(R.string.select_time_label), icon = Icons.Outlined.Schedule, contentDescription = stringResource(R.string.select_time_label), - onClick = { onPrimaryClick(offsetTime) } + onClick = { onPrimaryClick(offsetTime) }, ) TimeZoneOption( title = stringResource(R.string.delete_label), icon = Icons.Outlined.Delete, contentDescription = stringResource(R.string.delete_label), - onClick = { deleteAnimationRunning = true } + onClick = { deleteAnimationRunning = true }, ) } } @@ -192,7 +192,7 @@ private fun TimeZoneOption( icon: ImageVector, contentDescription: String, onClick: () -> Unit, -) = ProvideColor(MaterialTheme.colorScheme.onSurfaceVariant){ +) = ProvideColor(MaterialTheme.colorScheme.onSurfaceVariant) { Row( modifier = Modifier .clip(RoundedCornerShape(4.dp)) @@ -200,7 +200,7 @@ private fun TimeZoneOption( .fillMaxWidth() .padding(horizontal = 8.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { Icon( imageVector = icon, @@ -219,7 +219,7 @@ private fun TimeZoneLabel( onLabelClick: () -> Unit, ) = ProvideStyle( color = MaterialTheme.colorScheme.onSurfaceVariant, - textStyle = MaterialTheme.typography.bodyMedium + textStyle = MaterialTheme.typography.bodyMedium, ) { AnimatedContent( label = "Expand animation", @@ -230,11 +230,12 @@ private fun TimeZoneLabel( AnimatedVisibility(expanded) { Row( modifier = Modifier.height(24.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Icon( imageVector = Icons.Default.Edit, - contentDescription = null, // Not required because there is text next to it + // Not required because there is text next to it + contentDescription = null, modifier = Modifier.padding(end = 8.dp), ) Text( @@ -245,12 +246,13 @@ private fun TimeZoneLabel( } else { Row( modifier = Modifier.height(24.dp), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { AnimatedVisibility(visible = expanded) { Icon( imageVector = Icons.Default.Edit, - contentDescription = null, // Not required because there is text next to it + // Not required because there is text next to it + contentDescription = null, modifier = Modifier.padding(end = 8.dp), ) } @@ -277,7 +279,7 @@ private class FavoriteTimeZoneItemParameterProvider : tz = FavoriteZone( timeZone = TimeZone.getDefault(), position = 1, - label = "" + label = "", ), ), FavoriteTimeZoneItemParameter( @@ -285,7 +287,7 @@ private class FavoriteTimeZoneItemParameterProvider : tz = FavoriteZone( timeZone = TimeZone.getDefault(), position = 1, - label = "Some text" + label = "Some text", ), ), FavoriteTimeZoneItemParameter( @@ -293,7 +295,7 @@ private class FavoriteTimeZoneItemParameterProvider : tz = FavoriteZone( timeZone = TimeZone.getDefault(), position = 1, - label = "" + label = "", ), ), FavoriteTimeZoneItemParameter( @@ -301,9 +303,9 @@ private class FavoriteTimeZoneItemParameterProvider : tz = FavoriteZone( timeZone = TimeZone.getDefault(), position = 1, - label = "Some text" + label = "Some text", ), - ) + ), ) } @@ -324,7 +326,7 @@ private fun PreviewFavoriteTimeZones( item = tz.tz, fromTime = ZonedDateTime.parse( "2023-05-01T14:00+03:00[Africa/Addis_Ababa]", - DateTimeFormatter.ISO_ZONED_DATE_TIME + DateTimeFormatter.ISO_ZONED_DATE_TIME, ), expanded = expanded, onClick = { expanded = !expanded }, @@ -333,6 +335,6 @@ private fun PreviewFavoriteTimeZones( onLabelClick = {}, isDragging = false, timeZoneNames = timeZoneNames, - localeDisplayNames = localeDisplayNames + localeDisplayNames = localeDisplayNames, ) } diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/components/UserTimeZone.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/components/UserTimeZone.kt similarity index 86% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/components/UserTimeZone.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/components/UserTimeZone.kt index 6b9b7769..96f5cd70 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/components/UserTimeZone.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/components/UserTimeZone.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone.components +package app.myzel394.numberhub.feature.timezone.components import android.text.format.DateFormat import androidx.compose.animation.AnimatedContent @@ -50,14 +50,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.LocalLocale -import com.sadellie.unitto.core.ui.common.squashable -import com.sadellie.unitto.core.ui.datetime.formatDateDayMonthYear -import com.sadellie.unitto.core.ui.datetime.formatTimeAmPm -import com.sadellie.unitto.core.ui.datetime.formatTimeHours -import com.sadellie.unitto.core.ui.datetime.formatTimeMinutes -import com.sadellie.unitto.core.ui.datetime.formatZone +import app.myzel394.numberhub.core.base.R +import app.myzel394.numberhub.core.ui.LocalLocale +import app.myzel394.numberhub.core.ui.common.squashable +import app.myzel394.numberhub.core.ui.datetime.formatDateDayMonthYear +import app.myzel394.numberhub.core.ui.datetime.formatTimeAmPm +import app.myzel394.numberhub.core.ui.datetime.formatTimeHours +import app.myzel394.numberhub.core.ui.datetime.formatTimeMinutes +import app.myzel394.numberhub.core.ui.datetime.formatZone import java.time.ZonedDateTime @Composable @@ -77,7 +77,7 @@ internal fun UserTimeZone( onClick = onClick, onLongClick = onResetClick, cornerRadiusRange = 8.dp..32.dp, - interactionSource = remember { MutableInteractionSource() } + interactionSource = remember { MutableInteractionSource() }, ) .background(MaterialTheme.colorScheme.tertiaryContainer) .padding(horizontal = 16.dp, vertical = 12.dp), @@ -86,11 +86,11 @@ internal fun UserTimeZone( Text( text = userTime.formatZone(locale), style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onTertiaryContainer + color = MaterialTheme.colorScheme.onTertiaryContainer, ) Row( - verticalAlignment = Alignment.Bottom + verticalAlignment = Alignment.Bottom, ) { SlidingText(userTime.formatTimeHours(locale, is24Hour)) TimeSeparator() @@ -104,7 +104,7 @@ internal fun UserTimeZone( Text( text = userTime.formatDateDayMonthYear(locale), style = MaterialTheme.typography.headlineMedium, - color = MaterialTheme.colorScheme.onTertiaryContainer + color = MaterialTheme.colorScheme.onTertiaryContainer, ) } AnimatedVisibility( @@ -132,16 +132,16 @@ private fun SlidingText( label = "user time change", transitionSpec = { slideInVertically { height -> height } + fadeIn() togetherWith - slideOutVertically { height -> -height } + fadeOut() using - SizeTransform() - } + slideOutVertically { height -> -height } + fadeOut() using + SizeTransform() + }, ) { target -> Text( text = target, style = MaterialTheme.typography.displayLarge, color = MaterialTheme.colorScheme.onTertiaryContainer, overflow = TextOverflow.Visible, - maxLines = 1 + maxLines = 1, ) } } @@ -153,7 +153,7 @@ private fun TimeSeparator() { style = MaterialTheme.typography.displayLarge, color = MaterialTheme.colorScheme.onTertiaryContainer, overflow = TextOverflow.Visible, - maxLines = 1 + maxLines = 1, ) } @@ -165,6 +165,6 @@ private fun PreviewUserTimeZone() { userTime = ZonedDateTime.now(), onClick = {}, onResetClick = {}, - showReset = true + showReset = true, ) } diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/navigation/TimeZoneNavigation.kt b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/navigation/TimeZoneNavigation.kt similarity index 79% rename from feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/navigation/TimeZoneNavigation.kt rename to feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/navigation/TimeZoneNavigation.kt index fb2c6c53..a867ff6c 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/navigation/TimeZoneNavigation.kt +++ b/feature/timezone/src/main/java/app/myzel394/numberhub/feature/timezone/navigation/TimeZoneNavigation.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.feature.timezone.navigation +package app.myzel394.numberhub.feature.timezone.navigation import android.os.Build import androidx.navigation.NavController @@ -25,12 +25,12 @@ import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.navArgument import androidx.navigation.navDeepLink -import com.sadellie.unitto.core.ui.common.EmptyScreen -import com.sadellie.unitto.core.ui.model.DrawerItem -import com.sadellie.unitto.core.ui.unittoComposable -import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.feature.timezone.AddTimeZoneRoute -import com.sadellie.unitto.feature.timezone.TimeZoneRoute +import app.myzel394.numberhub.core.ui.common.EmptyScreen +import app.myzel394.numberhub.core.ui.model.DrawerItem +import app.myzel394.numberhub.core.ui.unittoComposable +import app.myzel394.numberhub.core.ui.unittoNavigation +import app.myzel394.numberhub.feature.timezone.AddTimeZoneRoute +import app.myzel394.numberhub.feature.timezone.TimeZoneRoute import java.time.ZonedDateTime import java.time.format.DateTimeFormatter @@ -40,7 +40,7 @@ private const val ADD_TIME_ZONE_ROUTE = "ADD_TIME_ZONE_ROUTE" private const val USER_TIME_ARG = "USER_TIME_ARG" private fun NavController.navigateToAddTimeZone( - userTime: ZonedDateTime + userTime: ZonedDateTime, ) { val formattedTime = userTime .format(DateTimeFormatter.ISO_ZONED_DATE_TIME) @@ -50,16 +50,15 @@ private fun NavController.navigateToAddTimeZone( } fun NavGraphBuilder.timeZoneGraph( - navigateToMenu: () -> Unit, - navigateToSettings: () -> Unit, + openDrawer: () -> Unit, navController: NavHostController, ) { unittoNavigation( startDestination = start, route = graph, deepLinks = listOf( - navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" } - ) + navDeepLink { uriPattern = "app://app.myzel394.numberhub/$graph" }, + ), ) { unittoComposable(start) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { @@ -68,9 +67,8 @@ fun NavGraphBuilder.timeZoneGraph( } TimeZoneRoute( - openMenu = navigateToMenu, - navigateToSettings = navigateToSettings, - navigateToAddTimeZone = navController::navigateToAddTimeZone + openDrawer = openDrawer, + navigateToAddTimeZone = navController::navigateToAddTimeZone, ) } @@ -81,8 +79,8 @@ fun NavGraphBuilder.timeZoneGraph( defaultValue = null nullable = true type = NavType.StringType - } - ) + }, + ), ) { stackEntry -> if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { EmptyScreen() @@ -97,7 +95,7 @@ fun NavGraphBuilder.timeZoneGraph( AddTimeZoneRoute( navigateUp = navController::navigateUp, - userTime = userTime + userTime = userTime, ) } } diff --git a/gradle/init.gradle.kts b/gradle/init.gradle.kts new file mode 100644 index 00000000..f0ae9341 --- /dev/null +++ b/gradle/init.gradle.kts @@ -0,0 +1,66 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +val ktlintVersion = "1.0.1" + +initscript { + val spotlessVersion = "6.23.3" + + repositories { + mavenCentral() + } + + dependencies { + classpath("com.diffplug.spotless:spotless-plugin-gradle:$spotlessVersion") + } +} + +rootProject { + subprojects { + apply() + extensions.configure { + kotlin { + target("**/*.kt") + targetExclude( + "**/build/**/*.kt", + "**/com/sadellie/unitto/data/converter/collections/*.kt", + "**/com/sadellie/unitto/core/ui/common/icons/iconpack/*.kt", + ) + ktlint(ktlintVersion).editorConfigOverride( + mapOf( + "android" to "true", + ), + ) + toggleOffOn() + // TODO licenseHeaderFile(rootProject.file("spotless/copyright.kt")) + } + format("kts") { + target("**/*.kts") + targetExclude("**/build/**/*.kts") + // Look for the first line that doesn't have a block comment (assumed to be the license) + // TODO licenseHeaderFile(rootProject.file("spotless/copyright.kts"), "(^(?![\\/ ]\\*).*$)") + } + format("xml") { + target("**/*.xml") + targetExclude("**/build/**/*.xml") + // Look for the first XML tag that isn't a comment (