From 681ff8b4bd4c6adcfcc96994f4eb1dffebe98786 Mon Sep 17 00:00:00 2001 From: angrezichatterbox Date: Tue, 21 Jan 2025 22:30:38 +0530 Subject: [PATCH 1/6] feat: Added drawable for suggestion button background --- ...gender_suggestion_button_left_background.xml | 17 +++++++++++++++++ ...ender_suggestion_button_right_background.xml | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 app/src/main/res/drawable/gender_suggestion_button_left_background.xml create mode 100644 app/src/main/res/drawable/gender_suggestion_button_right_background.xml diff --git a/app/src/main/res/drawable/gender_suggestion_button_left_background.xml b/app/src/main/res/drawable/gender_suggestion_button_left_background.xml new file mode 100644 index 00000000..90c9168f --- /dev/null +++ b/app/src/main/res/drawable/gender_suggestion_button_left_background.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/gender_suggestion_button_right_background.xml b/app/src/main/res/drawable/gender_suggestion_button_right_background.xml new file mode 100644 index 00000000..adfa6332 --- /dev/null +++ b/app/src/main/res/drawable/gender_suggestion_button_right_background.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + From 99a598ec93c6d379b67c8fde867a65ec7334bbdd Mon Sep 17 00:00:00 2001 From: angrezichatterbox Date: Tue, 21 Jan 2025 22:32:04 +0530 Subject: [PATCH 2/6] feat: Implemneted mutliple noun type suggestion --- app/build.gradle.kts | 2 + .../be/scri/helpers/DatabaseFileManager.kt | 24 +++ .../java/be/scri/helpers/DatabaseHelper.kt | 120 ++++-------- .../java/be/scri/helpers/DatabaseManagers.kt | 17 ++ .../KeyboardDBHelper/ContractDataLoader.kt | 28 +++ .../KeyboardDBHelper/EmojiDataManager.kt | 43 +++++ .../KeyboardDBHelper/GenderDataManager.kt | 106 +++++++++++ .../KeyboardDBHelper/PluralFormsManager.kt | 72 +++++++ .../main/java/be/scri/models/DataContract.kt | 29 +++ .../be/scri/services/EnglishKeyboardIME.kt | 6 +- .../be/scri/services/FrenchKeyboardIME.kt | 5 +- .../be/scri/services/GeneralKeyboardIME.kt | 179 +++++++++++++++--- .../be/scri/services/GermanKeyboardIME.kt | 7 +- .../be/scri/services/ItalianKeyboardIME.kt | 5 +- .../be/scri/services/PortugueseKeyboardIME.kt | 5 +- .../be/scri/services/RussianKeyboardIME.kt | 5 +- .../be/scri/services/SpanishKeyboardIME.kt | 5 +- .../be/scri/services/SwedishKeyboardIME.kt | 5 +- .../layout/keyboard_view_command_options.xml | 38 ++++ 19 files changed, 570 insertions(+), 131 deletions(-) create mode 100644 app/src/main/java/be/scri/helpers/DatabaseFileManager.kt create mode 100644 app/src/main/java/be/scri/helpers/DatabaseManagers.kt create mode 100644 app/src/main/java/be/scri/helpers/KeyboardDBHelper/ContractDataLoader.kt create mode 100644 app/src/main/java/be/scri/helpers/KeyboardDBHelper/EmojiDataManager.kt create mode 100644 app/src/main/java/be/scri/helpers/KeyboardDBHelper/GenderDataManager.kt create mode 100644 app/src/main/java/be/scri/helpers/KeyboardDBHelper/PluralFormsManager.kt create mode 100644 app/src/main/java/be/scri/models/DataContract.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8ae3a6fe..ed823bd4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -19,6 +19,7 @@ plugins { id("de.mannodermaus.android-junit5") version "1.11.2.0" id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" id("jacoco") + kotlin("plugin.serialization") version "1.9.0" } jacoco { @@ -247,6 +248,7 @@ dependencies { api("com.google.code.gson:gson:2.10.1") api("com.github.bumptech.glide:glide:4.14.2") ksp("com.github.bumptech.glide:ksp:4.14.2") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") } tasks.register("moveFromi18n") { diff --git a/app/src/main/java/be/scri/helpers/DatabaseFileManager.kt b/app/src/main/java/be/scri/helpers/DatabaseFileManager.kt new file mode 100644 index 00000000..ac01d194 --- /dev/null +++ b/app/src/main/java/be/scri/helpers/DatabaseFileManager.kt @@ -0,0 +1,24 @@ +package be.scri.helpers + +import android.content.Context +import android.util.Log +import java.io.FileOutputStream + +class DatabaseFileManager( + private val context: Context, +) { + fun loadDatabaseFile(language: String) { + val databaseName = "${language}LanguageData.sqlite" + val dbFile = context.getDatabasePath(databaseName) + Log.i("ALPHA", "Loaded Database") + + if (!dbFile.exists()) { + context.assets.open("data/$databaseName").use { inputStream -> + FileOutputStream(dbFile).use { outputStream -> + inputStream.copyTo(outputStream) + outputStream.flush() + } + } + } + } +} diff --git a/app/src/main/java/be/scri/helpers/DatabaseHelper.kt b/app/src/main/java/be/scri/helpers/DatabaseHelper.kt index 9b180cc6..f0e2d1f6 100644 --- a/app/src/main/java/be/scri/helpers/DatabaseHelper.kt +++ b/app/src/main/java/be/scri/helpers/DatabaseHelper.kt @@ -1,35 +1,19 @@ -/** - * A helper to facilitate database calls for Scribe keyboard commands. - * - * Copyright (C) 2024 Scribe - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package be.scri.helpers import android.content.Context -import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper -import java.io.FileOutputStream -import java.io.InputStream -import java.io.OutputStream class DatabaseHelper( - private val context: Context, -) : SQLiteOpenHelper(context, null, null, DATABASE_VERSION) { + context: Context, +) : SQLiteOpenHelper( + context, + null, + null, + DATABASE_VERSION, + ) { + private val dbManagers = DatabaseManagers(context) + companion object { private const val DATABASE_VERSION = 1 } @@ -47,66 +31,28 @@ class DatabaseHelper( } fun loadDatabase(language: String) { - val databaseName = "${language}LanguageData.sqlite" - val dbFile = context.getDatabasePath(databaseName) - if (!dbFile.exists()) { - val inputStream: InputStream = context.assets.open("data/$databaseName") - val outputStream: OutputStream = FileOutputStream(dbFile) - - inputStream.copyTo(outputStream) - - outputStream.flush() - outputStream.close() - inputStream.close() - } - } - - fun getEmojiKeywords(language: String): HashMap> { - val hashMap = HashMap>() - val dbFile = context.getDatabasePath("${language}LanguageData.sqlite") - val db = SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READONLY) - val cursor = db.rawQuery("SELECT * FROM emoji_keywords", null) - - cursor.use { - if (cursor.moveToFirst()) { - do { - val key = cursor.getString(0) - hashMap[key] = getEmojiKeyMaps(cursor) - } while (cursor.moveToNext()) - } - } - return hashMap - } - - fun getEmojiKeyMaps(cursor: Cursor): MutableList { - val values = mutableListOf() - - for (i in 1 until cursor.columnCount) { - values.add(cursor.getString(i)) - } - return values - } - - fun getNounKeywords(language: String): HashMap> { - val hashMap = HashMap>() - val dbFile = context.getDatabasePath("${language}LanguageData.sqlite") - val db = SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READONLY) - val cursor = db.rawQuery("SELECT * FROM nouns", null) - - cursor.use { - if (cursor.moveToFirst()) { - do { - val key = cursor.getString(0).lowercase() - hashMap[key] = getNounKeyMaps(cursor) - } while (cursor.moveToNext()) - } - } - return hashMap - } - - fun getNounKeyMaps(cursor: Cursor): MutableList { - val values = mutableListOf() - values.add(cursor.getString(2)) - return values - } + dbManagers.fileManager.loadDatabaseFile(language) + } + + fun getRequiredData(language: String): DataContract? = + dbManagers.contractLoader.loadContract( + language, + ) + + fun getEmojiKeywords(language: String): HashMap> = + dbManagers.emojiManager.getEmojiKeywords( + language, + ) + + fun findGenderOfWord(language: String): HashMap> = + dbManagers.genderManager.findGenderOfWord( + language, + getRequiredData(language), + ) + + fun checkIfWordIsPlural(language: String): List? = + dbManagers.pluralManager.checkIfWordIsPlural( + language, + getRequiredData(language), + ) } diff --git a/app/src/main/java/be/scri/helpers/DatabaseManagers.kt b/app/src/main/java/be/scri/helpers/DatabaseManagers.kt new file mode 100644 index 00000000..a7679eca --- /dev/null +++ b/app/src/main/java/be/scri/helpers/DatabaseManagers.kt @@ -0,0 +1,17 @@ +package be.scri.helpers + +import ContractDataLoader +import EmojiDataManager +import GenderDataManager +import PluralFormsManager +import android.content.Context + +class DatabaseManagers( + context: Context, +) { + val fileManager = DatabaseFileManager(context) + val contractLoader = ContractDataLoader(context) + val emojiManager = EmojiDataManager(context) + val genderManager = GenderDataManager(context) + val pluralManager = PluralFormsManager(context) +} diff --git a/app/src/main/java/be/scri/helpers/KeyboardDBHelper/ContractDataLoader.kt b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/ContractDataLoader.kt new file mode 100644 index 00000000..765d788d --- /dev/null +++ b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/ContractDataLoader.kt @@ -0,0 +1,28 @@ + +import android.content.Context +import android.util.Log +import kotlinx.serialization.json.Json +import java.io.IOException + +class ContractDataLoader( + private val context: Context, +) { + fun loadContract(language: String): DataContract? { + val contractName = "${language.lowercase()}.json" + Log.i("ALPHA", "This is the $language") + + return try { + val json = Json { ignoreUnknownKeys = true } + context.assets.open("data-contracts/$contractName").use { contractFile -> + val content = contractFile.bufferedReader().readText() + Log.i("ALPHA", content) + json.decodeFromString(content).also { + Log.i("MY-TAG", it.toString()) + } + } + } catch (e: IOException) { + Log.e("MY-TAG", "Error loading contract: $contractName", e) + null + } + } +} diff --git a/app/src/main/java/be/scri/helpers/KeyboardDBHelper/EmojiDataManager.kt b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/EmojiDataManager.kt new file mode 100644 index 00000000..cf9b5486 --- /dev/null +++ b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/EmojiDataManager.kt @@ -0,0 +1,43 @@ + + +import android.content.Context +import android.database.Cursor +import android.database.sqlite.SQLiteDatabase + +class EmojiDataManager( + private val context: Context, +) { + fun getEmojiKeywords(language: String): HashMap> { + val dbFile = context.getDatabasePath("${language}LanguageData.sqlite") + return processEmojiKeywords(dbFile.path) + } + + private fun processEmojiKeywords(dbPath: String): HashMap> { + val hashMap = HashMap>() + val db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY) + + db.use { database -> + database.rawQuery("SELECT * FROM emoji_keywords", null).use { cursor -> + processEmojiCursor(cursor, hashMap) + } + } + return hashMap + } + + private fun processEmojiCursor( + cursor: Cursor, + hashMap: HashMap>, + ) { + if (!cursor.moveToFirst()) return + + do { + val key = cursor.getString(0) + hashMap[key] = getEmojiKeyMaps(cursor) + } while (cursor.moveToNext()) + } + + private fun getEmojiKeyMaps(cursor: Cursor): MutableList = + MutableList(cursor.columnCount - 1) { index -> + cursor.getString(index + 1) + } +} diff --git a/app/src/main/java/be/scri/helpers/KeyboardDBHelper/GenderDataManager.kt b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/GenderDataManager.kt new file mode 100644 index 00000000..8adb59a7 --- /dev/null +++ b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/GenderDataManager.kt @@ -0,0 +1,106 @@ +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.util.Log + +class GenderDataManager( + private val context: Context, +) { + fun findGenderOfWord( + language: String, + jsonData: DataContract?, + ): HashMap> = + when { + jsonData == null -> HashMap() + !context.getDatabasePath("${language}LanguageData.sqlite").exists() -> { + Log.e("MY-TAG", "Database file for $language does not exist.") + HashMap() + } + + else -> processGenderData("${language}LanguageData.sqlite", jsonData) + } + + private fun processGenderData( + dbPath: String, + jsonData: DataContract, + ): HashMap> = + HashMap>().also { genderMap -> + context.getDatabasePath(dbPath).path.let { path -> + SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY).use { db -> + when { + hasCanonicalGender(jsonData) -> + processGenders( + db = db, + nounColumn = jsonData.numbers.keys.firstOrNull(), + genderColumn = jsonData.genders.canonical.firstOrNull(), + genderMap = genderMap, + ) + + hasMasculineFeminine(jsonData) -> { + processGenders( + db = db, + nounColumn = jsonData.genders.masculines.firstOrNull(), + genderMap = genderMap, + defaultGender = "masculine", + ) + processGenders( + db = db, + nounColumn = jsonData.genders.feminines.firstOrNull(), + genderMap = genderMap, + defaultGender = "feminine", + ) + } + + else -> Log.e("MY-TAG", "No valid gender columns found.") + } + } + } + Log.i("MY-TAG", "Found ${genderMap.size} gender entries") + } + + private fun hasCanonicalGender(jsonData: DataContract): Boolean = + jsonData.genders.canonical + .firstOrNull() + ?.isNotEmpty() == true + + private fun hasMasculineFeminine(jsonData: DataContract): Boolean = + jsonData.genders.masculines.isNotEmpty() && + jsonData.genders.feminines.isNotEmpty() + + @Suppress("NestedBlockDepth") + private fun processGenders( + db: SQLiteDatabase, + nounColumn: String?, + genderMap: HashMap>, + genderColumn: String? = null, + defaultGender: String? = null, + ) { + db.rawQuery("SELECT * FROM nouns", null)?.use { cursor -> + val nounIndex = cursor.getColumnIndex(nounColumn) + val genderIndex = genderColumn?.let { cursor.getColumnIndex(it) } ?: -1 + + if (nounIndex == -1 || (genderColumn != null && genderIndex == -1)) { + Log.e("MY-TAG", "Required columns not found.") + return + } + + while (cursor.moveToNext()) { + cursor.getString(nounIndex)?.lowercase()?.takeUnless { it.isEmpty() }?.let { noun -> + val gender = + when { + genderColumn != null -> cursor.getString(genderIndex) + else -> defaultGender + } + + if (!gender.isNullOrEmpty()) { + val existingGenders = genderMap[noun]?.toMutableList() ?: mutableListOf() + if (!existingGenders.contains(gender)) { + existingGenders.add(gender) + genderMap[noun] = existingGenders + } + } + } + } + } + Log.i("MY-TAG", genderMap["schild"].toString()) + } +} diff --git a/app/src/main/java/be/scri/helpers/KeyboardDBHelper/PluralFormsManager.kt b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/PluralFormsManager.kt new file mode 100644 index 00000000..7c920370 --- /dev/null +++ b/app/src/main/java/be/scri/helpers/KeyboardDBHelper/PluralFormsManager.kt @@ -0,0 +1,72 @@ + + +import android.content.Context +import android.database.Cursor +import android.database.sqlite.SQLiteDatabase +import android.util.Log + +class PluralFormsManager( + private val context: Context, +) { + fun checkIfWordIsPlural( + language: String, + jsonData: DataContract?, + ): List? { + if (jsonData?.numbers?.values.isNullOrEmpty()) { + Log.e("MY-TAG", "JSON data for 'numbers' is null or empty.") + return null + } + + val dbFile = context.getDatabasePath("${language}LanguageData.sqlite") + val pluralForms = jsonData.numbers.values.toList() + Log.d("MY-TAG", "Plural Forms: $pluralForms") + + return queryPluralForms(dbFile.path, pluralForms) + } + + private fun queryPluralForms( + dbPath: String, + pluralForms: List, + ): List { + val result = mutableListOf() + val db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY) + + db.use { database -> + database.rawQuery("SELECT * FROM nouns", null)?.use { cursor -> + processPluralFormsCursor(cursor, pluralForms, result) + } + } + + return result + } + + private fun processPluralFormsCursor( + cursor: Cursor, + pluralForms: List, + result: MutableList, + ) { + if (!cursor.moveToFirst()) { + Log.w("MY-TAG", "Cursor is empty, no data found in 'nouns' table.") + return + } + + do { + addPluralForms(cursor, pluralForms, result) + } while (cursor.moveToNext()) + } + + private fun addPluralForms( + cursor: Cursor, + pluralForms: List, + result: MutableList, + ) { + pluralForms.forEach { pluralForm -> + val columnIndex = cursor.getColumnIndex(pluralForm) + if (columnIndex != -1) { + cursor.getString(columnIndex)?.let { result.add(it) } + } else { + Log.e("MY-TAG", "Column '$pluralForm' not found in the database.") + } + } + } +} diff --git a/app/src/main/java/be/scri/models/DataContract.kt b/app/src/main/java/be/scri/models/DataContract.kt new file mode 100644 index 00000000..659db0a1 --- /dev/null +++ b/app/src/main/java/be/scri/models/DataContract.kt @@ -0,0 +1,29 @@ +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class DataContract( + val numbers: Map, + val genders: Genders, + val conjugations: Map, +) + +@Serializable +data class Genders( + val canonical: List, + val feminines: List, + val masculines: List, + val commons: List, + val neuters: List, +) + +@Serializable +data class Conjugation( + val title: String = "", + @SerialName("1") val firstPerson: Map? = null, + @SerialName("2") val secondPerson: Map? = null, + @SerialName("3") val thirdPersonSingular: Map? = null, + @SerialName("4") val firstPersonPlural: Map? = null, + @SerialName("5") val secondPersonPlural: Map? = null, + @SerialName("6") val thirdPersonPlural: Map? = null, +) diff --git a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt index c9017c17..d8a5e861 100644 --- a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt @@ -101,7 +101,7 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord) } else -> { @@ -118,7 +118,9 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) + + Log.i("MY-TAG", "$checkIfPluralWord") Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/java/be/scri/services/FrenchKeyboardIME.kt b/app/src/main/java/be/scri/services/FrenchKeyboardIME.kt index e430fad8..e42143ee 100644 --- a/app/src/main/java/be/scri/services/FrenchKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/FrenchKeyboardIME.kt @@ -97,7 +97,7 @@ class FrenchKeyboardIME : GeneralKeyboardIME("French") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -114,7 +114,8 @@ class FrenchKeyboardIME : GeneralKeyboardIME("French") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt b/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt index 02612029..9e9fdc2d 100644 --- a/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt @@ -85,15 +85,21 @@ abstract class GeneralKeyboardIME( private var emojiSpaceTablet2: View? = null private var emojiBtnTablet3: Button? = null - // How quickly do we have to doubletap shift to enable permanent caps lock. + private var genderSuggestionLeft: Button? = null + private var genderSuggestionRight: Button? = null + private var isSingularAndPlural: Boolean = false + + // How quickly do we have to double-tap shift to enable permanent caps lock. private val shiftPermToggleSpeed: Int = DEFAULT_SHIFT_PERM_TOGGLE_SPEED private lateinit var dbHelper: DatabaseHelper lateinit var emojiKeywords: HashMap> - lateinit var nounKeywords: HashMap> + lateinit var nounKeywords: HashMap> + lateinit var pluralWords: List var isAutoSuggestEnabled: Boolean = false var lastWord: String? = null var autosuggestEmojis: MutableList? = null - var nounTypeSuggestion: MutableList? = null + var nounTypeSuggestion: List? = null + var checkIfPluralWord: Boolean = false private var currentEnterKeyType: Int? = null // abstract var keyboardViewKeyboardBinding : KeyboardViewKeyboardBinding @@ -226,7 +232,6 @@ abstract class GeneralKeyboardIME( else -> switchToToolBar() } updateEnterKeyColor(isUserDarkMode) -// updateCloseButtonColor(isUserDarkMode) } private fun switchToToolBar() { @@ -376,6 +381,8 @@ abstract class GeneralKeyboardIME( emojiBtnTablet2 = binding.emojiBtnTablet2 emojiSpaceTablet2 = binding.emojiSpaceTablet2 emojiBtnTablet3 = binding.emojiBtnTablet3 + genderSuggestionLeft = binding.translateBtnLeft + genderSuggestionRight = binding.translateBtnRight } fun updateButtonVisibility(isAutoSuggestEnabled: Boolean) { @@ -428,23 +435,48 @@ abstract class GeneralKeyboardIME( return null } - fun findNounTypeForLastWord( - nounKeywords: HashMap>, + fun findGenderForLastWord( + nounKeywords: HashMap>, lastWord: String?, - ): MutableList? { + ): List? { lastWord?.let { word -> val lowerCaseWord = word.lowercase() - val nouns = nounKeywords[lowerCaseWord] - if (nouns != null) { - Log.d("Debug", "Noun Types for '$word': $nouns") - return nouns + Log.i("MY-TAG", word) + Log.i("MY-TAG", nounKeywords.keys.toString()) + Log.i("MY-TAG", nounKeywords[word].toString()) + val gender = nounKeywords[lowerCaseWord] + if (gender != null) { + Log.d("Debug", "Gender for '$word': $gender") + Log.i("MY-TAG", pluralWords.contains(lastWord).toString()) + if (pluralWords.any { it.equals(lastWord, ignoreCase = true) }) { + Log.i("MY-TAG", "Plural Words : $pluralWords") + isSingularAndPlural = true + Log.i("MY-TAG", "isSingularPlural Updated to true") + } else { + isSingularAndPlural = false + Log.i("MY-TAG", "Plural Words : $pluralWords") + Log.i("MY-TAG", "isSingularPlural Updated to false") + } + return gender } else { - Log.d("Debug", "No nouns found for '$word'") + Log.d("Debug", "No gender found for '$word'") } } return null } + fun findWheatherWordIsPlural( + pluralWords: List, + lastWord: String?, + ): Boolean { + for (item in pluralWords) { + if (item == lastWord) { + return true + } + } + return false + } + fun updateButtonText( isAutoSuggestEnabled: Boolean, autosuggestEmojis: MutableList?, @@ -466,30 +498,119 @@ abstract class GeneralKeyboardIME( } } - fun updateAutoSuggestText(nounTypeSuggestion: MutableList?) { + fun updateAutoSuggestText( + nounTypeSuggestion: List? = null, + isPlural: Boolean = false, + ) { + if (isPlural) { + var(colorRes, text) = handleColorAndTextForNounType(nounType = "PL") + text = "PL" + colorRes = R.color.annotateOrange + binding.translateBtnLeft.visibility = View.INVISIBLE + binding.translateBtnRight.visibility = View.INVISIBLE + binding.translateBtn.apply { + visibility = View.VISIBLE + binding.translateBtn.text = text + textSize = NOUN_TYPE_SIZE + background = + ContextCompat.getDrawable(context, R.drawable.rounded_drawable)?.apply { + setTintMode(PorterDuff.Mode.SRC_IN) + setTint(ContextCompat.getColor(context, colorRes)) + } + } + } else { + nounTypeSuggestion?.size?.let { + if (it > 1 || isSingularAndPlural) { + handleMultipleNounFormats(nounTypeSuggestion) + } else { + handleSingleType(nounTypeSuggestion) + } + } + } + } + + fun handleSingleType(nounTypeSuggestion: List?) { + val text = nounTypeSuggestion?.get(0).toString() + val (colorRes, buttonText) = handleColorAndTextForNounType(text) + + binding.translateBtnLeft.visibility = View.INVISIBLE + binding.translateBtnRight.visibility = View.INVISIBLE + binding.translateBtn.apply { + visibility = View.VISIBLE + binding.translateBtn.text = buttonText + textSize = NOUN_TYPE_SIZE + background = + ContextCompat.getDrawable(context, R.drawable.rounded_drawable)?.apply { + setTintMode(PorterDuff.Mode.SRC_IN) + setTint(ContextCompat.getColor(context, colorRes)) + } + } + } + + fun handleMultipleNounFormats(nounTypeSuggestion: List?) { + binding.apply { + translateBtnLeft.visibility = View.VISIBLE + translateBtnRight.visibility = View.VISIBLE + translateBtn.visibility = View.INVISIBLE + + val (leftType, rightType) = + if (isSingularAndPlural) { + "PL" to nounTypeSuggestion?.get(0).toString() + } else { + nounTypeSuggestion?.get(0).toString() to nounTypeSuggestion?.get(1).toString() + } + + handleColorAndTextForNounType(leftType).let { (colorRes, text) -> + translateBtnLeft.text = text + translateBtnLeft.background = + ContextCompat + .getDrawable( + applicationContext, + R.drawable.gender_suggestion_button_left_background, + )?.apply { + setTintMode(PorterDuff.Mode.SRC_IN) + setTint(ContextCompat.getColor(applicationContext, colorRes)) + } + } + + handleColorAndTextForNounType(rightType).let { (colorRes, text) -> + translateBtnRight.text = text + translateBtnRight.background = + ContextCompat + .getDrawable( + applicationContext, + R.drawable.gender_suggestion_button_right_background, + )?.apply { + setTintMode(PorterDuff.Mode.SRC_IN) + setTint(ContextCompat.getColor(applicationContext, colorRes)) + } + } + } + } + + fun handleColorAndTextForNounType(nounType: String): Pair { val suggestionMap = mapOf( "PL" to Pair(R.color.annotateOrange, "PL"), - "N" to Pair(R.color.annotateGreen, "N"), - "C" to Pair(R.color.annotatePurple, "C"), - "M" to Pair(R.color.annotateBlue, "M"), - "F" to Pair(R.color.annotateRed, "F"), + "neuter" to Pair(R.color.annotateGreen, "N"), + "common of two genders" to Pair(R.color.annotatePurple, "C"), + "common" to Pair(R.color.annotatePurple, "C"), + "masculine" to Pair(R.color.annotateBlue, "M"), + "feminine" to Pair(R.color.annotateRed, "F"), ) - - val (colorRes, text) = - suggestionMap[nounTypeSuggestion?.getOrNull(0)] + var (colorRes, text) = + suggestionMap[nounType] ?: Pair(R.color.transparent, "Suggestion") - - binding.translateBtn.text = text - val drawable = ContextCompat.getDrawable(this, R.drawable.rounded_drawable) - drawable?.setTintMode(PorterDuff.Mode.SRC_IN) - drawable?.setTint(ContextCompat.getColor(this, colorRes)) - binding.translateBtn.background = drawable + return Pair(colorRes, text) } fun disableAutoSuggest() { + binding.translateBtnRight.visibility = View.INVISIBLE + binding.translateBtnLeft.visibility = View.INVISIBLE + binding.translateBtn.visibility = View.VISIBLE binding.translateBtn.text = "Suggestion" binding.translateBtn.setBackgroundColor(getColor(R.color.transparent)) + binding.translateBtn.textSize = SUGGESTION_SIZE } private fun insertEmoji(emoji: String) { @@ -532,8 +653,10 @@ abstract class GeneralKeyboardIME( dbHelper = DatabaseHelper(this) dbHelper.loadDatabase(languageAlias) emojiKeywords = dbHelper.getEmojiKeywords(languageAlias) - nounKeywords = dbHelper.getNounKeywords(languageAlias) + pluralWords = dbHelper.checkIfWordIsPlural(languageAlias)!! + nounKeywords = dbHelper.findGenderOfWord(languageAlias) + Log.i("MY-TAG", nounKeywords.toString()) keyboard = KeyboardBase(this, keyboardXml, enterKeyType) keyboardView?.setKeyboard(keyboard!!) } @@ -822,5 +945,7 @@ abstract class GeneralKeyboardIME( private companion object { const val DEFAULT_SHIFT_PERM_TOGGLE_SPEED = 500 const val TEXT_LENGTH = 20 + const val NOUN_TYPE_SIZE = 25f + const val SUGGESTION_SIZE = 15f } } diff --git a/app/src/main/java/be/scri/services/GermanKeyboardIME.kt b/app/src/main/java/be/scri/services/GermanKeyboardIME.kt index 64600da1..536937a3 100644 --- a/app/src/main/java/be/scri/services/GermanKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/GermanKeyboardIME.kt @@ -105,7 +105,7 @@ class GermanKeyboardIME : GeneralKeyboardIME("German") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -122,9 +122,10 @@ class GermanKeyboardIME : GeneralKeyboardIME("German") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") - Log.d("MY-TAG", "$nounTypeSuggestion") + updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) if (code != KeyboardBase.KEYCODE_SHIFT) { super.updateShiftKeyState() diff --git a/app/src/main/java/be/scri/services/ItalianKeyboardIME.kt b/app/src/main/java/be/scri/services/ItalianKeyboardIME.kt index 44e1a375..e98295e9 100644 --- a/app/src/main/java/be/scri/services/ItalianKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/ItalianKeyboardIME.kt @@ -97,7 +97,7 @@ class ItalianKeyboardIME : GeneralKeyboardIME("Italian") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -114,7 +114,8 @@ class ItalianKeyboardIME : GeneralKeyboardIME("Italian") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/java/be/scri/services/PortugueseKeyboardIME.kt b/app/src/main/java/be/scri/services/PortugueseKeyboardIME.kt index cb9e2df8..9d2d0a30 100644 --- a/app/src/main/java/be/scri/services/PortugueseKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/PortugueseKeyboardIME.kt @@ -97,7 +97,7 @@ class PortugueseKeyboardIME : GeneralKeyboardIME("Portuguese") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -114,7 +114,8 @@ class PortugueseKeyboardIME : GeneralKeyboardIME("Portuguese") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/java/be/scri/services/RussianKeyboardIME.kt b/app/src/main/java/be/scri/services/RussianKeyboardIME.kt index 424bf7c3..78585481 100644 --- a/app/src/main/java/be/scri/services/RussianKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/RussianKeyboardIME.kt @@ -97,7 +97,7 @@ class RussianKeyboardIME : GeneralKeyboardIME("Russian") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -114,7 +114,8 @@ class RussianKeyboardIME : GeneralKeyboardIME("Russian") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/java/be/scri/services/SpanishKeyboardIME.kt b/app/src/main/java/be/scri/services/SpanishKeyboardIME.kt index 4476114c..3a2b456a 100644 --- a/app/src/main/java/be/scri/services/SpanishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/SpanishKeyboardIME.kt @@ -101,7 +101,7 @@ class SpanishKeyboardIME : GeneralKeyboardIME("Spanish") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -118,7 +118,8 @@ class SpanishKeyboardIME : GeneralKeyboardIME("Spanish") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/java/be/scri/services/SwedishKeyboardIME.kt b/app/src/main/java/be/scri/services/SwedishKeyboardIME.kt index 88dd2953..effdaa25 100644 --- a/app/src/main/java/be/scri/services/SwedishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/SwedishKeyboardIME.kt @@ -101,7 +101,7 @@ class SwedishKeyboardIME : GeneralKeyboardIME("Swedish") { KeyboardBase.KEYCODE_SPACE -> { handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(nounTypeSuggestion) + updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) } else -> { @@ -118,7 +118,8 @@ class SwedishKeyboardIME : GeneralKeyboardIME("Swedish") { lastWord = getLastWordBeforeCursor() Log.d("Debug", "$lastWord") autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - nounTypeSuggestion = findNounTypeForLastWord(nounKeywords, lastWord) + nounTypeSuggestion = findGenderForLastWord(nounKeywords, lastWord) + checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) Log.d("Debug", "$autosuggestEmojis") Log.d("MY-TAG", "$nounTypeSuggestion") updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) diff --git a/app/src/main/res/layout/keyboard_view_command_options.xml b/app/src/main/res/layout/keyboard_view_command_options.xml index eded1757..4fad5248 100644 --- a/app/src/main/res/layout/keyboard_view_command_options.xml +++ b/app/src/main/res/layout/keyboard_view_command_options.xml @@ -53,6 +53,44 @@ app:layout_constraintStart_toEndOf="@+id/separator_1" app:layout_constraintTop_toTopOf="@+id/command_field" /> +