Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR for New UI changes #2

Merged
merged 25 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ android {
lint {
abortOnError true
}
buildFeatures {
viewBinding true
}
}

dependencies {
Expand All @@ -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'
Expand All @@ -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")
}
6 changes: 3 additions & 3 deletions app/src/debug/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
SPDX-License-Identifier: GPL-3.0-only
-->
<resources>
<string name="english_ime_name" translatable="false">HeliBoard debug</string>
<string name="spell_checker_service_name" translatable="false">HeliBoard debug Spell Checker</string>
<string name="ime_settings" translatable="false">HeliBoard debug Settings</string>
<string name="english_ime_name" translatable="false">Oscar AI Keyboard</string>
<string name="spell_checker_service_name" translatable="false">Oscar debug Spell Checker</string>
<string name="ime_settings" translatable="false">Oscar debug Settings</string>

</resources>
35 changes: 30 additions & 5 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only

<application android:label="@string/english_ime_name"
android:name="helium314.keyboard.latin.App"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:allowBackup="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<!-- Services -->
<service android:name="LatinIME"
android:label="@string/english_ime_name"
Expand All @@ -48,7 +54,6 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
<!-- Activities -->
<activity android:name=".setup.SetupActivity"
android:theme="@style/platformActivityTheme"
android:icon="@mipmap/ic_launcher"
android:launchMode="singleTask"
android:noHistory="true"
android:exported="true">
Expand Down Expand Up @@ -99,7 +104,27 @@ SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>

<activity
android:name=".setup.MainActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/AppTheme"/>
<activity
android:name=".setup.KeyboardselectionActivity"
android:exported="false"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize"
android:theme="@style/AppTheme"/>
<activity
android:name=".setup.PrivacyPolicyActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/AppTheme"/>
<activity
android:name=".setup.TermsOfUseActivity"
android:exported="false"
android:label="@string/app_name"
android:theme="@style/AppTheme"/>
<!-- Broadcast receivers -->
<receiver android:name="SystemBroadcastReceiver"
android:exported="true">
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/helium314/keyboard/AIEngine/AIState.kt
Original file line number Diff line number Diff line change
@@ -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(),
)
47 changes: 47 additions & 0 deletions app/src/main/java/helium314/keyboard/AIEngine/SummarizeUiState.kt
Original file line number Diff line number Diff line change
@@ -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
}
108 changes: 108 additions & 0 deletions app/src/main/java/helium314/keyboard/AIEngine/SummarizeViewModel.kt
Original file line number Diff line number Diff line change
@@ -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<AIState> = _state.asStateFlow()


private val _aiState = MutableLiveData<AIState>()
val replyData: LiveData<AIState>
get() = _aiState

private val _isAICorrecting = MutableLiveData<Boolean>()
val isAICorrecting: LiveData<Boolean>
get() = _isAICorrecting

private val _uiState: MutableStateFlow<SummarizeUiState> =
MutableStateFlow(SummarizeUiState.Initial)
val uiState: StateFlow<SummarizeUiState> =
_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 ?: "")
// }
// }
// }

}
Original file line number Diff line number Diff line change
@@ -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 <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SummarizeViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return SummarizeViewModel( generativeModel) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Original file line number Diff line number Diff line change
@@ -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<TextView>(R.id.text_view_instruction)
textViewInstruction.text = spannableString

val buttonEnable = view.findViewById<Button>(R.id.enableId)
buttonEnable.setOnClickListener {
// Open the system settings to enable the keyboard
startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS))
}

return view
}

}
Loading