Compare commits

...

55 Commits

Author SHA1 Message Date
Myzel394
9df12ca237
Merge pull request #48 from Myzel394/update-dependencies 2024-10-23 20:51:03 +02:00
Myzel394
bc62f7ec98
Merge pull request #41 from crisp5/date-diff-365days-patch 2024-10-23 20:23:45 +02:00
Myzel394
f6551934c7
chore: Update dependencies
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-10-23 20:20:51 +02:00
Myzel394
fea7175bcc
fix(docs): Fix long_description.txt 2024-10-17 17:29:41 +02:00
Myzel394
45c99de9af
fix(docs): Fix short_description.txt 2024-10-17 17:28:36 +02:00
Myzel394
12cbb05f17
Merge pull request #46 from PingoLeon/master
core: Add / Improve French translation
2024-09-23 10:43:58 +02:00
Léon
32329da46d
core: Add / Improve French translation 2024-09-23 17:11:38 +09:00
crisp5
bbaf17233f
Use 365 days to compute date difference 2024-09-10 01:22:49 +00:00
Myzel394
05c8513249
Merge pull request #37 from iKeramat/master
core: Add Persian(farsi) translation
2024-09-02 19:09:41 +02:00
Mohammad Hasan Keramat J
d1a3a4799a core: Add Persian(farsi) translation
Signed-off-by: Mohammad Hasan Keramat J <ikeramat@libremobileos.com>
2024-09-02 13:59:40 +03:30
Myzel394
ce2ce6ff74
Merge pull request #22 from Myzel394/hotfix-issue-21
Fix crash
2024-07-22 22:34:07 +02:00
Myzel394
87104feb98
chore: Update version
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-22 22:09:03 +02:00
Myzel394
4e509cbbfd
fix(converter): Only show OneValueSummary if unitTo is not 0
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-22 22:08:49 +02:00
Myzel394
d7f410c66f
Merge pull request #20 from sitiom/izzyondroid
docs: add IzzyOnDroid badge
2024-07-22 20:00:02 +02:00
Myzel394
776faa2d62
fix: Clean IzzyOnDroid badge 2024-07-22 19:57:52 +02:00
Ryan Caezar Itang
b6ba89065d
docs: add IzzyOnDroid badge 2024-07-22 23:50:29 +08:00
Myzel394
1b292c1c31
chore: Fix version
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-22 16:49:02 +02:00
Myzel394
879a7b68c5
Merge pull request #19 from Myzel394/update-version
chore: Fix version
2024-07-22 16:33:33 +02:00
Myzel394
aacc153ec2
chore: Fix version
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-22 16:20:43 +02:00
Myzel394
5439dde324
Merge pull request #16 from Myzel394/version-5
Version 5
2024-07-22 16:08:58 +02:00
Myzel394
57ea6f1ec7
Merge remote-tracking branch 'origin/version-5' into version-5 2024-07-21 22:09:22 +02:00
Myzel394
fc60b81699
feat(ci-cd): Increase Java heap size
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 22:09:13 +02:00
Myzel394
11fe482992
Merge pull request #17 from Crazy-Unicooorn/master
Updated french translations
2024-07-21 21:15:55 +02:00
Myzel394
cc7c719ee9
test(evaluator): Fix incorrect character (use minus from UTF-8 Mathematical Operators instead of "-" from ASCII Punctuation)
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 19:59:15 +02:00
Myzel394
33293a4c28
fix(evaluator): Fix power
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 19:27:37 +02:00
Myzel394
b53a0b1f92
test(evaluator): Add more tests
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 19:04:52 +02:00
Myzel394
84ddb6b6fa
fix(evaluator)!: Throw exception when trying to do 0^0
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 19:04:38 +02:00
Myzel394
6a5efe92ba
tests(evaluator): Add more tests
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 18:55:23 +02:00
Myzel394
5a9440dd17
fix(evaluator): Improve sin and cos threshold values
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 18:55:12 +02:00
Myzel394
f313da7042
fix(evaluator): Fix square root rounding error; Closes #18
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-21 18:44:46 +02:00
Crazy Unicorn
84c76606ce updated french translation 2024-07-19 20:52:16 +00:00
Crazy Unicorn
cbf3fa54f8 updated french translations 2024-07-19 20:45:26 +00:00
Myzel394
a25e773f83
chore: Fix fastlane
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-19 19:50:37 +02:00
Myzel394
1e2cc1ca2e
chore: Fix versionName
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-19 19:50:25 +02:00
Myzel394
f92becc333
Merge pull request #13 from Myzel394/improve-keyboard-layout
Improve converter screen
2024-07-17 21:02:00 +02:00
Myzel394
a07aa51163
fix: Only show ValueOneSummary if value is available
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-16 20:41:37 +02:00
Myzel394
ad107b0143
fix: Fix ConverterKeyboard.kt overflow
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 22:23:32 +02:00
Myzel394
ab4c8a8963
feat: Add opinionated unit pairings
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 21:56:06 +02:00
Myzel394
a3da66a6f0
Merge pull request #15 from Myzel394/fix-units
Fix units
2024-07-13 16:46:57 +02:00
Myzel394
855f620548
feat: Add information for value of 1 for conversions
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 16:45:25 +02:00
Myzel394
305744f9d5
fix: Fix size
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 16:22:59 +02:00
Myzel394
5a694ea5c8
feat: Add single digit change feature for calculation summary
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 16:17:00 +02:00
Myzel394
2097ab593b
feat: Add base calculation summary underneath converter
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 16:02:07 +02:00
Myzel394
b343b78753
fix: Improve ConverterKeyboard.kt
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 16:01:27 +02:00
Myzel394
38ba85abaa
fix: Improve animation for ConverterKeyboard.kt
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 13:44:17 +02:00
Myzel394
00ca88b1e6
feat: Add animation to ConverterKeyboard.kt
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 12:45:16 +02:00
Myzel394
0a021975fc
fix: Fix unit values
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-13 11:44:36 +02:00
Myzel394
68c17d1d97
tests: Add more tests to area unit tests
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-12 23:55:32 +02:00
Myzel394
6cf9c53541
fix: Fix area unit values
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-12 23:55:07 +02:00
Myzel394
792dc9366b
feat: Set default ordering to scale ascending
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-12 23:08:48 +02:00
Myzel394
1a2ae455c9
fix: Add Hexadecimal as default NumberBase
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-12 22:46:28 +02:00
Myzel394
084d66ac88
feat: Add custom keyboard depending on input unit when in base converter screen
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-12 22:44:37 +02:00
Myzel394
7e9d057535
fix: Do not remember width and height to update correctly
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-12 22:43:39 +02:00
Myzel394
12938e9122
chore: Update dependencies
Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
2024-07-11 21:38:30 +02:00
Myzel394
902aad9f55
feat(docs): Update images 2024-06-04 21:58:16 +02:00
38 changed files with 2650 additions and 324 deletions

View File

