diff --git a/app/build.gradle b/app/build.gradle
index 366f98b87..6bc70aa1a 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -91,6 +91,9 @@ android {
lint {
abortOnError true
}
+ buildFeatures {
+ viewBinding true
+ }
}
dependencies {
@@ -107,6 +110,8 @@ dependencies {
// color picker for user-defined colors
implementation 'com.github.martin-stone:hsv-alpha-color-picker-android:3.1.0'
+ implementation 'androidx.activity:activity:1.9.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
// test
testImplementation 'junit:junit:4.13.2'
@@ -115,4 +120,14 @@ dependencies {
testImplementation 'org.robolectric:robolectric:4.12.1'
testImplementation 'androidx.test:runner:1.5.2'
testImplementation 'androidx.test:core:1.5.0'
+
+ // Generative AI
+ implementation("com.google.ai.client.generativeai:generativeai:0.9.0")
+
+ //multiple bottom sheets
+ implementation ("com.roshaan.multiplebottomsheets:multiplebottomsheets:1.0.1")
+ implementation ("com.google.android.material:material:1.12.0")
+ // Rich Editor
+
+ implementation("com.mohamedrejeb.richeditor:richeditor-compose:1.0.0-rc05")
}
diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml
index e8755c20a..124bd90df 100644
--- a/app/src/debug/res/values/strings.xml
+++ b/app/src/debug/res/values/strings.xml
@@ -3,8 +3,8 @@
SPDX-License-Identifier: GPL-3.0-only
-->
- HeliBoard debug
- HeliBoard debug Spell Checker
- HeliBoard debug Settings
+ Oscar AI Keyboard
+ Oscar debug Spell Checker
+ Oscar debug Settings
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f0cee5671..86e800285 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -15,8 +15,6 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
@@ -99,7 +96,26 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
-
+
+
+
+
diff --git a/app/src/main/java/helium314/keyboard/AIEngine/AIState.kt b/app/src/main/java/helium314/keyboard/AIEngine/AIState.kt
new file mode 100644
index 000000000..65c517c64
--- /dev/null
+++ b/app/src/main/java/helium314/keyboard/AIEngine/AIState.kt
@@ -0,0 +1,9 @@
+package helium314.keyboard.AIEngine
+
+import com.mohamedrejeb.richeditor.model.RichTextState
+
+data class AIState(
+ val isAIProcessing: Boolean = false,
+ val isAICorrecting: Boolean = false,
+ val aiText: RichTextState = RichTextState(),
+)
diff --git a/app/src/main/java/helium314/keyboard/AIEngine/SummarizeUiState.kt b/app/src/main/java/helium314/keyboard/AIEngine/SummarizeUiState.kt
new file mode 100644
index 000000000..2692afd49
--- /dev/null
+++ b/app/src/main/java/helium314/keyboard/AIEngine/SummarizeUiState.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package helium314.keyboard.AIEngine
+
+/**
+ * A sealed hierarchy describing the state of the text generation.
+ */
+sealed interface SummarizeUiState {
+
+ /**
+ * Empty state when the screen is first shown
+ */
+ data object Initial: SummarizeUiState
+
+ /**
+ * Still loading
+ */
+ data object Loading: SummarizeUiState
+
+ /**
+ * Text has been generated
+ */
+ data class Success(
+ val outputText: String
+ ): SummarizeUiState
+
+ /**
+ * There was an error generating text
+ */
+ data class Error(
+ val errorMessage: String
+ ): SummarizeUiState
+}
diff --git a/app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModel.kt b/app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModel.kt
new file mode 100644
index 000000000..353f54115
--- /dev/null
+++ b/app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModel.kt
@@ -0,0 +1,108 @@
+package helium314.keyboard.AIEngine
+
+import android.content.Context
+import android.widget.Toast
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.google.ai.client.generativeai.GenerativeModel
+import com.google.ai.client.generativeai.type.content
+import helium314.keyboard.gemini.GeminiClient
+import helium314.keyboard.latin.utils.Log
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+
+class SummarizeViewModel(
+ private val generativeModel: GenerativeModel
+) : ViewModel() {
+
+ private val _state = MutableStateFlow(AIState())
+ val state: StateFlow = _state.asStateFlow()
+
+
+ private val _aiState = MutableLiveData()
+ val replyData: LiveData
+ get() = _aiState
+
+ private val _isAICorrecting = MutableLiveData()
+ val isAICorrecting: LiveData
+ get() = _isAICorrecting
+
+ private val _uiState: MutableStateFlow =
+ MutableStateFlow(SummarizeUiState.Initial)
+ val uiState: StateFlow =
+ _uiState.asStateFlow()
+
+// fun onAICorrection(context: Context) {
+//
+// val generativeModel = geminiClient.geminiFlashModel
+//
+// val inputContent = content {
+// text("Please correct the following text for any spelling and grammatical errors, and slightly paraphrase it while keeping the original language and the markdown format:\n")
+// }
+// viewModelScope.launch {
+// try {
+// val response = generativeModel.generateContent(inputContent)
+// _state.update { it.copy(isAICorrecting = true) }
+// Toast.makeText(context, "Text Corrected With AIEngine", Toast.LENGTH_SHORT).show()
+// } catch (e: Exception) {
+// Toast.makeText(context, "Error Correcting Text With AIEngine", Toast.LENGTH_SHORT)
+// .show()
+// } finally {
+// _state.update { it.copy(isAICorrecting = false) }
+// }
+// }
+// }
+
+ fun summarizeStreaming(inputText: String) {
+ _uiState.value = SummarizeUiState.Loading
+
+ val prompt =
+ "Please correct the following text for any spelling and grammatical errors, and slightly paraphrase it while keeping the original language and the markdown format:\n: $inputText"
+
+ viewModelScope.launch {
+ try {
+ var outputContent = ""
+ generativeModel.generateContentStream(prompt)
+ .collect { response ->
+ outputContent += response.text
+ _uiState.value = SummarizeUiState.Success(outputContent)
+ Log.d("SummarizeViewModel", "outputContent: $outputContent")
+ }
+ } catch (e: Exception) {
+ _uiState.value = SummarizeUiState.Error(e.localizedMessage ?: "")
+ Log.d("SummarizeViewModel", "Error: ${e.localizedMessage}")
+ }
+ }
+ }
+
+// fun summarizeStreamingLiveData(inputText: String) {
+// //_uiState.value = SummarizeUiState.Loading
+//
+// val prompt =
+// "Please correct the following text for any spelling and grammatical errors, and slightly paraphrase it while keeping the original language and the markdown format:\n: $inputText"
+//
+// viewModelScope.launch {
+// try {
+// var outputContent = ""
+// val response = generativeModel.generateContentStream(prompt)
+// val response = AIState(prompt)
+// _aiState.postValue(response)
+//
+// //_aiState.value = generativeModel.generateContentStream(prompt)
+//
+//// .collect { response ->
+//// outputContent += response.text
+//// _uiState.value = SummarizeUiState.Success(outputContent)
+//// }
+// } catch (e: Exception) {
+// _uiState.value = SummarizeUiState.Error(e.localizedMessage ?: "")
+// }
+// }
+// }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModelFactory.kt b/app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModelFactory.kt
new file mode 100644
index 000000000..dbb1285a2
--- /dev/null
+++ b/app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModelFactory.kt
@@ -0,0 +1,20 @@
+package helium314.keyboard.AIEngine
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.google.ai.client.generativeai.GenerativeModel
+import helium314.keyboard.gemini.GeminiClient
+
+class SummarizeViewModelFactory(
+ //private val geminiClient: GeminiClient,
+ private val generativeModel: GenerativeModel
+) : ViewModelProvider.Factory {
+
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(SummarizeViewModel::class.java)) {
+ @Suppress("UNCHECKED_CAST")
+ return SummarizeViewModel( generativeModel) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
diff --git a/app/src/main/java/helium314/keyboard/bottomsheets/SheetOneFragment.kt b/app/src/main/java/helium314/keyboard/bottomsheets/SheetOneFragment.kt
new file mode 100644
index 000000000..737f9233b
--- /dev/null
+++ b/app/src/main/java/helium314/keyboard/bottomsheets/SheetOneFragment.kt
@@ -0,0 +1,65 @@
+package helium314.keyboard.bottomsheets
+
+
+import android.content.Intent
+import android.graphics.Color
+import android.graphics.Typeface
+import android.os.Bundle
+import android.text.SpannableString
+import android.text.Spanned
+import android.text.style.ForegroundColorSpan
+import android.text.style.StyleSpan
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.TextView
+import helium314.keyboard.latin.R
+import android.provider.Settings
+
+class SheetOneFragment : Fragment() {
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ var view = inflater.inflate(R.layout.fragment_sheet1, container, false)
+
+ val instructionText =
+ "Tap the toggle to enable Oscar Keyboard in \n your keyboard list"
+ val spannableString = SpannableString(instructionText)
+
+ val startIndex = instructionText.indexOf("Oscar Keyboard")
+ val endIndex = startIndex + "Oscar Keyboard".length
+
+ if (startIndex >= 0) {
+ spannableString.setSpan(
+ ForegroundColorSpan(Color.BLACK), // Set color to black
+ startIndex,
+ endIndex,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+
+ spannableString.setSpan(
+ StyleSpan(Typeface.BOLD), // Set style to bold
+ startIndex,
+ endIndex,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
+ )
+ }
+
+ val textViewInstruction = view.findViewById(R.id.text_view_instruction)
+ textViewInstruction.text = spannableString
+
+ val buttonEnable = view.findViewById