@ -3,6 +3,9 @@ name: Build and push debug app
on: on:
pull_request: pull_request:
env:
JAVA_OPTS: -Xmx12G
jobs: jobs:
debug-builds: debug-builds:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -4,6 +4,9 @@ on:
release: release:
types: [ published ] types: [ published ]
env:
JAVA_OPTS: -Xmx12G
jobs: jobs:
release-app-github: release-app-github:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -4,6 +4,9 @@ on:
release: release:
types: [ published ] types: [ published ]
env:
JAVA_OPTS: -Xmx12G
jobs: jobs:
release-app-google-play: release-app-google-play:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -16,6 +16,7 @@
# Download NumberHub # Download NumberHub
[<img src="readme_content/google-play-badge.png" alt="Get it on Google Play" height="80">](https://play.google.com/store/apps/details?id=app.myzel394.numberhub) [<img src="readme_content/google-play-badge.png" alt="Get it on Google Play" height="80">](https://play.google.com/store/apps/details?id=app.myzel394.numberhub)
[<img src="readme_content/izzyondroid-badge.png" alt="Get it on IzzyOnDroid" height="80">](https://apt.izzysoft.de/fdroid/index/apk/app.myzel394.numberhub)
[<img src="readme_content/github-badge.png" alt="Get it on GitHub" height="80">](https://github.com/Myzel394/NumberHub/releases) [<img src="readme_content/github-badge.png" alt="Get it on GitHub" height="80">](https://github.com/Myzel394/NumberHub/releases)
[<img src="readme_content/obtainium-badge.png" alt="Get it on Obtainium" height="80">](https://apps.obtainium.imranr.dev/redirect?r=obtainium://add/https://github.com/Myzel394/NumberHub//) [<img src="readme_content/obtainium-badge.png" alt="Get it on Obtainium" height="80">](https://apps.obtainium.imranr.dev/redirect?r=obtainium://add/https://github.com/Myzel394/NumberHub//)

View File

@ -56,6 +56,7 @@ android {
"en-rGB", "en-rGB",
"de", "de",
"es", "es",
"fa",
"fr", "fr",
"hu", "hu",
"in", "in",

File diff suppressed because it is too large Load Diff

View File

@ -18,15 +18,37 @@
--> -->
<resources> <resources>
<!-- Person's height -->
<string name="body_mass_height">Taille</string>
<string name="body_mass_imperial">Impérial</string>
<string name="body_mass_metric">Métrique</string>
<string name="body_mass_normal">Poids normal</string>
<!-- Will be a text followed by a number like so: "Normal weight for your height - 60" -->
<!-- https://fr.wikipedia.org/wiki/Obésité for the terms used to qualify obese class-->
<string name="body_mass_normal_weight">Poids normal pour votre taille</string>
<string name="body_mass_obese_1">Obésité</string>
<string name="body_mass_obese_2">Obésité sévère</string>
<string name="body_mass_obese_3">Obésité morbide</string>
<string name="body_mass_overweight">En surpoids</string>
<!-- Also known as Body mass index (BMI) -->
<!-- Body Mass should be "Masse Corporelle" but is referred as "IMC" in France, which is commonly used and short for "Indice de Masse Corporelle"-->
<string name="body_mass_title">IMC</string>
<string name="body_mass_underweight">En sous-poids</string>
<!-- Person's weight -->
<string name="body_mass_weight">Poids</string>
<string name="calculator_clear_history_support">Toutes les expressions de l\'historique seront supprimées pour toujours. Cette action ne peux pas être annulée !</string> <string name="calculator_clear_history_support">Toutes les expressions de l\'historique seront supprimées pour toujours. Cette action ne peux pas être annulée !</string>
<string name="calculator_divide_by_zero_error">Impossible de diviser par 0</string> <string name="calculator_divide_by_zero_error">Impossible de diviser par 0</string>
<string name="calculator_no_history">Pas d\'historique</string> <string name="calculator_no_history">Aucun historique</string>
<string name="calculator_title">Calculatrice</string> <string name="calculator_title">Calculatrice</string>
<string name="cancel_label">Annuler</string> <string name="cancel_label">Annuler</string>
<string name="checked_filter_description">Filtre vérifié</string> <string name="checked_filter_description">Filtre vérifié</string>
<string name="clear_history_label">Vider l\'historique</string> <string name="clear_history_label">Vider l\'historique</string>
<string name="clear_input_description">Effacer l\'entrée</string> <string name="clear_input_description">Effacer l\'entrée</string>
<string name="clear_label">Clear</string> <string name="clear_label">Effacer</string>
<string name="click_to_try_again_label">Cliquez pour réessayer</string> <string name="click_to_try_again_label">Cliquez pour réessayer</string>
<string name="comma">Virgule</string> <string name="comma">Virgule</string>
<string name="converter_favorite_button_description">Ajouter ou supprimer une unité des favoris</string> <string name="converter_favorite_button_description">Ajouter ou supprimer une unité des favoris</string>
@ -36,7 +58,7 @@
<string name="converter_search_bar_placeholder">Rechercher des unités</string> <string name="converter_search_bar_placeholder">Rechercher des unités</string>
<string name="converter_swap_units_description">Échanger les unités</string> <string name="converter_swap_units_description">Échanger les unités</string>
<string name="copied_label">%1$s! copié</string> <string name="copied_label">%1$s! copié</string>
<string name="date_calculator_add">Ajouter</string> <string name="date_calculator_add">Ajouter </string>
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/33QTn2NVrjJT772cBDFRqSMH.png --> <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/33QTn2NVrjJT772cBDFRqSMH.png -->
<string name="date_calculator_days">Jours</string> <string name="date_calculator_days">Jours</string>
@ -52,7 +74,7 @@
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/33QTn2NVrjJT772cBDFRqSMH.png --> <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/33QTn2NVrjJT772cBDFRqSMH.png -->
<string name="date_calculator_months">Mois</string> <string name="date_calculator_months">Mois</string>
<string name="date_calculator_start">Début</string> <string name="date_calculator_start">Début</string>
<string name="date_calculator_subtract">Soustraire</string> <string name="date_calculator_subtract"> Soustraire</string>
<string name="date_calculator_title">Calculateur de date</string> <string name="date_calculator_title">Calculateur de date</string>
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/33QTn2NVrjJT772cBDFRqSMH.png --> <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/33QTn2NVrjJT772cBDFRqSMH.png -->
@ -61,13 +83,11 @@
<string name="drop_down_description">Ouvrir ou fermer le menu déroulant</string> <string name="drop_down_description">Ouvrir ou fermer le menu déroulant</string>
<string name="enabled_label">Activé</string> <string name="enabled_label">Activé</string>
<string name="error_label">Erreur</string> <string name="error_label">Erreur</string>
<string name="hello_label">Bonjour!</string> <string name="hello_label">Bonjour !</string>
<string name="loading_label">Chargement…</string> <string name="loading_label">Chargement…</string>
<string name="navigate_up_description">Naviguer vers le haut</string> <string name="navigate_up_description">Naviguer vers le haut</string>
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/9lSfdkfKShwyQFEF4nvbVaIb.jpg <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/9lSfdkfKShwyQFEF4nvbVaIb.jpg Used in this dialog window. Should be short -->
Used in this dialog window. Should be short -->
<string name="next_label">Suite</string> <string name="next_label">Suite</string>
<string name="no_results_description">Résultat de recherche vide</string> <string name="no_results_description">Résultat de recherche vide</string>
<string name="no_results_label">Aucun résultat trouvé</string> <string name="no_results_label">Aucun résultat trouvé</string>
@ -78,32 +98,34 @@ Used in this dialog window. Should be short -->
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/uWOHJmIq9riqsq7PO82ZQp3a.png --> <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/uWOHJmIq9riqsq7PO82ZQp3a.png -->
<string name="select_time_label">Choisir le temps</string> <string name="select_time_label">Choisir le temps</string>
<string name="settings_about_unitto">À propos d\'NumberHub</string> <string name="settings_about_unitto">À propos de NumberHub</string>
<string name="settings_about_unitto_support">En savoir plus sur l\'application</string> <string name="settings_about_unitto_support">En savoir plus sur l\'application</string>
<string name="settings_additional">Additional</string> <string name="settings_additional">Paramètres supplémentaires</string>
<string name="settings_amoled_dark">AMOLED Noir</string> <string name="settings_amoled_dark">Interface AMOLED</string>
<string name="settings_amoled_dark_support">Utiliser un fond noir pour les thèmes sombres</string> <string name="settings_amoled_dark_support">Utiliser un fond noir pour les thèmes sombres</string>
<string name="settings_auto">Auto</string> <string name="settings_auto">Auto</string>
<string name="settings_back_up">Sauvegarde</string>
<string name="settings_calculator_support">Vue historique</string> <string name="settings_calculator_support">Vue historique</string>
<string name="settings_clear_cache">Effacer le cache</string> <string name="settings_clear_cache">Effacer le cache</string>
<string name="settings_color_scheme">Palette de couleurs</string> <string name="settings_color_scheme">Palette de couleurs</string>
<string name="settings_color_theme">Thème couleur</string> <string name="settings_color_theme">Thème de couleurs</string>
<string name="settings_color_theme_support">Choisir un mode de thème</string> <string name="settings_color_theme_support">Choisir un mode de thème</string>
<string name="settings_converter_support">Groupes d\'unités, tri, formatage</string> <string name="settings_converter_support">Groupes d\'unités, tri, formatage</string>
<string name="settings_currency_rates_note_text">Les taux de change sont mis à jour quotidiennement. L\'application ne permet pas de suivre le marché en temps réel.</string> <string name="settings_currency_rates_note_text">Les taux de change sont mis à jour quotidiennement. L\'application ne permet pas de suivre le marché en temps réel.</string>
<string name="settings_currency_rates_note_title">Taux de conversion faux ?</string> <string name="settings_currency_rates_note_title">Taux de conversion faux ?</string>
<string name="settings_dark_mode">Sombre</string> <string name="settings_dark_mode">Sombre</string>
<string name="settings_decimal_separator">Séparateur de décimales</string>
<string name="settings_disable_unit_group_description">Désactiver le groupe d\'unités</string> <string name="settings_disable_unit_group_description">Désactiver le groupe d\'unités</string>
<string name="settings_display">Affichage</string> <string name="settings_display">Affichage</string>
<string name="settings_display_support">Apparence de l\'Application</string> <string name="settings_display_support">Apparence de l\'application</string>
<string name="settings_dynamic_colors">Couleurs dynamiques</string> <string name="settings_dynamic_colors">Couleurs dynamiques</string>
<string name="settings_dynamic_colors_support">Utilisez les couleurs de votre fond d\'écran</string> <string name="settings_dynamic_colors_support">Utilisez les couleurs de votre fond d\'écran</string>
<string name="settings_enable_unit_group_description">Activer le groupe d\'unités</string> <string name="settings_enable_unit_group_description">Activer le groupe d\'unités</string>
<string name="settings_exponential_notation">Notation exponentielle</string> <string name="settings_exponential_notation">Notation scientifique</string>
<string name="settings_exponential_notation_support">Remplacer une partie du nombre par E</string> <string name="settings_exponential_notation_support">Remplacer une partie du nombre par E</string>
<string name="settings_format_time">Formatter l\'heure</string> <string name="settings_format_time">Formater l\'heure</string>
<string name="settings_format_time_support">Exemple : Afficher 130 minutes comme 2h 10m</string> <string name="settings_format_time_support">Exemple : Afficher 130 minutes comme 2h 10m</string>
<string name="settings_formatting">Formattage</string> <string name="settings_formatting">Formatage</string>
<string name="settings_formatting_preview">Aperçu (cliquez pour changer)</string> <string name="settings_formatting_preview">Aperçu (cliquez pour changer)</string>
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/Gj9ZCNPXIfKddDQgccvboVFz.jpg <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/Gj9ZCNPXIfKddDQgccvboVFz.jpg
@ -112,8 +134,9 @@ https://s3.eu-west-1.amazonaws.com/po-pub/i/prtM85P6x1fMuLg1I0zbkceo.png
Maybe this can be labeled better? Let me know. It should be something that can describe content of the Formatting screen. --> Maybe this can be labeled better? Let me know. It should be something that can describe content of the Formatting screen. -->
<string name="settings_formatting_support">Précision et format des nombres</string> <string name="settings_formatting_support">Précision et format des nombres</string>
<string name="settings_language">Langue</string> <string name="settings_language">Langue</string>
<string name="settings_language_support">Changer la langue de l\'app</string>
<string name="settings_light_mode">Clair</string> <string name="settings_light_mode">Clair</string>
<string name="settings_middle_zero">Zéro au milieu</string> <string name="settings_middle_zero">Zéro central</string>
<string name="settings_middle_zero_support">Intervertir les boutons zéro et décimal</string> <string name="settings_middle_zero_support">Intervertir les boutons zéro et décimal</string>
<string name="settings_note">Note</string> <string name="settings_note">Note</string>
<string name="settings_partial_history_view">Vue partielle de l\'historique</string> <string name="settings_partial_history_view">Vue partielle de l\'historique</string>
@ -124,8 +147,9 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="settings_precision_max">%1$s (Max)</string> <string name="settings_precision_max">%1$s (Max)</string>
<string name="settings_precision_support">Nombre de décimales</string> <string name="settings_precision_support">Nombre de décimales</string>
<string name="settings_privacy_policy">Politique de confidentialité</string> <string name="settings_privacy_policy">Politique de confidentialité</string>
<string name="settings_rate_this_app">Évaluer l\'application</string> <string name="settings_rate_this_app">Noter l\'application</string>
<string name="settings_reorder_unit_group_description">Réorganiser le groupe d\'unités</string> <string name="settings_reorder_unit_group_description">Réorganiser le groupe d\'unités</string>
<string name="settings_restore">Restaurer</string>
<string name="settings_selected_color">Couleur sélectionnée</string> <string name="settings_selected_color">Couleur sélectionnée</string>
<string name="settings_selected_style">Style sélectionné</string> <string name="settings_selected_style">Style sélectionné</string>
<string name="settings_separator">Séparateur</string> <string name="settings_separator">Séparateur</string>
@ -141,8 +165,13 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/r1VikAn70eXQP4da2hrntTGQ.jpg --> <!-- https://s3.eu-west-1.amazonaws.com/po-pub/i/r1VikAn70eXQP4da2hrntTGQ.jpg -->
<!-- Option name to use system default setting --> <!-- Option name to use system default setting -->
<string name="settings_system">Système</string> <string name="settings_system">Système</string>
<string name="settings_system_font">Police</string>
<string name="settings_system_font_support">Afficher avec la police système</string>
<string name="settings_ac_button">bouton AC</string>
<string name="settings_ac_button_support">Afficher le bouton de suppression</string>
<string name="settings_terms_and_conditions">Termes et conditions</string> <string name="settings_terms_and_conditions">Termes et conditions</string>
<string name="settings_third_party_licenses">Licences tierces</string> <string name="settings_third_party_licenses">Licences tierces</string>
<string name="settings_thousands_separator">Séparateur de milliers</string>
<string name="settings_title">Paramètres</string> <string name="settings_title">Paramètres</string>
<string name="settings_translate_app">Traduire cette app</string> <string name="settings_translate_app">Traduire cette app</string>
<string name="settings_translate_app_support">Rejoignez le projet POEditor pour aider</string> <string name="settings_translate_app_support">Rejoignez le projet POEditor pour aider</string>
@ -152,9 +181,17 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="settings_units_sorting_support">Changer l\'ordre des unités</string> <string name="settings_units_sorting_support">Changer l\'ordre des unités</string>
<string name="settings_version_name">Nom de la version</string> <string name="settings_version_name">Nom de la version</string>
<string name="settings_vibrations">Vibrations</string> <string name="settings_vibrations">Vibrations</string>
<string name="settings_vibrations_support">Retour haptique lors du click sur les boutons du clavier</string> <string name="settings_vibrations_support">Retour haptique lors du clic sur les boutons du clavier</string>
<string name="settings_view_source_code">Voir le code source</string> <string name="settings_view_source_code">Voir le code source</string>
<string name="time_zone_add_title">Ajouter un fuseau horaire</string> <string name="time_zone_add_title">Ajouter un fuseau horaire</string>
<string name="time_zone_no_results_button">Lire l\'article</string>
<!-- NumberHub beta text-->
<string name="settings_numberhub_newApp">Unitto est maintenant NumberHub !</string>
<string name="settings_numberhub_newApp_message">Unitto n\'est plus maintenu. Vous êtes l\'un des premiers utilisateurs à essayer NumberHub ! Veuillez faire passer le mot et partager l\'application avec vos amis. Merci pour votre soutien !</string>
<string name="settings_numberhub_newApp_announcement">NumberHub sert de remplacement direct pour Unitto. Il a les mêmes fonctionnalités et plus encore. NumberHub est encore en version bêta et des changements peuvent survenir. Veuillez signaler tout problème que vous rencontrez. Merci d\'être l\'un des premiers à l\'essayer !</string>
<string name="time_zone_title">Fuseaux horaires</string> <string name="time_zone_title">Fuseaux horaires</string>
<string name="tomorrow">Demain</string> <string name="tomorrow">Demain</string>
<string name="unit_acre">Acre</string> <string name="unit_acre">Acre</string>
@ -258,175 +295,175 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_cubic_millimeter_short">mm³</string> <string name="unit_cubic_millimeter_short">mm³</string>
<string name="unit_currency_ada">Cardano</string> <string name="unit_currency_ada">Cardano</string>
<string name="unit_currency_aed">Dirham des Émirats arabes unis</string> <string name="unit_currency_aed">Dirham des Émirats arabes unis</string>
<string name="unit_currency_afn">Afghan afghani</string> <string name="unit_currency_afn">Afghani</string>
<string name="unit_currency_all">Albanian lek</string> <string name="unit_currency_all">Lek</string>
<string name="unit_currency_amd">Armenian dram</string> <string name="unit_currency_amd">Dram</string>
<string name="unit_currency_ang">Netherlands Antillean Guilder</string> <string name="unit_currency_ang">Florin des Antilles néerlandaises</string>
<string name="unit_currency_aoa">Angolan kwanza</string> <string name="unit_currency_aoa">Kwanza</string>
<string name="unit_currency_ars">Argentine peso</string> <string name="unit_currency_ars">Peso argentin</string>
<string name="unit_currency_aud">Australian dollar</string> <string name="unit_currency_aud">Dollar australien</string>
<string name="unit_currency_awg">Aruban florin</string> <string name="unit_currency_awg">Florin arubais</string>
<string name="unit_currency_azn">Azerbaijani manat</string> <string name="unit_currency_azn">Manat azerbaïdjanais</string>
<string name="unit_currency_bam">Bosnia-Herzegovina Convertible Mark</string> <string name="unit_currency_bam">Mark convertible de Bosnie-Herzégovine</string>
<string name="unit_currency_bbd">Bajan dollar</string> <string name="unit_currency_bbd">Dollar barbadien</string>
<string name="unit_currency_bdt">Bangladeshi taka</string> <string name="unit_currency_bdt">Taka</string>
<string name="unit_currency_bgn">Bulgarian lev</string> <string name="unit_currency_bgn">Lev bulgare</string>
<string name="unit_currency_bhd">Bahraini dinar</string> <string name="unit_currency_bhd">Dinar bahreïni</string>
<string name="unit_currency_bif">Burundian Franc</string> <string name="unit_currency_bif">Franc burundais</string>
<string name="unit_currency_bmd">Bermudan dollar</string> <string name="unit_currency_bmd">Dollar bermudien</string>
<string name="unit_currency_bnd">Brunei dollar</string> <string name="unit_currency_bnd">Dollar de Brunei</string>
<string name="unit_currency_bob">Bolivian boliviano</string> <string name="unit_currency_bob">Boliviano</string>
<string name="unit_currency_brl">Brazilian real</string> <string name="unit_currency_brl">Réal brésilien</string>
<string name="unit_currency_bsd">Bahamian dollar</string> <string name="unit_currency_bsd">Dollar bahaméen</string>
<string name="unit_currency_btn">Bhutan currency</string> <string name="unit_currency_btn">Ngultrum</string>
<string name="unit_currency_bwp">Botswanan Pula</string> <string name="unit_currency_bwp">Pula</string>
<string name="unit_currency_byn">New Belarusian Ruble</string> <string name="unit_currency_byn">Nouveau rouble biélorusse</string>
<string name="unit_currency_byr">Belarusian Ruble</string> <string name="unit_currency_byr">Rouble biélorusse</string>
<string name="unit_currency_bzd">Belize dollar</string> <string name="unit_currency_bzd">Dollar bélizien</string>
<string name="unit_currency_cad">Canadian dollar</string> <string name="unit_currency_cad">Dollar canadien</string>
<string name="unit_currency_cdf">Congolese franc</string> <string name="unit_currency_cdf">Franc congolais</string>
<string name="unit_currency_chf">Swiss franc</string> <string name="unit_currency_chf">Franc suisse</string>
<string name="unit_currency_clf">Chilean Unit of Account (UF)</string> <string name="unit_currency_clf">Chilean Unit of Account (UF)</string>
<string name="unit_currency_clp">Chilean peso</string> <string name="unit_currency_clp">Peso chilien</string>
<string name="unit_currency_cny">Chinese Yuan</string> <string name="unit_currency_cny">Yuan</string>
<string name="unit_currency_cop">Colombian peso</string> <string name="unit_currency_cop">Peso colombien</string>
<string name="unit_currency_crc">Costa Rican Colón</string> <string name="unit_currency_crc">Colón costaricien</string>
<string name="unit_currency_cuc">Cuban convertible peso</string> <string name="unit_currency_cuc">Peso cubain convertible</string>
<string name="unit_currency_cup">Cuban Peso</string> <string name="unit_currency_cup">Peso cubain</string>
<string name="unit_currency_cve">Cape Verdean escudo</string> <string name="unit_currency_cve">Escudo cap-verdien</string>
<string name="unit_currency_czk">Czech koruna</string> <string name="unit_currency_czk">Couronne tchèque</string>
<string name="unit_currency_dai">Dai</string> <string name="unit_currency_dai">Dai</string>
<string name="unit_currency_djf">Djiboutian franc</string> <string name="unit_currency_djf">Franc Djibouti</string>
<string name="unit_currency_dkk">Danish krone</string> <string name="unit_currency_dkk">Couronne danoise</string>
<string name="unit_currency_dop">Dominican peso</string> <string name="unit_currency_dop">Peso dominicain</string>
<string name="unit_currency_dzd">Algerian dinar</string> <string name="unit_currency_dzd">Dinar algérien</string>
<string name="unit_currency_egp">Egyptian pound</string> <string name="unit_currency_egp">Livre égyptienne</string>
<string name="unit_currency_ern">Eritrean nakfa</string> <string name="unit_currency_ern">Nakfa érythréen</string>
<string name="unit_currency_etb">Ethiopian birr</string> <string name="unit_currency_etb">Birr éthiopien</string>
<string name="unit_currency_eur">Euro</string> <string name="unit_currency_eur">Euro</string>
<string name="unit_currency_fjd">Fijian dollar</string> <string name="unit_currency_fjd">Dollar fidjien</string>
<string name="unit_currency_fkp">Falkland Islands pound</string> <string name="unit_currency_fkp">Livre des îles Malouines</string>
<string name="unit_currency_gbp">Pound sterling</string> <string name="unit_currency_gbp">Livre sterling</string>
<string name="unit_currency_gel">Georgian lari</string> <string name="unit_currency_gel">Lari géorgien</string>
<string name="unit_currency_ghs">Ghanaian cedi</string> <string name="unit_currency_ghs">Cedi ghanéen</string>
<string name="unit_currency_gip">Gibraltar pound</string> <string name="unit_currency_gip">Livre de Gibraltar</string>
<string name="unit_currency_gmd">Gambian dalasi</string> <string name="unit_currency_gmd">Dalasi gambien</string>
<string name="unit_currency_gnf">Guinean franc</string> <string name="unit_currency_gnf">Franc guinéen</string>
<string name="unit_currency_gtq">Guatemalan quetzal</string> <string name="unit_currency_gtq">Quetzal guatémaltèque</string>
<string name="unit_currency_gyd">Guyanaese Dollar</string> <string name="unit_currency_gyd">Dollar guyanien</string>
<string name="unit_currency_hkd">Hong Kong dollar</string> <string name="unit_currency_hkd">Dollar de Hong Kong</string>
<string name="unit_currency_hnl">Honduran lempira</string> <string name="unit_currency_hnl">Lempira hondurien</string>
<string name="unit_currency_hrk">Croatian kuna</string> <string name="unit_currency_hrk">Kuna croate</string>
<string name="unit_currency_htg">Haitian gourde</string> <string name="unit_currency_htg">Gourde haïtienne</string>
<string name="unit_currency_huf">Hungarian forint</string> <string name="unit_currency_huf">Forint hongrois</string>
<string name="unit_currency_idr">Indonesian rupiah</string> <string name="unit_currency_idr">Roupie indonésienne</string>
<string name="unit_currency_ils">Israeli New Shekel</string> <string name="unit_currency_ils">Shekel israélien</string>
<string name="unit_currency_inr">Indian rupee</string> <string name="unit_currency_inr">Roupie indienne</string>
<string name="unit_currency_iqd">Iraqi dinar</string> <string name="unit_currency_iqd">Dinar irakien</string>
<string name="unit_currency_irr">Iranian rial</string> <string name="unit_currency_irr">Rial iranien</string>
<string name="unit_currency_isk">Icelandic króna</string> <string name="unit_currency_isk">Couronne islandaise</string>
<string name="unit_currency_jep">Jersey Pound</string> <string name="unit_currency_jep">Livre de Jersey</string>
<string name="unit_currency_jmd">Jamaican dollar</string> <string name="unit_currency_jmd">Dollar jamaïcain</string>
<string name="unit_currency_jod">Jordanian dinar</string> <string name="unit_currency_jod">Dinar jordanien</string>
<string name="unit_currency_jpy">Japanese yen</string> <string name="unit_currency_jpy">Yen japonais</string>
<string name="unit_currency_kes">Kenyan shilling</string> <string name="unit_currency_kes">Shilling kényan</string>
<string name="unit_currency_kgs">Kyrgystani Som</string> <string name="unit_currency_kgs">Som kirghize</string>
<string name="unit_currency_khr">Cambodian riel</string> <string name="unit_currency_khr">Riel cambodgien</string>
<string name="unit_currency_kmf">Comorian franc</string> <string name="unit_currency_kmf">Franc comorien</string>
<string name="unit_currency_kpw">North Korean won</string> <string name="unit_currency_kpw">Won nord-coréen</string>
<string name="unit_currency_krw">South Korean won</string> <string name="unit_currency_krw">Won sud-coréen</string>
<string name="unit_currency_kwd">Kuwaiti dinar</string> <string name="unit_currency_kwd">Dinar koweïtien</string>
<string name="unit_currency_kyd">Cayman Islands dollar</string> <string name="unit_currency_kyd">Dollar des îles Caïmans</string>
<string name="unit_currency_kzt">Kazakhstani tenge</string> <string name="unit_currency_kzt">Tenge kazakh</string>
<string name="unit_currency_lak">Laotian Kip</string> <string name="unit_currency_lak">Kip laotien</string>
<string name="unit_currency_lbp">Lebanese pound</string> <string name="unit_currency_lbp">Livre libanaise</string>
<string name="unit_currency_lkr">Sri Lankan rupee</string> <string name="unit_currency_lkr">Roupie srilankaise</string>
<string name="unit_currency_lrd">Liberian dollar</string> <string name="unit_currency_lrd">Dollar libérien</string>
<string name="unit_currency_lsl">Lesotho loti</string> <string name="unit_currency_lsl">Loti lesothan</string>
<string name="unit_currency_ltl">Lithuanian litas</string> <string name="unit_currency_ltl">Litas lituanien</string>
<string name="unit_currency_lvl">Latvian lats</string> <string name="unit_currency_lvl">Lats letton</string>
<string name="unit_currency_lyd">Libyan dinar</string> <string name="unit_currency_lyd">Dinar libyen</string>
<string name="unit_currency_mad">Moroccan dirham</string> <string name="unit_currency_mad">Dirham marocain</string>
<string name="unit_currency_mdl">Moldovan leu</string> <string name="unit_currency_mdl">Leu moldave</string>
<string name="unit_currency_mga">Malagasy ariary</string> <string name="unit_currency_mga">Ariary malgache</string>
<string name="unit_currency_mkd">Macedonian denar</string> <string name="unit_currency_mkd">Denar macédonien</string>
<string name="unit_currency_mmk">Myanmar Kyat</string> <string name="unit_currency_mmk">Kyat birman</string>
<string name="unit_currency_mnt">Mongolian tugrik</string> <string name="unit_currency_mnt">Tugrik mongol</string>
<string name="unit_currency_mop">Macanese pataca</string> <string name="unit_currency_mop">Pataca macanaise</string>
<string name="unit_currency_mro">Mauritanian ouguiya</string> <string name="unit_currency_mro">Ouguiya mauritanien</string>
<string name="unit_currency_mur">Mauritian rupee</string> <string name="unit_currency_mur">Roupie mauricienne</string>
<string name="unit_currency_mvr">Maldivian rufiyaa</string> <string name="unit_currency_mvr">Rufiyaa maldivienne</string>
<string name="unit_currency_mwk">Malawian kwacha</string> <string name="unit_currency_mwk">Kwacha malawien</string>
<string name="unit_currency_mxn">Mexican peso</string> <string name="unit_currency_mxn">Peso mexicain</string>
<string name="unit_currency_myr">Malaysian ringgit</string> <string name="unit_currency_myr">Ringgit malaisien</string>
<string name="unit_currency_mzn">Mozambican Metical</string> <string name="unit_currency_mzn">Metical mozambicain</string>
<string name="unit_currency_nad">Namibian dollar</string> <string name="unit_currency_nad">Dollar namibien</string>
<string name="unit_currency_ngn">Nigerian naira</string> <string name="unit_currency_ngn">Naira nirian</string>
<string name="unit_currency_nio">Nicaraguan córdoba</string> <string name="unit_currency_nio">Córdoba nicaraguayen</string>
<string name="unit_currency_nok">Norwegian krone</string> <string name="unit_currency_nok">Couronne norvégienne</string>
<string name="unit_currency_npr">Nepalese rupee</string> <string name="unit_currency_npr">Roupie népalaise</string>
<string name="unit_currency_nzd">New Zealand dollar</string> <string name="unit_currency_nzd">Dollar néo-zélandais</string>
<string name="unit_currency_omr">Omani rial</string> <string name="unit_currency_omr">Rial omanais</string>
<string name="unit_currency_pab">Panamanian balboa</string> <string name="unit_currency_pab">Balboa panaméen</string>
<string name="unit_currency_pen">Sol</string> <string name="unit_currency_pen">Sol péruvien</string>
<string name="unit_currency_pgk">Papua New Guinean kina</string> <string name="unit_currency_pgk">Kina papouasien</string>
<string name="unit_currency_php">Philippine peso</string> <string name="unit_currency_php">Peso philippin</string>
<string name="unit_currency_pkr">Pakistani rupee</string> <string name="unit_currency_pkr">Roupie pakistanaise</string>
<string name="unit_currency_pln">Poland złoty</string> <string name="unit_currency_pln">Złoty polonais</string>
<string name="unit_currency_pyg">Paraguayan guarani</string> <string name="unit_currency_pyg">Guaraní paraguayen</string>
<string name="unit_currency_qar">Qatari Rial</string> <string name="unit_currency_qar">Riyal qatari</string>
<string name="unit_currency_ron">Romanian leu</string> <string name="unit_currency_ron">Leu roumain</string>
<string name="unit_currency_rsd">Serbian dinar</string> <string name="unit_currency_rsd">Dinar serbe</string>
<string name="unit_currency_rub">Russian ruble</string> <string name="unit_currency_rub">Rouble russe</string>
<string name="unit_currency_rwf">Rwandan Franc</string> <string name="unit_currency_rwf">Franc rwandais</string>
<string name="unit_currency_sar">Saudi riyal</string> <string name="unit_currency_sar">Riyal saoudien</string>
<string name="unit_currency_sbd">Solomon Islands dollar</string> <string name="unit_currency_sbd">Dollar des îles Salomon</string>
<string name="unit_currency_scr">Seychellois rupee</string> <string name="unit_currency_scr">Roupie seychelloise</string>
<string name="unit_currency_sdg">Sudanese pound</string> <string name="unit_currency_sdg">Livre soudanaise</string>
<string name="unit_currency_sek">Swedish krona</string> <string name="unit_currency_sek">Couronne suédoise</string>
<string name="unit_currency_sgd">Singapore dollar</string> <string name="unit_currency_sgd">Dollar de Singapour</string>
<string name="unit_currency_shib">Shiba Inu</string> <string name="unit_currency_shib">Shiba Inu</string>
<string name="unit_currency_shp">Saint Helena pound</string> <string name="unit_currency_shp">Livre de Sainte-Hélène</string>
<string name="unit_currency_sll">Sierra Leonean leone</string> <string name="unit_currency_sll">Leone sierra-léonais</string>
<string name="unit_currency_sos">Somali shilling</string> <string name="unit_currency_sos">Shilling somalien</string>
<string name="unit_currency_srd">Surinamese dollar</string> <string name="unit_currency_srd">Dollar surinamais</string>
<string name="unit_currency_std">São Tomé and Príncipe Dobra (pre-2018)</string> <string name="unit_currency_std">Dobra santoméen (avant 2018)</string>
<string name="unit_currency_svc">Salvadoran Colón</string> <string name="unit_currency_svc">Colón salvadorien</string>
<string name="unit_currency_syp">Syrian pound</string> <string name="unit_currency_syp">Livre syrienne</string>
<string name="unit_currency_szl">Swazi lilangeni</string> <string name="unit_currency_szl">Lilangeni swazi</string>
<string name="unit_currency_thb">Thai baht</string> <string name="unit_currency_thb">Baht thaïlandais</string>
<string name="unit_currency_theta">Theta</string> <string name="unit_currency_theta">Theta</string>
<string name="unit_currency_tjs">Tajikistani somoni</string> <string name="unit_currency_tjs">Somoni tadjik</string>
<string name="unit_currency_tmt">Turkmenistani manat</string> <string name="unit_currency_tmt">Manat turkmène</string>
<string name="unit_currency_tnd">Tunisian dinar</string> <string name="unit_currency_tnd">Dinar tunisien</string>
<string name="unit_currency_top">Tongan Paʻanga</string> <string name="unit_currency_top">Paʻanga tongan</string>
<string name="unit_currency_try">Turkish lira</string> <string name="unit_currency_try">Livre turque</string>
<string name="unit_currency_ttd">Trinidad &amp; Tobago Dollar</string> <string name="unit_currency_ttd">Dollar de Trinité-et-Tobago</string>
<string name="unit_currency_twd">New Taiwan dollar</string> <string name="unit_currency_twd">Nouveau dollar taïwanais</string>
<string name="unit_currency_tzs">Tanzanian shilling</string> <string name="unit_currency_tzs">Shilling tanzanien</string>
<string name="unit_currency_uah">Ukrainian hryvnia</string> <string name="unit_currency_uah">Hryvnia ukrainienne</string>
<string name="unit_currency_ugx">Ugandan shilling</string> <string name="unit_currency_ugx">Shilling ougandais</string>
<string name="unit_currency_uni">Universe</string> <string name="unit_currency_uni">Universe</string>
<string name="unit_currency_usd">United States dollar</string> <string name="unit_currency_usd">Dollar américain</string>
<string name="unit_currency_usdc">USD Coin</string> <string name="unit_currency_usdc">USD Coin</string>
<string name="unit_currency_uyu">Uruguayan peso</string> <string name="unit_currency_uyu">Peso uruguayen</string>
<string name="unit_currency_uzs">Uzbekistani som</string> <string name="unit_currency_uzs">Som ouzbek</string>
<string name="unit_currency_vef">Sovereign Bolivar</string> <string name="unit_currency_vef">Bolivar souverain</string>
<string name="unit_currency_vnd">Vietnamese dong</string> <string name="unit_currency_vnd">Dong vietnamien</string>
<string name="unit_currency_vuv">Vanuatu vatu</string> <string name="unit_currency_vuv">Vatu vanuatu</string>
<string name="unit_currency_wbtc">Wrapped Bitcoin</string> <string name="unit_currency_wbtc">Wrapped Bitcoin</string>
<string name="unit_currency_wst">Samoan tala</string> <string name="unit_currency_wst">Tālā</string>
<string name="unit_currency_xaf">Central African CFA franc</string> <string name="unit_currency_xaf">Franc CFA d\'Afrique centrale</string>
<string name="unit_currency_xag">Silver Ounce</string> <string name="unit_currency_xag">Once d\'argent</string>
<string name="unit_currency_xcd">East Caribbean dollar</string> <string name="unit_currency_xcd">Dollar des Caraïbes orientales</string>
<string name="unit_currency_xdr">Special Drawing Rights</string> <string name="unit_currency_xdr">Droits de tirage spéciaux</string>
<string name="unit_currency_xof">West African CFA franc</string> <string name="unit_currency_xof">Franc CFA d\'Afrique de l\'Ouest</string>
<string name="unit_currency_xpf">CFP franc</string> <string name="unit_currency_xpf">Franc CFP</string>
<string name="unit_currency_yer">Yemeni rial</string> <string name="unit_currency_yer">Rial yéménite</string>
<string name="unit_currency_zar">South African rand</string> <string name="unit_currency_zar">Rand sud-africain</string>
<string name="unit_currency_zmk">Zambian kwacha</string> <string name="unit_currency_zmk">Kwacha zambien</string>
<string name="unit_currency_zmw">Zambian Kwacha</string> <string name="unit_currency_zmw">Kwacha zambien</string>
<string name="unit_currency_zwl">Zimbabwean Dollar</string> <string name="unit_currency_zwl">Dollar zimbabwéen</string>
<string name="unit_day">Jour</string> <string name="unit_day">Jour</string>
<string name="unit_day_short">j</string> <string name="unit_day_short">j</string>
<string name="unit_decimal">Décimal</string> <string name="unit_decimal">Décimal</string>
@ -459,7 +496,7 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_earth_surface_gravity">Gravité de surface de la Terre</string> <string name="unit_earth_surface_gravity">Gravité de surface de la Terre</string>
<string name="unit_earth_surface_gravity_short">G Terre</string> <string name="unit_earth_surface_gravity_short">G Terre</string>
<string name="unit_earths_orbital_speed">Vitesse orbitale de la Terre</string> <string name="unit_earths_orbital_speed">Vitesse orbitale de la Terre</string>
<string name="unit_electron_cross_section">Electron cross section</string> <string name="unit_electron_cross_section">Section efficace de l\'électron</string>
<string name="unit_electron_cross_section_short">ecs</string> <string name="unit_electron_cross_section_short">ecs</string>
<string name="unit_electron_mass_rest">Masse électronique</string> <string name="unit_electron_mass_rest">Masse électronique</string>
<string name="unit_electron_mass_rest_short">me</string> <string name="unit_electron_mass_rest_short">me</string>
@ -548,7 +585,7 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_group_data_transfer">Transfert de données</string> <string name="unit_group_data_transfer">Transfert de données</string>
<string name="unit_group_electrostatic_capacitance">Capacité</string> <string name="unit_group_electrostatic_capacitance">Capacité</string>
<string name="unit_group_energy">Énergie</string> <string name="unit_group_energy">Énergie</string>
<string name="unit_group_flow_rate">Flux</string> <string name="unit_group_flow_rate">Mesure de débit</string>
<string name="unit_group_flux">Flux</string> <string name="unit_group_flux">Flux</string>
<string name="unit_group_force">Force</string> <string name="unit_group_force">Force</string>
<string name="unit_group_length">Longueur</string> <string name="unit_group_length">Longueur</string>
@ -560,7 +597,7 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_group_pressure">Pression</string> <string name="unit_group_pressure">Pression</string>
<string name="unit_group_speed">Vélocité</string> <string name="unit_group_speed">Vélocité</string>
<string name="unit_group_temperature">Température</string> <string name="unit_group_temperature">Température</string>
<string name="unit_group_time">Time</string> <string name="unit_group_time">Temps</string>
<string name="unit_group_torque">Couple</string> <string name="unit_group_torque">Couple</string>
<string name="unit_group_volume">Volume</string> <string name="unit_group_volume">Volume</string>
<string name="unit_hectare">Hectare</string> <string name="unit_hectare">Hectare</string>
@ -577,18 +614,18 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_hour_short">h</string> <string name="unit_hour_short">h</string>
<string name="unit_imperial_cup">Tasse impériale</string> <string name="unit_imperial_cup">Tasse impériale</string>
<string name="unit_imperial_cup_short">cup</string> <string name="unit_imperial_cup_short">cup</string>
<string name="unit_imperial_fluid_ounce">Imperial fluid ounce</string> <string name="unit_imperial_fluid_ounce">Once liquide impériale</string>
<string name="unit_imperial_fluid_ounce_short">fl oz</string> <string name="unit_imperial_fluid_ounce_short">fl oz</string>
<string name="unit_imperial_gallon">Gallon imperial</string> <string name="unit_imperial_gallon">Gallon impérial</string>
<string name="unit_imperial_gallon_short">gal</string> <string name="unit_imperial_gallon_short">gal</string>
<string name="unit_imperial_pint">Pinte impériale</string> <string name="unit_imperial_pint">Pinte impériale</string>
<string name="unit_imperial_pint_short">pt</string> <string name="unit_imperial_pint_short">pt</string>
<string name="unit_imperial_quart">Quart impérial</string> <string name="unit_imperial_quart">Quart impérial</string>
<string name="unit_imperial_quart_short">qt</string> <string name="unit_imperial_quart_short">qt</string>
<string name="unit_imperial_tablespoon">Imperial tablespoon</string> <string name="unit_imperial_tablespoon">Cuillère à soupe impériale</string>
<string name="unit_imperial_tablespoon_short">tablespoon</string> <string name="unit_imperial_tablespoon_short">cuillère à soupe</string>
<string name="unit_imperial_teaspoon">Imperial teaspoon</string> <string name="unit_imperial_teaspoon">Cuillère à café impériale</string>
<string name="unit_imperial_teaspoon_short">teaspoon</string> <string name="unit_imperial_teaspoon_short">cuillère à café</string>
<string name="unit_imperial_ton">Tonne impériale</string> <string name="unit_imperial_ton">Tonne impériale</string>
<string name="unit_imperial_ton_short">t</string> <string name="unit_imperial_ton_short">t</string>
<string name="unit_inch">Pouce</string> <string name="unit_inch">Pouce</string>
@ -790,7 +827,7 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_milliliter_per_second_short">mL/s</string> <string name="unit_milliliter_per_second_short">mL/s</string>
<string name="unit_milliliter_short">mL</string> <string name="unit_milliliter_short">mL</string>
<string name="unit_millimeter">Millimètre</string> <string name="unit_millimeter">Millimètre</string>
<string name="unit_millimeter_of_mercury">Millimeter of mercury</string> <string name="unit_millimeter_of_mercury">Millimètre de mercure</string>
<string name="unit_millimeter_of_mercury_short">mm Hg</string> <string name="unit_millimeter_of_mercury_short">mm Hg</string>
<string name="unit_millimeter_per_hour">Millimètre/heure</string> <string name="unit_millimeter_per_hour">Millimètre/heure</string>
<string name="unit_millimeter_per_hour_short">mm/h</string> <string name="unit_millimeter_per_hour_short">mm/h</string>
@ -1023,7 +1060,7 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_uranus_mass_short">M Uranus</string> <string name="unit_uranus_mass_short">M Uranus</string>
<string name="unit_uranus_surface_gravity">Gravité de surface d\'Uranus</string> <string name="unit_uranus_surface_gravity">Gravité de surface d\'Uranus</string>
<string name="unit_uranus_surface_gravity_short">G Uranus</string> <string name="unit_uranus_surface_gravity_short">G Uranus</string>
<string name="unit_us_fluid_ounce">US fluid ounce</string> <string name="unit_us_fluid_ounce">Once liquide américaine</string>
<string name="unit_us_fluid_ounce_short">fl oz</string> <string name="unit_us_fluid_ounce_short">fl oz</string>
<string name="unit_us_legal_cup">Tasse américaine</string> <string name="unit_us_legal_cup">Tasse américaine</string>
<string name="unit_us_legal_cup_short">cup</string> <string name="unit_us_legal_cup_short">cup</string>
@ -1034,9 +1071,9 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_us_liquid_quart">Quarts américain</string> <string name="unit_us_liquid_quart">Quarts américain</string>
<string name="unit_us_liquid_quart_short">qt</string> <string name="unit_us_liquid_quart_short">qt</string>
<string name="unit_us_tablespoon">Cuillère à soupe américaine</string> <string name="unit_us_tablespoon">Cuillère à soupe américaine</string>
<string name="unit_us_tablespoon_short">tablespoon</string> <string name="unit_us_tablespoon_short">cuillère à soupe</string>
<string name="unit_us_teaspoon">Cuillère à café américaine</string> <string name="unit_us_teaspoon">Cuillère à café américaine</string>
<string name="unit_us_teaspoon_short">teaspoon</string> <string name="unit_us_teaspoon_short">cuillère à café</string>
<string name="unit_velocity_of_light_in_vacuum">Vitesse de la lumière dans le vide</string> <string name="unit_velocity_of_light_in_vacuum">Vitesse de la lumière dans le vide</string>
<string name="unit_venus_equatorial_radius">Radius équatorial de Vénus</string> <string name="unit_venus_equatorial_radius">Radius équatorial de Vénus</string>
<string name="unit_venus_equatorial_radius_short">R Vénus</string> <string name="unit_venus_equatorial_radius_short">R Vénus</string>
@ -1062,4 +1099,4 @@ Maybe this can be labeled better? Let me know. It should be something that can d
<string name="unit_yard_short">yd</string> <string name="unit_yard_short">yd</string>
<string name="unit_year_short">y</string> <string name="unit_year_short">y</string>
<string name="yesterday">Hier</string> <string name="yesterday">Hier</string>
</resources> </resources>

View File

@ -25,7 +25,6 @@ import androidx.compose.foundation.layout.FlowRowScope
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
/** /**
@ -51,8 +50,8 @@ fun KeypadFlow(
@IntRange(0, 100) verticalPadding: 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 height: Float = (1f - verticalPadding / 100f) / rows
val width: Float = remember { (1f - horizontalPadding / 100f) / columns } val width: Float = (1f - horizontalPadding / 100f) / columns
FlowRow( FlowRow(
modifier = modifier, modifier = modifier,

View File

@ -102,17 +102,232 @@ class UnitsRepositoryImpl @Inject constructor(
suspend fun getPairId(id: String): String = withContext(Dispatchers.IO) { suspend fun getPairId(id: String): String = withContext(Dispatchers.IO) {
val basedUnitPair = getUnitStats(id).pairedUnitId val basedUnitPair = getUnitStats(id).pairedUnitId
if (basedUnitPair != null) return@withContext basedUnitPair if (basedUnitPair != null) {
return@withContext basedUnitPair
}
val inMemoryUnit = inMemory.first { it.id == id } val inMemoryUnit = inMemory.first { it.id == id }
val collection = inMemory.filter { it.group == inMemoryUnit.group } val collection = inMemory.filter { it.group == inMemoryUnit.group }
val pair = collection return@withContext when (inMemoryUnit.id) {
.map { getById(it.id) to getUnitStats(it.id) } // === === === Length === === ===
.sortedByDescending { it.second.frequency } UnitID.nanometer -> UnitID.micrometer
.firstOrNull { it.second.isFavorite }?.first ?: collection.first() UnitID.micrometer -> UnitID.millimeter
UnitID.millimeter -> UnitID.centimeter
return@withContext pair.id UnitID.centimeter -> UnitID.inch
UnitID.inch -> UnitID.centimeter
UnitID.decimeter -> UnitID.centimeter
UnitID.foot -> UnitID.meter
UnitID.yard -> UnitID.meter
UnitID.meter -> UnitID.foot
UnitID.kilometer -> UnitID.mile
UnitID.mile -> UnitID.kilometer
UnitID.nautical_mile -> UnitID.kilometer
UnitID.mercury_equatorial_radius -> UnitID.kilometer
UnitID.mars_equatorial_radius -> UnitID.kilometer
UnitID.venus_equatorial_radius -> UnitID.kilometer
UnitID.earth_equatorial_radius -> UnitID.kilometer
UnitID.neptune_equatorial_radius -> UnitID.kilometer
UnitID.uranus_equatorial_radius -> UnitID.kilometer
UnitID.saturn_equatorial_radius -> UnitID.kilometer
UnitID.jupiter_equatorial_radius -> UnitID.kilometer
UnitID.sun_equatorial_radius -> UnitID.kilometer
UnitID.light_year -> UnitID.kilometer
UnitID.parsec -> UnitID.light_year
UnitID.kiloparsec -> UnitID.parsec
UnitID.megaparsec -> UnitID.kiloparsec
// === === === Mass === === ===
UnitID.electron_mass_rest -> UnitID.atomic_mass_unit
UnitID.atomic_mass_unit -> UnitID.electron_mass_rest
UnitID.microgram -> UnitID.milligram
UnitID.milligram -> UnitID.gram
UnitID.grain -> UnitID.gram
UnitID.carat -> UnitID.gram
UnitID.gram -> UnitID.carat
UnitID.ounce -> UnitID.gram
UnitID.pound -> UnitID.kilogram
UnitID.kilogram -> UnitID.pound
UnitID.metric_ton -> UnitID.kilogram
UnitID.imperial_ton -> UnitID.pound
UnitID.mercury_mass -> UnitID.kilogram
UnitID.mars_mass -> UnitID.kilogram
UnitID.venus_mass -> UnitID.kilogram
UnitID.earth_mass -> UnitID.kilogram
UnitID.uranus_mass -> UnitID.kilogram
UnitID.neptune_mass -> UnitID.kilogram
UnitID.saturn_mass -> UnitID.kilogram
UnitID.jupiter_mass -> UnitID.kilogram
UnitID.sun_mass -> UnitID.kilogram
// === === === Speed === === ===
UnitID.millimeter_per_hour -> UnitID.millimeter_per_second
UnitID.millimeter_per_second -> UnitID.millimeter_per_hour
UnitID.millimeter_per_minute -> UnitID.millimeter_per_second
UnitID.centimeter_per_hour -> UnitID.centimeter_per_second
UnitID.centimeter_per_second -> UnitID.centimeter_per_hour
UnitID.centimeter_per_minute -> UnitID.centimeter_per_second
UnitID.meter_per_hour -> UnitID.meter_per_second
UnitID.meter_per_second -> UnitID.meter_per_hour
UnitID.meter_per_minute -> UnitID.meter_per_second
UnitID.kilometer_per_hour -> UnitID.mile_per_hour
UnitID.kilometer_per_second -> UnitID.mile_per_second
UnitID.kilometer_per_minute -> UnitID.kilometer_per_second
UnitID.mile_per_hour -> UnitID.kilometer_per_hour
UnitID.mile_per_second -> UnitID.kilometer_per_second
UnitID.mile_per_minute -> UnitID.mile_per_second
UnitID.foot_per_hour -> UnitID.foot_per_second
UnitID.foot_per_second -> UnitID.foot_per_hour
UnitID.foot_per_minute -> UnitID.foot_per_second
UnitID.yard_per_hour -> UnitID.yard_per_second
UnitID.yard_per_second -> UnitID.yard_per_hour
UnitID.yard_per_minute -> UnitID.yard_per_second
UnitID.knot -> UnitID.kilometer_per_hour
UnitID.mach -> UnitID.kilometer_per_hour
UnitID.velocity_of_light_in_vacuum -> UnitID.kilometer_per_hour
UnitID.earths_orbital_speed -> UnitID.kilometer_per_hour
UnitID.cosmic_velocity_first -> UnitID.kilometer_per_hour
UnitID.cosmic_velocity_second -> UnitID.kilometer_per_hour
UnitID.cosmic_velocity_third -> UnitID.kilometer_per_hour
// === === === Temperature === === ===
UnitID.celsius -> UnitID.fahrenheit
UnitID.fahrenheit -> UnitID.celsius
UnitID.kelvin -> UnitID.celsius
// === === === Area === === ===
UnitID.square_micrometer -> UnitID.square_millimeter
UnitID.square_millimeter -> UnitID.square_centimeter
UnitID.square_centimeter -> UnitID.square_meter
UnitID.square_decimeter -> UnitID.square_meter
UnitID.square_meter -> UnitID.square_kilometer
UnitID.square_kilometer -> UnitID.square_meter
UnitID.square_inch -> UnitID.square_foot
UnitID.square_foot -> UnitID.square_inch
UnitID.square_yard -> UnitID.square_meter
UnitID.square_mile -> UnitID.square_kilometer
UnitID.acre -> UnitID.square_meter
UnitID.hectare -> UnitID.square_meter
UnitID.cent -> UnitID.square_meter
// === === === Time === === ===
UnitID.attosecond -> UnitID.nanosecond
UnitID.nanosecond -> UnitID.microsecond
UnitID.microsecond -> UnitID.millisecond
UnitID.millisecond -> UnitID.second
UnitID.jiffy -> UnitID.millisecond
UnitID.second -> UnitID.millisecond
UnitID.minute -> UnitID.second
UnitID.hour -> UnitID.minute
UnitID.day -> UnitID.hour
UnitID.week -> UnitID.day
// === === === Data === === ===
// TODO: Add tibibyte, exibyte
UnitID.bit -> UnitID.byte
UnitID.byte -> UnitID.kilobyte
UnitID.kilobyte -> UnitID.megabyte
UnitID.megabyte -> UnitID.gigabyte
UnitID.gigabyte -> UnitID.terabyte
UnitID.terabyte -> UnitID.petabyte
UnitID.petabyte -> UnitID.exabyte
UnitID.kilobit -> UnitID.kilobyte
UnitID.megabit -> UnitID.megabyte
UnitID.gigabit -> UnitID.gigabyte
UnitID.terabit -> UnitID.terabyte
UnitID.petabit -> UnitID.petabyte
UnitID.exabit -> UnitID.exabyte
UnitID.kibibit -> UnitID.kilobyte
UnitID.mebibit -> UnitID.megabyte
UnitID.gibibit -> UnitID.gigabyte
UnitID.kibibyte -> UnitID.kilobyte
UnitID.mebibyte -> UnitID.megabyte
UnitID.gibibyte -> UnitID.gigabyte
// === === === Acceleration === === ===
UnitID.millimeter_per_square_second -> UnitID.centimeter_per_square_second
UnitID.centimeter_per_square_second -> UnitID.meter_per_square_second
UnitID.decimeter_per_square_second -> UnitID.meter_per_square_second
UnitID.meter_per_square_second -> UnitID.kilometer_per_square_second
UnitID.mercury_surface_gravity -> UnitID.meter_per_square_second
UnitID.mars_surface_gravity -> UnitID.meter_per_square_second
UnitID.venus_surface_gravity -> UnitID.meter_per_square_second
UnitID.uranus_surface_gravity -> UnitID.meter_per_square_second
UnitID.earth_surface_gravity -> UnitID.meter_per_square_second
UnitID.saturn_surface_gravity -> UnitID.meter_per_square_second
UnitID.neptune_surface_gravity -> UnitID.meter_per_square_second
UnitID.jupiter_surface_gravity -> UnitID.meter_per_square_second
UnitID.sun_surface_gravity -> UnitID.meter_per_square_second
// === === === Power === === ===
UnitID.attowatt -> UnitID.watt
UnitID.watt -> UnitID.kilowatt
UnitID.kilowatt -> UnitID.watt
UnitID.megawatt -> UnitID.kilowatt
// === === === Angle === === ===
UnitID.degree -> UnitID.radian
UnitID.radian -> UnitID.degree
// === === === Data Transfer === === ===
UnitID.bit_per_second -> UnitID.byte_per_second
UnitID.kilobit_per_second -> UnitID.kilobyte_per_second
UnitID.megabit_per_second -> UnitID.megabyte_per_second
UnitID.gigabit_per_second -> UnitID.gigabyte_per_second
UnitID.terabit_per_second -> UnitID.terabyte_per_second
UnitID.petabit_per_second -> UnitID.petabyte_per_second
UnitID.exabit_per_second -> UnitID.exabyte_per_second
UnitID.byte_per_second -> UnitID.kilobyte_per_second
UnitID.kilobyte_per_second -> UnitID.megabyte_per_second
UnitID.megabyte_per_second -> UnitID.gigabyte_per_second
UnitID.gigabyte_per_second -> UnitID.megabyte_per_second
UnitID.terabyte_per_second -> UnitID.gigabyte_per_second
UnitID.petabyte_per_second -> UnitID.terabyte_per_second
// === === === Fuel === === ===
UnitID.kilometer_per_liter -> UnitID.mile_us_per_liter
UnitID.mile_us_per_liter -> UnitID.kilometer_per_liter
else ->
(collection
.map { getById(it.id) to getUnitStats(it.id) }
.sortedByDescending { it.second.frequency }
.firstOrNull { it.second.isFavorite }?.first ?: collection.first()).id
}
} }
suspend fun incrementCounter(id: String) = withContext(Dispatchers.IO) { suspend fun incrementCounter(id: String) = withContext(Dispatchers.IO) {

View File

@ -27,19 +27,100 @@ import java.math.BigDecimal
internal val areaCollection: List<BasicUnit> by lazy { internal val areaCollection: List<BasicUnit> by lazy {
listOf( listOf(
NormalUnit(UnitID.cent, BigDecimal("6083246572000000000000000000000000"), UnitGroup.AREA, R.string.unit_cent, R.string.unit_cent_short), // https://www.gowebtool.com/unit-conversion/area/convert.php?from=electron_cross_section&to=acre
NormalUnit(UnitID.acre, BigDecimal("60832465720000000000000000000000"), UnitGroup.AREA, R.string.unit_acre, R.string.unit_acre_short), NormalUnit(
NormalUnit(UnitID.hectare, BigDecimal("150320296400000000000000000000000"), UnitGroup.AREA, R.string.unit_hectare, R.string.unit_hectare_short ), UnitID.acre,
NormalUnit(UnitID.square_foot, BigDecimal("1396521251000000000000000000"), UnitGroup.AREA, R.string.unit_square_foot, R.string.unit_square_foot_short), BigDecimal("60832465720659000000000000000000"),
NormalUnit(UnitID.square_mile, BigDecimal("38932778060000000000000000000000000"), UnitGroup.AREA, R.string.unit_square_mile, R.string.unit_square_mile_short), UnitGroup.AREA,
NormalUnit(UnitID.square_yard, BigDecimal("12568691260000000000000000000"), UnitGroup.AREA, R.string.unit_square_yard, R.string.unit_square_yard_short), R.string.unit_acre,
NormalUnit(UnitID.square_inch, BigDecimal("9698064247000000000000000"), UnitGroup.AREA, R.string.unit_square_inch, R.string.unit_square_inch_short), R.string.unit_acre_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), // https://www.gowebtool.com/unit-conversion/area/convert.php?from=electron_cross_section&to=cent
NormalUnit(UnitID.square_centimeter, BigDecimal("1503202964000000000000000"), UnitGroup.AREA, R.string.unit_square_centimeter, R.string.unit_square_centimeter_short), NormalUnit(
NormalUnit(UnitID.square_decimeter, BigDecimal("150320296400000000000000000"), UnitGroup.AREA, R.string.unit_square_decimeter, R.string.unit_square_decimeter_short), UnitID.cent,
NormalUnit(UnitID.square_meter, BigDecimal("15032029640000000000000000000"), UnitGroup.AREA, R.string.unit_square_meter, R.string.unit_square_meter_short), BigDecimal("608324656845820000000000000000"),
NormalUnit(UnitID.square_kilometer, BigDecimal("15032029640000000000000000000000000"), UnitGroup.AREA, R.string.unit_square_kilometer, R.string.unit_square_kilometer_short), UnitGroup.AREA,
R.string.unit_cent,
R.string.unit_cent_short,
),
NormalUnit(
UnitID.hectare,
BigDecimal("150320296474920000000000000000000"),
UnitGroup.AREA,
R.string.unit_hectare,
R.string.unit_hectare_short,
),
NormalUnit(
UnitID.square_foot,
BigDecimal("1396521251622100000000000000"),
UnitGroup.AREA,
R.string.unit_square_foot,
R.string.unit_square_foot_short,
),
// https://www.gowebtool.com/unit-conversion/area/convert.php?from=electron_cross_section&to=square_mile_survey_us_statute
NormalUnit(
UnitID.square_mile,
BigDecimal("38932778061222000000000000000000000"),
UnitGroup.AREA,
R.string.unit_square_mile,
R.string.unit_square_mile_short,
),
NormalUnit(
UnitID.square_yard,
BigDecimal("12568691264599000000000000000"),
UnitGroup.AREA,
R.string.unit_square_yard,
R.string.unit_square_yard_short,
),
NormalUnit(
UnitID.square_inch,
BigDecimal("9698064247375700000000000"),
UnitGroup.AREA,
R.string.unit_square_inch,
R.string.unit_square_inch_short,
),
NormalUnit(
UnitID.square_micrometer,
BigDecimal("15032029647492000"),
UnitGroup.AREA,
R.string.unit_square_micrometer,
R.string.unit_square_micrometer_short,
),
NormalUnit(
UnitID.square_millimeter,
BigDecimal("15032029647492000000000"),
UnitGroup.AREA,
R.string.unit_square_millimeter,
R.string.unit_square_millimeter_short,
),
NormalUnit(
UnitID.square_centimeter,
BigDecimal("1503202964749200000000000"),
UnitGroup.AREA,
R.string.unit_square_centimeter,
R.string.unit_square_centimeter_short,
),
NormalUnit(
UnitID.square_decimeter,
BigDecimal("150320296474920000000000000"),
UnitGroup.AREA,
R.string.unit_square_decimeter,
R.string.unit_square_decimeter_short,
),
NormalUnit(
UnitID.square_meter,
BigDecimal("15032029647492000000000000000"),
UnitGroup.AREA,
R.string.unit_square_meter,
R.string.unit_square_meter_short,
),
NormalUnit(
UnitID.square_kilometer,
BigDecimal("15032029647492000000000000000000000"),
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), NormalUnit(UnitID.electron_cross_section, BigDecimal("1"), UnitGroup.AREA, R.string.unit_electron_cross_section, R.string.unit_electron_cross_section_short),
) )
} }

View File

@ -119,12 +119,21 @@ class AllUnitsTest {
@Test @Test
fun testArea() = testWithUnits { fun testArea() = testWithUnits {
cent.checkWith(acre, "75.9", "7590") cent.checkWith(acre, "75.9", "0.759")
cent.checkWith(square_meter, "1", "40.46856")
acre.checkWith(square_kilometer, "75.9", "0.30716") acre.checkWith(square_kilometer, "75.9", "0.30716")
hectare.checkWith(square_foot, "75.9", "8169808.00585") acre.checkWith(square_yard, "1", "4840")
acre.checkWith(square_meter, "1", "4046.85642")
acre.checkWith(cent, "1", "100")
hectare.checkWith(acre, "1", "2.47105");
hectare.checkWith(square_foot, "1", "107639.10417")
hectare.checkWith(square_foot, "75.9", "8169808.00628")
square_foot.checkWith(square_decimeter, "75.9", "705.13407") square_foot.checkWith(square_decimeter, "75.9", "705.13407")
square_mile.checkWith(square_foot, "75.9", "2115970560.8762") square_mile.checkWith(square_foot, "1", "27878400")
// Probably floating point error
square_mile.checkWith(square_foot, "75.9", "2115970560.00002")
square_yard.checkWith(square_foot, "75.9", "683.1") square_yard.checkWith(square_foot, "75.9", "683.1")
square_yard.checkWith(square_foot, "1", "9")
square_inch.checkWith(square_foot, "75.9", "0.52708") square_inch.checkWith(square_foot, "75.9", "0.52708")
square_micrometer.checkWith(square_millimeter, "75.9", "0.00008") square_micrometer.checkWith(square_millimeter, "75.9", "0.00008")
square_millimeter.checkWith(square_centimeter, "75.9", "0.759") square_millimeter.checkWith(square_centimeter, "75.9", "0.759")
@ -133,6 +142,7 @@ class AllUnitsTest {
square_meter.checkWith(acre, "75.9", "0.01876") square_meter.checkWith(acre, "75.9", "0.01876")
square_kilometer.checkWith(hectare, "75.9", "7590") square_kilometer.checkWith(hectare, "75.9", "7590")
electron_cross_section.checkWith(square_micrometer, "75.9", "0.000000000000005") electron_cross_section.checkWith(square_micrometer, "75.9", "0.000000000000005")
square_decimeter.checkWith(acre, "123.456", "0.00031")
} }
@Test @Test

View File

@ -26,9 +26,19 @@ import kotlin.math.asin
import kotlin.math.atan import kotlin.math.atan
import kotlin.math.pow import kotlin.math.pow
// Dirty hack to avoid -0.000000000001
val PI_THRESHOLD = BigDecimal("0.000000000000001")
internal fun BigDecimal.sin(radianMode: Boolean): BigDecimal { internal fun BigDecimal.sin(radianMode: Boolean): BigDecimal {
val angle: Double = if (radianMode) this.toDouble() else Math.toRadians(this.toDouble()) val angle: Double = if (radianMode) this.toDouble() else Math.toRadians(this.toDouble())
return kotlin.math.sin(angle).toBigDecimal()
val result = kotlin.math.sin(angle).toBigDecimal()
if (result.abs() < PI_THRESHOLD) {
return BigDecimal.ZERO
}
return result
} }
internal fun BigDecimal.arsin(radianMode: Boolean): BigDecimal { internal fun BigDecimal.arsin(radianMode: Boolean): BigDecimal {
@ -38,7 +48,14 @@ internal fun BigDecimal.arsin(radianMode: Boolean): BigDecimal {
internal fun BigDecimal.cos(radianMode: Boolean): BigDecimal { internal fun BigDecimal.cos(radianMode: Boolean): BigDecimal {
val angle: Double = if (radianMode) this.toDouble() else Math.toRadians(this.toDouble()) val angle: Double = if (radianMode) this.toDouble() else Math.toRadians(this.toDouble())
return kotlin.math.cos(angle).toBigDecimal()
val result = kotlin.math.cos(angle).toBigDecimal()
if (result.abs() < PI_THRESHOLD) {
return BigDecimal.ZERO
}
return result
} }
internal fun BigDecimal.arcos(radianMode: Boolean): BigDecimal { internal fun BigDecimal.arcos(radianMode: Boolean): BigDecimal {

View File

@ -93,10 +93,14 @@ class Expression(
} }
moveIfMatched(Token.Operator.divide) -> { moveIfMatched(Token.Operator.divide) -> {
val divisor = parseFactor() // Adding those `setScale` calls have been added in
// 36a931c7d175b5cad52ff3abceb7784b0bb82aac to fix #18
// I'm not sure if this is the correct way to fix it, but it
// seems to be working
val divisor = parseFactor().setScale(MAX_PRECISION)
if (divisor.compareTo(BigDecimal.ZERO) == 0) throw ExpressionException.DivideByZero() if (divisor.compareTo(BigDecimal.ZERO) == 0) throw ExpressionException.DivideByZero()
expression = expression.divide(divisor, roundingMode) expression = expression.setScale(MAX_PRECISION).divide(divisor, roundingMode)
} }
} }
} }
@ -166,7 +170,8 @@ class Expression(
// sin // sin
if (moveIfMatched(Token.Func.sin)) { if (moveIfMatched(Token.Func.sin)) {
expr = parseFuncParentheses().sin(radianMode) val x = parseFuncParentheses()
expr = x.sin(radianMode)
} }
// cos // cos
@ -211,7 +216,13 @@ class Expression(
// Power // Power
if (moveIfMatched(Token.Operator.power)) { if (moveIfMatched(Token.Operator.power)) {
expr = expr.pow(parseFactor()) val factor = parseFactor()
if (factor.compareTo(BigDecimal.ZERO) == 0 && expr.compareTo(BigDecimal.ZERO) == 0) {
throw ExpressionException.BadExpression()
}
expr = expr.pow(factor)
} }
// Modulo // Modulo

View File

@ -57,4 +57,7 @@ class ExpressionComplexTest {
@Test @Test
fun expression12() = assertExpr("2×(3+4)×(52)÷6", "7") fun expression12() = assertExpr("2×(3+4)×(52)÷6", "7")
@Test
fun shouldDivideRootAndDivideInCorrectOrder() = assertExpr("(√9)÷6", "0.5")
} }

View File

@ -111,4 +111,55 @@ class ExpressionSimpleTest {
@Test @Test
fun expression29() = assertExpr("0!", "1") fun expression29() = assertExpr("0!", "1")
@Test
fun factorial() = assertExpr("5!", "120")
@Test
fun singleNumber() = assertExpr("42", "42")
@Test(expected = NumberFormatException::class)
fun divisionByZero() = assertExpr("1÷0", "")
@Test(expected = NumberFormatException::class)
fun invalidExpressionMissingOperand() = assertExpr("42+", "")
@Test
fun largeNumbers() = assertExpr("9999999999*9999999999", "99999999980000000001")
@Test
fun highPrecision() = assertExpr("1÷3", "0.3333333333")
@Test
fun deeplyNestedParentheses() = assertExpr("((((((42))))))", "42")
@Test
fun constantsAndFunctions() = assertExpr("π+e", "${Math.PI + Math.E}")
@Test(expected = NumberFormatException::class)
fun edgeMathematicalCases() = assertExpr("0^0", "")
@Test
fun zeroExponent() = assertExpr("5^0", "1")
@Test
fun negativeExponent() = assertExpr("5^(2)", "0.04")
@Test
fun trigonometricLimits() = assertExpr("sin(0)", "0")
@Test
fun sinAtPi() = assertExpr("sin(π)", "0")
@Test
fun sinAtHalfPi() = assertExpr("sin(π÷2)", "1")
@Test
fun cosAtPi() = assertExpr("cos(π)", "-1")
@Test
fun cosAtHalfPi() = assertExpr("cos(π÷2)", "0")
@Test
fun cosAtPiOverThree() = assertExpr("cos(π÷3)", "0.5")
} }

View File

@ -37,6 +37,16 @@ sealed interface BasicUnit {
interface NumberBase : BasicUnit { interface NumberBase : BasicUnit {
fun convert(unitTo: NumberBase, value: String): String fun convert(unitTo: NumberBase, value: String): String
companion object {
val Hexadecimal = NumberBaseUnit(
"hexadecimal",
BigDecimal(16),
UnitGroup.NUMBER_BASE,
0,
0,
)
}
} }
interface Default : BasicUnit { interface Default : BasicUnit {

View File

@ -120,7 +120,7 @@ internal fun Preferences.getUnitConverterFormatTime(): Boolean {
internal fun Preferences.getUnitConverterSorting(): UnitsListSorting { internal fun Preferences.getUnitConverterSorting(): UnitsListSorting {
return this[PrefsKeys.UNIT_CONVERTER_SORTING] return this[PrefsKeys.UNIT_CONVERTER_SORTING]
?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE ?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.SCALE_ASC
} }
internal fun Preferences.getShownUnitGroups(): List<UnitGroup> { internal fun Preferences.getShownUnitGroups(): List<UnitGroup> {

View File

@ -1,33 +1,28 @@
Calculator, converter and more. Calculator, converter and so much more!
Look for <b>Calculator</b> on your home screen after installing the app. NumberHub will be installed as "Calculator" on your home screen.
• Deep customization: themes, number formatter and etc. * No ads or in-app purchases
• No ads, in-app purchases or asking for donations * Open source
• Open source
<b>Calculator</b> Calculator
Copy, paste, save and share expression results * Copy, paste, save and share expression results
Trigonometric functions * Trigonometric functions
Fractional output * Fractional output
<b>Unit converter</b> **Unit converter**
• 570 units Over 500 units! Convert miles to kilometers, Dollar to Euro, Bytes to Gigabytes and so much more!
• Built-in currency converter
• Favorite units
• Organize unit groups
• Smart search algorithm
<b>Date calculator</b> **Date calculator**
• Add and subtract dates
• Calculate difference Add and subtract dates with ease
• Create events in calendar
**Time converter**
Convert time zones
<b>Time converter</b>
• Add to favorites
• Add labels to time zones
The app uses https://github.com/fawazahmed0/currency-api by https://github.com/fawazahmed0 The app uses https://github.com/fawazahmed0/currency-api by https://github.com/fawazahmed0
Requests are send to cdn.jsdelivr.net. Requests are sent to cdn.jsdelivr.net.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

After

Width:  |  Height:  |  Size: 1010 KiB

View File

@ -1 +1 @@
Your Hub for ✖️ Math / 💲 Currency rates / 📆 Date calculations / Time zones... Your Hub for Math / Currency rates / Date calculations / Time zones...

View File

@ -1 +1 @@
Unitto — calculator and unit converter NumberHub

View File

@ -22,6 +22,7 @@ import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.SizeTransform import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.expandHorizontally import androidx.compose.animation.expandHorizontally
@ -31,6 +32,11 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.AnchoredDraggableState
import androidx.compose.foundation.gestures.DraggableAnchors
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
@ -40,6 +46,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.SwapHoriz import androidx.compose.material.icons.outlined.SwapHoriz
@ -64,6 +71,7 @@ import androidx.compose.ui.draw.rotate
import androidx.compose.ui.focus.onFocusEvent import androidx.compose.ui.focus.onFocusEvent
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -94,11 +102,14 @@ import app.myzel394.numberhub.data.common.isExpression
import app.myzel394.numberhub.data.converter.ConverterResult import app.myzel394.numberhub.data.converter.ConverterResult
import app.myzel394.numberhub.data.converter.UnitID import app.myzel394.numberhub.data.converter.UnitID
import app.myzel394.numberhub.data.model.converter.UnitGroup import app.myzel394.numberhub.data.model.converter.UnitGroup
import app.myzel394.numberhub.feature.converter.components.BaseCalculationSummary
import app.myzel394.numberhub.feature.converter.components.DefaultKeyboard import app.myzel394.numberhub.feature.converter.components.DefaultKeyboard
import app.myzel394.numberhub.feature.converter.components.NumberBaseKeyboard import app.myzel394.numberhub.feature.converter.components.NumberBaseKeyboard
import app.myzel394.numberhub.feature.converter.components.UnitSelectionButton import app.myzel394.numberhub.feature.converter.components.UnitSelectionButton
import app.myzel394.numberhub.feature.converter.components.ValueOneSummary
import java.math.BigDecimal import java.math.BigDecimal
import java.util.Locale import java.util.Locale
import kotlin.math.absoluteValue
@Composable @Composable
internal fun ConverterRoute( internal fun ConverterRoute(
@ -203,10 +214,30 @@ private fun NumberBase(
convert() convert()
} }
val density = LocalDensity.current
val dragState = remember {
AnchoredDraggableState(
initialValue = DragState.CLOSED,
anchors = DraggableAnchors {
DragState.CLOSED at 0f
DragState.OPEN at with(density) { -60.dp.toPx() }
},
positionalThreshold = { 0f },
velocityThreshold = { 0f },
animationSpec = tween(easing = LinearEasing, durationMillis = 50),
)
}
PortraitLandscape( PortraitLandscape(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
content1 = { contentModifier -> content1 = { contentModifier ->
ColumnWithConstraints(modifier = contentModifier) { ColumnWithConstraints(
modifier = contentModifier
.anchoredDraggable(
state = dragState,
orientation = Orientation.Vertical,
),
) {
val textFieldModifier = Modifier.weight(2f) val textFieldModifier = Modifier.weight(2f)
NumberBaseTextField( NumberBaseTextField(
@ -224,6 +255,22 @@ private fun NumberBase(
) )
AnimatedUnitShortName(stringResource(uiState.unitTo.shortName)) AnimatedUnitShortName(stringResource(uiState.unitTo.shortName))
if (uiState.result is ConverterResult.NumberBase) {
BaseCalculationSummary(
modifier = Modifier
.fillMaxWidth()
.horizontalScroll(rememberScrollState())
.then(with(density) { Modifier.height(dragState.offset.absoluteValue.toDp()) }),
basis = uiState.unitTo,
result = uiState.result,
onResultChange = { newValue ->
val valueConverted = uiState.unitTo.convert(uiState.unitFrom, newValue)
updateInput1(TextFieldValue(valueConverted))
},
)
}
Spacer(modifier = Modifier.height(it.maxHeight * 0.03f)) Spacer(modifier = Modifier.height(it.maxHeight * 0.03f))
UnitSelectionButtons( UnitSelectionButtons(
@ -250,6 +297,7 @@ private fun NumberBase(
addDigit = { updateInput1(uiState.input.addTokens(it)) }, addDigit = { updateInput1(uiState.input.addTokens(it)) },
deleteDigit = { updateInput1(uiState.input.deleteTokens()) }, deleteDigit = { updateInput1(uiState.input.deleteTokens()) },
clearInput = { updateInput1(TextFieldValue()) }, clearInput = { updateInput1(TextFieldValue()) },
basis = uiState.unitFrom,
) )
}, },
) )
@ -284,6 +332,20 @@ private fun Default(
} }
var focusedOnInput1 by rememberSaveable { mutableStateOf(true) } var focusedOnInput1 by rememberSaveable { mutableStateOf(true) }
val density = LocalDensity.current
val dragState = remember {
AnchoredDraggableState(
initialValue = DragState.CLOSED,
anchors = DraggableAnchors {
DragState.CLOSED at 0f
DragState.OPEN at with(density) { -60.dp.toPx() }
},
positionalThreshold = { 0f },
velocityThreshold = { 0f },
animationSpec = tween(easing = LinearEasing, durationMillis = 50),
)
}
LaunchedEffect(connection) { LaunchedEffect(connection) {
if ((connection == ConnectionState.Available) and (uiState.result is ConverterResult.Error)) { if ((connection == ConnectionState.Available) and (uiState.result is ConverterResult.Error)) {
val unitFrom = uiState.unitFrom val unitFrom = uiState.unitFrom
@ -304,7 +366,13 @@ private fun Default(
PortraitLandscape( PortraitLandscape(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
content1 = { contentModifier -> content1 = { contentModifier ->
ColumnWithConstraints(modifier = contentModifier) { boxWithConstraintsScope -> ColumnWithConstraints(
modifier = contentModifier
.anchoredDraggable(
state = dragState,
orientation = Orientation.Vertical,
),
) { boxWithConstraintsScope ->
val textFieldModifier = Modifier val textFieldModifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.weight(2f) .weight(2f)
@ -425,6 +493,18 @@ private fun Default(
), ),
) )
if (uiState.result is ConverterResult.Default && uiState.unitTo.factor > BigDecimal.ZERO) {
ValueOneSummary(
modifier = with(density) {
Modifier
.fillMaxWidth()
.height(dragState.offset.absoluteValue.toDp())
.horizontalScroll(rememberScrollState())
},
uiState = uiState,
)
}
Spacer(modifier = Modifier.height(boxWithConstraintsScope.maxHeight * 0.03f)) Spacer(modifier = Modifier.height(boxWithConstraintsScope.maxHeight * 0.03f))
UnitSelectionButtons( UnitSelectionButtons(

View File

@ -0,0 +1,3 @@
package app.myzel394.numberhub.feature.converter
internal enum class DragState { CLOSED, OPEN }

View File

@ -156,7 +156,7 @@ private fun UnitFromSelectorScreenPreview() {
selectedUnitGroup = UnitGroup.SPEED, selectedUnitGroup = UnitGroup.SPEED,
shownUnitGroups = UnitGroup.entries, shownUnitGroups = UnitGroup.entries,
showFavoritesOnly = false, showFavoritesOnly = false,
sorting = UnitsListSorting.USAGE, sorting = UnitsListSorting.SCALE_ASC,
), ),
onQueryChange = {}, onQueryChange = {},
toggleFavoritesOnly = {}, toggleFavoritesOnly = {},

View File

@ -155,7 +155,7 @@ private fun UnitToSelectorPreview() {
query = TextFieldValue("test"), query = TextFieldValue("test"),
units = units, units = units,
showFavoritesOnly = false, showFavoritesOnly = false,
sorting = UnitsListSorting.USAGE, sorting = UnitsListSorting.SCALE_ASC,
input = "100", input = "100",
scale = 3, scale = 3,
outputFormat = OutputFormat.PLAIN, outputFormat = OutputFormat.PLAIN,

View File

@ -0,0 +1,86 @@
package app.myzel394.numberhub.feature.converter.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import app.myzel394.numberhub.data.converter.ConverterResult
import app.myzel394.numberhub.data.model.converter.unit.BasicUnit
@Composable
internal fun BaseCalculationSummary(
modifier: Modifier = Modifier,
basis: BasicUnit.NumberBase,
result: ConverterResult.NumberBase,
onResultChange: (String) -> Unit,
) {
val fontStyle = MaterialTheme.typography.headlineSmall
Row(
modifier,
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
) {
for (index in 0..<result.value.length) {
val character = result.value[index]
val digit = character.digitToInt(16);
val base = basis.factor.toInt()
Row(
modifier = Modifier
.clip(MaterialTheme.shapes.small)
.clickable {
val newCurrentValue = (digit + 1) % base
val newResultText = result.value.substring(
0,
index,
) + newCurrentValue.toString(16) + result.value.substring(index + 1)
onResultChange(newResultText)
}
.padding(vertical = 2.dp, horizontal = 6.dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "$digit",
style = fontStyle,
color = MaterialTheme.colorScheme.primary,
)
Text(
text = " · $base",
style = fontStyle,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
text = "${result.value.length - index - 1}",
modifier = Modifier.offset(
y = -(MaterialTheme.typography.bodySmall.fontSize.div(
2,
)).value.dp,
),
style = fontStyle.copy(
fontSize = MaterialTheme.typography.bodySmall.fontSize,
),
color = MaterialTheme.colorScheme.tertiary,
)
}
if (index < result.value.length - 1) {
Text(
text = " + ",
style = fontStyle,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}
}

View File

@ -18,18 +18,33 @@
package app.myzel394.numberhub.feature.converter.components package app.myzel394.numberhub.feature.converter.components
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.core.tween
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable 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.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview 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.base.R
import app.myzel394.numberhub.core.base.Token import app.myzel394.numberhub.core.base.Token
import app.myzel394.numberhub.core.ui.LocalWindowSize import app.myzel394.numberhub.core.ui.LocalWindowSize
import app.myzel394.numberhub.core.ui.WindowHeightSizeClass import app.myzel394.numberhub.core.ui.WindowHeightSizeClass
import app.myzel394.numberhub.core.ui.WindowWidthSizeClass
import app.myzel394.numberhub.core.ui.common.ColumnWithConstraints
import app.myzel394.numberhub.core.ui.common.KeyboardButtonFilled import app.myzel394.numberhub.core.ui.common.KeyboardButtonFilled
import app.myzel394.numberhub.core.ui.common.KeyboardButtonLight import app.myzel394.numberhub.core.ui.common.KeyboardButtonLight
import app.myzel394.numberhub.core.ui.common.KeyboardButtonTertiary import app.myzel394.numberhub.core.ui.common.KeyboardButtonTertiary
@ -65,6 +80,9 @@ 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.Power
import app.myzel394.numberhub.core.ui.common.icons.iconpack.RightBracket 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.Root
import app.myzel394.numberhub.data.model.converter.unit.BasicUnit
import app.myzel394.numberhub.feature.converter.createSortedArray
import kotlin.math.ceil
@Composable @Composable
internal fun DefaultKeyboard( internal fun DefaultKeyboard(
@ -79,92 +97,401 @@ internal fun DefaultKeyboard(
) { ) {
val fractionalIcon = remember(fractional) { if (fractional == Token.PERIOD) IconPack.Dot else IconPack.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 } 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 val contentHeight: Float =
if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonToken.CONTENT_HEIGHT_SHORT else KeyboardButtonToken.CONTENT_HEIGHT_TALL
KeypadFlow( KeypadFlow(
modifier = modifier, modifier = modifier,
rows = 5, rows = 5,
columns = 4, columns = 4,
) { width, height -> ) { width, height ->
val bModifier = Modifier.fillMaxWidth(width).fillMaxHeight(height) val bModifier = Modifier
.fillMaxWidth(width)
.fillMaxHeight(height)
if (acButton) { if (acButton) {
KeyboardButtonTertiary(bModifier, IconPack.Clear, stringResource(R.string.delete_label), contentHeight) { clearInput() } KeyboardButtonTertiary(
KeyboardButtonFilled(bModifier, IconPack.Brackets, stringResource(R.string.keyboard_brackets), contentHeight) { addBracket() } bModifier,
IconPack.Clear,
stringResource(R.string.delete_label),
contentHeight,
) { clearInput() }
KeyboardButtonFilled(
bModifier,
IconPack.Brackets,
stringResource(R.string.keyboard_brackets),
contentHeight,
) { addBracket() }
} else { } else {
KeyboardButtonFilled(bModifier, IconPack.LeftBracket, stringResource(R.string.keyboard_left_bracket), contentHeight) { addDigit(Token.Operator.leftBracket) } KeyboardButtonFilled(
KeyboardButtonFilled(bModifier, IconPack.RightBracket, stringResource(R.string.keyboard_right_bracket), contentHeight) { addDigit(Token.Operator.rightBracket) } bModifier,
IconPack.LeftBracket,
stringResource(R.string.keyboard_left_bracket),
contentHeight,
) { addDigit(Token.Operator.leftBracket) }
KeyboardButtonFilled(
bModifier,
IconPack.RightBracket,
stringResource(R.string.keyboard_right_bracket),
contentHeight,
) { addDigit(Token.Operator.rightBracket) }
} }
KeyboardButtonFilled(bModifier, IconPack.Power, stringResource(R.string.keyboard_power), contentHeight) { addDigit(Token.Operator.power) } KeyboardButtonFilled(
KeyboardButtonFilled(bModifier, IconPack.Root, stringResource(R.string.keyboard_root), contentHeight) { addDigit(Token.Operator.sqrt) } bModifier,
IconPack.Power,
stringResource(R.string.keyboard_power),
contentHeight,
) { addDigit(Token.Operator.power) }
KeyboardButtonFilled(
bModifier,
IconPack.Root,
stringResource(R.string.keyboard_root),
contentHeight,
) { addDigit(Token.Operator.sqrt) }
KeyboardButtonLight(bModifier, IconPack.Key7, Token.Digit._7, contentHeight) { addDigit(Token.Digit._7) } KeyboardButtonLight(
KeyboardButtonLight(bModifier, IconPack.Key8, Token.Digit._8, contentHeight) { addDigit(Token.Digit._8) } bModifier,
KeyboardButtonLight(bModifier, IconPack.Key9, Token.Digit._9, contentHeight) { addDigit(Token.Digit._9) } IconPack.Key7,
KeyboardButtonFilled(bModifier, IconPack.Divide, stringResource(R.string.keyboard_divide), contentHeight) { addDigit(Token.Operator.divide) } Token.Digit._7,
contentHeight,
) { addDigit(Token.Digit._7) }
KeyboardButtonLight(
bModifier,
IconPack.Key8,
Token.Digit._8,
contentHeight,
) { addDigit(Token.Digit._8) }
KeyboardButtonLight(
bModifier,
IconPack.Key9,
Token.Digit._9,
contentHeight,
) { addDigit(Token.Digit._9) }
KeyboardButtonFilled(
bModifier,
IconPack.Divide,
stringResource(R.string.keyboard_divide),
contentHeight,
) { addDigit(Token.Operator.divide) }
KeyboardButtonLight(bModifier, IconPack.Key4, Token.Digit._4, contentHeight) { addDigit(Token.Digit._4) } KeyboardButtonLight(
KeyboardButtonLight(bModifier, IconPack.Key5, Token.Digit._5, contentHeight) { addDigit(Token.Digit._5) } bModifier,
KeyboardButtonLight(bModifier, IconPack.Key6, Token.Digit._6, contentHeight) { addDigit(Token.Digit._6) } IconPack.Key4,
KeyboardButtonFilled(bModifier, IconPack.Multiply, stringResource(R.string.keyboard_multiply), contentHeight) { addDigit(Token.Operator.multiply) } Token.Digit._4,
contentHeight,
) { addDigit(Token.Digit._4) }
KeyboardButtonLight(
bModifier,
IconPack.Key5,
Token.Digit._5,
contentHeight,
) { addDigit(Token.Digit._5) }
KeyboardButtonLight(
bModifier,
IconPack.Key6,
Token.Digit._6,
contentHeight,
) { addDigit(Token.Digit._6) }
KeyboardButtonFilled(
bModifier,
IconPack.Multiply,
stringResource(R.string.keyboard_multiply),
contentHeight,
) { addDigit(Token.Operator.multiply) }
KeyboardButtonLight(bModifier, IconPack.Key1, Token.Digit._1, contentHeight) { addDigit(Token.Digit._1) } KeyboardButtonLight(
KeyboardButtonLight(bModifier, IconPack.Key2, Token.Digit._2, contentHeight) { addDigit(Token.Digit._2) } bModifier,
KeyboardButtonLight(bModifier, IconPack.Key3, Token.Digit._3, contentHeight) { addDigit(Token.Digit._3) } IconPack.Key1,
KeyboardButtonFilled(bModifier, IconPack.Minus, stringResource(R.string.keyboard_minus), contentHeight) { addDigit(Token.Operator.minus) } Token.Digit._1,
contentHeight,
) { addDigit(Token.Digit._1) }
KeyboardButtonLight(
bModifier,
IconPack.Key2,
Token.Digit._2,
contentHeight,
) { addDigit(Token.Digit._2) }
KeyboardButtonLight(
bModifier,
IconPack.Key3,
Token.Digit._3,
contentHeight,
) { addDigit(Token.Digit._3) }
KeyboardButtonFilled(
bModifier,
IconPack.Minus,
stringResource(R.string.keyboard_minus),
contentHeight,
) { addDigit(Token.Operator.minus) }
if (middleZero) { if (middleZero) {
KeyboardButtonLight(bModifier, fractionalIcon, stringResource(fractionalIconDescription), contentHeight) { addDigit(Token.Digit.dot) } KeyboardButtonLight(
KeyboardButtonLight(bModifier, IconPack.Key0, Token.Digit._0, contentHeight) { addDigit(Token.Digit._0) } bModifier,
fractionalIcon,
stringResource(fractionalIconDescription),
contentHeight,
) { addDigit(Token.Digit.dot) }
KeyboardButtonLight(
bModifier,
IconPack.Key0,
Token.Digit._0,
contentHeight,
) { addDigit(Token.Digit._0) }
} else { } else {
KeyboardButtonLight(bModifier, IconPack.Key0, Token.Digit._0, contentHeight) { addDigit(Token.Digit._0) } KeyboardButtonLight(
KeyboardButtonLight(bModifier, fractionalIcon, stringResource(fractionalIconDescription), contentHeight) { addDigit(Token.Digit.dot) } bModifier,
IconPack.Key0,
Token.Digit._0,
contentHeight,
) { addDigit(Token.Digit._0) }
KeyboardButtonLight(
bModifier,
fractionalIcon,
stringResource(fractionalIconDescription),
contentHeight,
) { addDigit(Token.Digit.dot) }
} }
KeyboardButtonLight(bModifier, IconPack.Backspace, stringResource(R.string.delete_label), contentHeight, onLongClick = clearInput) { deleteDigit() } KeyboardButtonLight(
KeyboardButtonFilled(bModifier, IconPack.Plus, stringResource(R.string.keyboard_plus), contentHeight) { addDigit(Token.Operator.plus) } bModifier,
IconPack.Backspace,
stringResource(R.string.delete_label),
contentHeight,
onLongClick = clearInput,
) { deleteDigit() }
KeyboardButtonFilled(
bModifier,
IconPack.Plus,
stringResource(R.string.keyboard_plus),
contentHeight,
) { addDigit(Token.Operator.plus) }
} }
} }
val AVAILABLE_NUMBERS = mapOf<String, ImageVector>(
Token.Digit._0 to IconPack.Key0,
Token.Digit._1 to IconPack.Key1,
Token.Digit._2 to IconPack.Key2,
Token.Digit._3 to IconPack.Key3,
Token.Digit._4 to IconPack.Key4,
Token.Digit._5 to IconPack.Key5,
Token.Digit._6 to IconPack.Key6,
Token.Digit._7 to IconPack.Key7,
Token.Digit._8 to IconPack.Key8,
Token.Digit._9 to IconPack.Key9,
Token.Letter._A to IconPack.KeyA,
Token.Letter._B to IconPack.KeyB,
Token.Letter._C to IconPack.KeyC,
Token.Letter._D to IconPack.KeyD,
Token.Letter._E to IconPack.KeyE,
Token.Letter._F to IconPack.KeyF,
)
@Composable @Composable
internal fun NumberBaseKeyboard( internal fun NumberBaseKeyboard(
modifier: Modifier, modifier: Modifier,
addDigit: (String) -> Unit, addDigit: (String) -> Unit,
clearInput: () -> Unit, clearInput: () -> Unit,
deleteDigit: () -> Unit, deleteDigit: () -> Unit,
basis: BasicUnit.NumberBase,
) { ) {
val contentHeight: Float = if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonToken.CONTENT_HEIGHT_SHORT else KeyboardButtonToken.CONTENT_HEIGHT_TALL val contentHeight: Float = if (LocalWindowSize.current.heightSizeClass < WindowHeightSizeClass.Medium) KeyboardButtonToken.CONTENT_HEIGHT_SHORT else KeyboardButtonToken.CONTENT_HEIGHT_TALL
val isUsingColumn =
(LocalWindowSize.current.widthSizeClass > WindowWidthSizeClass.Expanded) or (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact)
KeypadFlow( var direction by remember {
modifier = modifier, mutableStateOf(AnimatedContentTransitionScope.SlideDirection.Right)
rows = 6, }
columns = 3,
) { width, height ->
val bModifier = Modifier.fillMaxWidth(width).fillMaxHeight(height)
val wideButtonModifier = Modifier.fillMaxHeight(height).fillMaxWidth(width * 2)
KeyboardButtonFilled(bModifier, IconPack.KeyA, Token.Letter._A, contentHeight) { addDigit(Token.Letter._A) } LaunchedEffect(isUsingColumn) {
KeyboardButtonFilled(bModifier, IconPack.KeyB, Token.Letter._B, contentHeight) { addDigit(Token.Letter._B) } direction = if (isUsingColumn) {
KeyboardButtonFilled(bModifier, IconPack.KeyC, Token.Letter._C, contentHeight) { addDigit(Token.Letter._C) } AnimatedContentTransitionScope.SlideDirection.Right
} else {
AnimatedContentTransitionScope.SlideDirection.Up
}
}
KeyboardButtonFilled(bModifier, IconPack.KeyD, Token.Letter._D, contentHeight) { addDigit(Token.Letter._D) } LaunchedEffect(basis) {
KeyboardButtonFilled(bModifier, IconPack.KeyE, Token.Letter._E, contentHeight) { addDigit(Token.Letter._E) } direction = when (direction) {
KeyboardButtonFilled(bModifier, IconPack.KeyF, Token.Letter._F, contentHeight) { addDigit(Token.Letter._F) } AnimatedContentTransitionScope.SlideDirection.Up -> AnimatedContentTransitionScope.SlideDirection.Down
AnimatedContentTransitionScope.SlideDirection.Down -> AnimatedContentTransitionScope.SlideDirection.Up
AnimatedContentTransitionScope.SlideDirection.Left -> AnimatedContentTransitionScope.SlideDirection.Right
AnimatedContentTransitionScope.SlideDirection.Right -> AnimatedContentTransitionScope.SlideDirection.Left
else -> direction
}
}
KeyboardButtonLight(bModifier, IconPack.Key7, Token.Digit._7, contentHeight) { addDigit(Token.Digit._7) } ColumnWithConstraints(modifier) { constraints ->
KeyboardButtonLight(bModifier, IconPack.Key8, Token.Digit._8, contentHeight) { addDigit(Token.Digit._8) } AnimatedContent(
KeyboardButtonLight(bModifier, IconPack.Key9, Token.Digit._9, contentHeight) { addDigit(Token.Digit._9) } transitionSpec = {
slideIntoContainer(animationSpec = tween(600), towards = direction).togetherWith(
slideOutOfContainer(animationSpec = tween(600), towards = direction),
)
},
targetState = basis.factor.toInt(),
label = "ConverterKeyboard-FlowRow",
) { amount ->
val columns: Int = when {
amount == 5 -> 2
amount == 3 -> 2
amount == 7 -> 2
amount == 10 -> 3
amount < 10 -> if (amount.and(1) == 0) 2 else if (amount % 3 == 0) 3 else amount % 3
else -> 3
}
val rows = when {
amount == 5 -> 3
amount == 3 -> 2
amount == 7 -> 4
amount == 10 -> 4
amount < 10 -> ceil(amount.toDouble() / columns.toDouble()).toInt() + 1
amount == 11 -> 5
amount == 12 -> 5
amount == 13 -> 5
else -> 6
}
val horizontalSpacing = 8.dp
val verticalSpacing = 12.dp
val height: Float = (1f - (verticalSpacing * (rows - 1) / constraints.maxHeight)) / rows
KeyboardButtonLight(bModifier, IconPack.Key4, Token.Digit._4, contentHeight) { addDigit(Token.Digit._4) } FlowRow(
KeyboardButtonLight(bModifier, IconPack.Key5, Token.Digit._5, contentHeight) { addDigit(Token.Digit._5) } modifier = modifier,
KeyboardButtonLight(bModifier, IconPack.Key6, Token.Digit._6, contentHeight) { addDigit(Token.Digit._6) } maxItemsInEachRow = columns,
horizontalArrangement = Arrangement.spacedBy(horizontalSpacing),
verticalArrangement = Arrangement.spacedBy(verticalSpacing),
) {
val bModifier = Modifier
.fillMaxHeight(height)
.fillMaxWidth()
KeyboardButtonLight(bModifier, IconPack.Key1, Token.Digit._1, contentHeight) { addDigit(Token.Digit._1) } when {
KeyboardButtonLight(bModifier, IconPack.Key2, Token.Digit._2, contentHeight) { addDigit(Token.Digit._2) } amount in arrayOf(3, 5, 7) -> {
KeyboardButtonLight(bModifier, IconPack.Key3, Token.Digit._3, contentHeight) { addDigit(Token.Digit._3) } for (int in createSortedArray(1..<amount, columns)) {
val key = AVAILABLE_NUMBERS.keys.elementAt(int)
val icon = AVAILABLE_NUMBERS[key]!!
KeyboardButtonLight(
bModifier.weight(1f),
icon,
key,
contentHeight,
) { addDigit(key) }
}
// TODO Should be a separate o use custom widthFillFactors and heightFillFactors KeyboardButtonLight(
KeyboardButtonLight(bModifier, IconPack.Key0, Token.Digit._0, contentHeight) { addDigit(Token.Digit._0) } bModifier.weight(1f),
KeyboardButtonLight(wideButtonModifier, IconPack.Backspace, stringResource(R.string.delete_label), contentHeight, clearInput) { deleteDigit() } IconPack.Key0,
Token.Digit._0,
contentHeight,
) { addDigit(Token.Digit._0) }
KeyboardButtonTertiary(
bModifier.weight(1f),
IconPack.Backspace,
stringResource(R.string.delete_label),
contentHeight,
clearInput,
) { deleteDigit() }
}
amount < 10 -> {
for (int in createSortedArray(0..<amount.coerceAtMost(10), columns)) {
val key = AVAILABLE_NUMBERS.keys.elementAt(int)
val icon = AVAILABLE_NUMBERS[key]!!
KeyboardButtonLight(
bModifier.weight(1f),
icon,
key,
contentHeight,
) { addDigit(key) }
}
KeyboardButtonTertiary(
bModifier,
IconPack.Backspace,
stringResource(R.string.delete_label),
contentHeight,
clearInput,
) { deleteDigit() }
}
amount == 10 -> {
for (int in createSortedArray(1..9, columns)) {
val key = AVAILABLE_NUMBERS.keys.elementAt(int)
val icon = AVAILABLE_NUMBERS[key]!!
KeyboardButtonLight(
bModifier.weight(1f),
icon,
key,
contentHeight,
) { addDigit(key) }
}
KeyboardButtonLight(
bModifier.weight(1f),
IconPack.Key0,
Token.Digit._0,
contentHeight,
) { addDigit(Token.Digit._0) }
KeyboardButtonTertiary(
bModifier.weight(2f),
IconPack.Backspace,
stringResource(R.string.delete_label),
contentHeight,
clearInput,
) { deleteDigit() }
}
else -> {
val rowsAmount = ceil((amount - 10) / 3f).toInt()
for (row in (rowsAmount - 1) downTo 0) {
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(horizontalSpacing),
) {
val rowStart = 10 + (row) * columns
val rowEnd = (rowStart + 3).coerceAtMost(amount.coerceAtMost(16))
for (index in createSortedArray(rowStart..<rowEnd, columns)) {
val key = AVAILABLE_NUMBERS.keys.elementAt(index)
val icon = AVAILABLE_NUMBERS[key]!!
KeyboardButtonFilled(
bModifier.weight(1f),
icon,
key,
contentHeight,
) { addDigit(key) }
}
}
}
for (int in createSortedArray(1..9, columns)) {
val key = AVAILABLE_NUMBERS.keys.elementAt(int)
val icon = AVAILABLE_NUMBERS[key]!!
KeyboardButtonLight(
bModifier.weight(1f),
icon,
key,
contentHeight,
) { addDigit(key) }
}
KeyboardButtonLight(
bModifier.weight(1f),
IconPack.Key0,
Token.Digit._0,
contentHeight,
) { addDigit(Token.Digit._0) }
KeyboardButtonTertiary(
bModifier.weight(2f),
IconPack.Backspace,
stringResource(R.string.delete_label),
contentHeight,
clearInput,
) { deleteDigit() }
}
}
}
}
} }
} }
@ -191,5 +518,6 @@ private fun PreviewConverterKeyboardNumberBase() {
addDigit = {}, addDigit = {},
clearInput = {}, clearInput = {},
deleteDigit = {}, deleteDigit = {},
basis = BasicUnit.NumberBase.Hexadecimal,
) )
} }

View File

@ -0,0 +1,74 @@
package app.myzel394.numberhub.feature.converter.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import app.myzel394.numberhub.data.common.format
import app.myzel394.numberhub.feature.converter.UnitConverterUIState
import java.math.BigDecimal
@Composable
internal fun ValueOneSummary(
modifier: Modifier = Modifier,
uiState: UnitConverterUIState.Default,
) {
val unitFromLabel = LocalContext.current.getString(uiState.unitFrom.displayName)
val unitToLabel = LocalContext.current.getString(uiState.unitTo.displayName)
val value = uiState.unitFrom.convert(uiState.unitTo, BigDecimal(1))
.format(uiState.scale, uiState.outputFormat)
val fontStyle = MaterialTheme.typography.headlineSmall
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
) {
Text(
1.toString(),
style = fontStyle,
color = MaterialTheme.colorScheme.primary,
)
Text(
" ",
style = fontStyle,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
unitFromLabel,
style = fontStyle,
color = MaterialTheme.colorScheme.tertiary,
)
Text(
" = ",
style = fontStyle,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
value,
style = fontStyle,
color = MaterialTheme.colorScheme.primary,
)
Text(
" ",
style = fontStyle,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
unitToLabel,
style = fontStyle,
color = MaterialTheme.colorScheme.tertiary,
)
}
}

View File

@ -0,0 +1,25 @@
package app.myzel394.numberhub.feature.converter
import kotlin.math.ceil
// So here's the problem. If we just go down from 3 downto 0 with columns 2, this results in:
// [3, 2]
// [1, 0]
// While this is correct, the ordering is incorrect. It should be
// [2, 3]
// [0, 1]
// TODO: Add support for rtl languages
internal fun createSortedArray(range: IntRange, columns: Int): List<Int> {
val result = mutableListOf<Int>()
val rows = ceil(range.count().toDouble() / columns.toDouble()).toInt()
for (row in rows downTo 0) {
for (column in 0 until columns) {
val index = row * columns + column + range.first
if (index <= range.last) {
result.add(index)
}
}
}
return result
}

View File

@ -112,7 +112,7 @@ internal fun ZonedDateTime.minus(
) )
} }
private val yearInSeconds by lazy { BigDecimal("31104000") } private val yearInSeconds by lazy { BigDecimal("31536000") }
private val monthsInSeconds by lazy { BigDecimal("2592000") } private val monthsInSeconds by lazy { BigDecimal("2592000") }
private val dayInSeconds by lazy { BigDecimal("86400") } private val dayInSeconds by lazy { BigDecimal("86400") }
private val hourInSeconds by lazy { BigDecimal("3600") } private val hourInSeconds by lazy { BigDecimal("3600") }

View File

@ -139,7 +139,7 @@ private fun PreviewConverterSettingsScreen() {
precision = 3, precision = 3,
outputFormat = OutputFormat.PLAIN, outputFormat = OutputFormat.PLAIN,
unitConverterFormatTime = false, unitConverterFormatTime = false,
unitConverterSorting = UnitsListSorting.USAGE, unitConverterSorting = UnitsListSorting.SCALE_ASC,
shownUnitGroups = UnitGroup.entries, shownUnitGroups = UnitGroup.entries,
unitConverterFavoritesOnly = false, unitConverterFavoritesOnly = false,
enableToolsExperiment = false, enableToolsExperiment = false,

View File

@ -1,31 +1,31 @@
[versions] [versions]
versionCode = "4" versionCode = "22"
versionName = "NumberHub" versionName = "0.2.2"
androidxBrowserBrowser = "1.8.0" androidxBrowserBrowser = "1.8.0"
androidGradlePlugin = "8.3.2" androidGradlePlugin = "8.3.2"
androidxActivityActivityCompose = "1.9.0" androidxActivityActivityCompose = "1.9.3"
androidxAppCompatAppCompat = "1.6.1" androidxAppCompatAppCompat = "1.7.0"
androidxCompose = "1.6.7" androidxCompose = "1.6.8"
androidxComposeCompiler = "1.5.9" androidxComposeCompiler = "1.5.9"
androidxComposeMaterial3 = "1.2.1" androidxComposeMaterial3 = "1.2.1"
androidxCoreCoreKts = "1.13.1" androidxCoreCoreKts = "1.13.1"
androidxGlanceGlance = "1.0.0" androidxGlanceGlance = "1.1.1"
androidxDatastoreDatastorePreferences = "1.1.1" androidxDatastoreDatastorePreferences = "1.1.1"
androidxEspresso = "3.5.1" androidxEspresso = "3.6.1"
androidxHiltHiltNavigationCompose = "1.2.0" androidxHiltHiltNavigationCompose = "1.2.0"
androidxMacroBenchmark = "1.2.4" androidxMacroBenchmark = "1.3.3"
androidxLifecycleLifecycleRuntimeCompose = "2.7.0" androidxLifecycleLifecycleRuntimeCompose = "2.8.6"
androidxNavigationNavigationCompose = "2.7.7" androidxNavigationNavigationCompose = "2.7.7"
androidxProfileinstallerProfileinstaller = "1.3.1" androidxProfileinstallerProfileinstaller = "1.4.1"
androidxRoom = "2.6.1" androidxRoom = "2.6.1"
androidxTest = "1.5.0" androidxTest = "1.6.1"
androidxTestExtJunitKtx = "1.1.5" androidxTestExtJunitKtx = "1.2.1"
androidxTestRunner = "1.5.2" androidxTestRunner = "1.6.2"
androidxUiAutomator = "2.3.0" androidxUiAutomator = "2.3.0"
androidxWindowWindow = "1.2.0" androidxWindowWindow = "1.3.0"
androidxWorkWorkRuntimeKtx = "2.9.0" androidxWorkWorkRuntimeKtx = "2.9.1"
comAndroidToolsDesugarJdkLibs = "2.0.4" comAndroidToolsDesugarJdkLibs = "2.1.2"
comGithubSadellieThemmo = "1.3.0" comGithubSadellieThemmo = "1.3.0"
comGoogleDagger = "2.49" comGoogleDagger = "2.49"
comSquareupMoshiMoshiKotlin = "1.15.0" comSquareupMoshiMoshiKotlin = "1.15.0"

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
readme_content/showcase.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB