Skip to content

Commit

Permalink
Merge pull request #5 from Parabox-App/develop
Browse files Browse the repository at this point in the history
1.0.8-beta
  • Loading branch information
ojhdt authored Dec 10, 2022
2 parents 1bd26e8 + 44ad3bb commit 1cf9900
Show file tree
Hide file tree
Showing 56 changed files with 2,769 additions and 738 deletions.
20 changes: 13 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ android {
applicationId "com.ojhdtapp.parabox"
minSdk 26
targetSdk 33
versionCode 9
versionName "1.0.7-beta"
versionCode 10
versionName "1.0.8-beta"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down Expand Up @@ -61,6 +61,9 @@ android {
lintOptions {
abortOnError false
}
aaptOptions {
noCompress "tflite"
}
applicationVariants.all { variant ->
kotlin.sourceSets {
getByName(variant.name) {
Expand Down Expand Up @@ -89,7 +92,7 @@ dependencies {
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "com.google.android.material:material:1.8.0-alpha02"
implementation "com.google.android.material:material:1.8.0-alpha03"

// Firebase
implementation platform('com.google.firebase:firebase-bom:31.0.1')
Expand Down Expand Up @@ -128,6 +131,9 @@ dependencies {

// ML-Kit
implementation 'com.google.mlkit:entity-extraction:16.0.0-beta4'
implementation 'com.google.mlkit:smart-reply:17.0.2'
implementation 'com.google.mlkit:translate:17.0.1'
implementation 'com.google.mlkit:language-id:17.0.4'

// Extended Gestures
implementation 'com.github.SmartToolFactory:Compose-Extended-Gestures:2.0.0'
Expand All @@ -139,7 +145,7 @@ dependencies {
implementation "commons-io:commons-io:2.7"

// Development Kit
implementation 'com.ojhdt:parabox-development-kit:1.0.5'
implementation 'com.ojhdt:parabox-development-kit:1.0.13-SNAPSHOT'

// Paging
def paging_version = "3.2.0-alpha03"
Expand Down Expand Up @@ -180,8 +186,8 @@ dependencies {
implementation "androidx.navigation:navigation-compose:$nav_version"

// m3
implementation "androidx.compose.material3:material3:1.1.0-alpha02"
implementation "androidx.compose.material3:material3-window-size-class:1.1.0-alpha02"
implementation "androidx.compose.material3:material3:1.1.0-alpha03"
implementation "androidx.compose.material3:material3-window-size-class:1.1.0-alpha03"

// Chrome Custom Tab
implementation "androidx.browser:browser:1.4.0"
Expand Down Expand Up @@ -211,7 +217,7 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

// Room
def room_version = "2.5.0-beta02"
def room_version = "2.5.0-rc01"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
<intent>
<action android:name="com.ojhdtapp.parabox.PLUGIN" />
</intent>
<intent>
<action android:name="android.intent.action.INSERT" />
<data android:mimeType="vnd.android.cursor.dir/event" />
</intent>
</queries>

<application
Expand Down
195 changes: 177 additions & 18 deletions app/src/main/java/com/ojhdtapp/parabox/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
Expand Down Expand Up @@ -72,21 +73,23 @@ import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderF
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.google.firebase.messaging.FirebaseMessaging
import com.ojhdtapp.parabox.core.util.BrowserUtil
import com.ojhdtapp.parabox.core.util.DataStoreKeys
import com.ojhdtapp.parabox.core.util.DownloadManagerUtil
import com.ojhdtapp.parabox.core.util.FileUtil
import com.ojhdtapp.parabox.core.util.GoogleDriveUtil
import com.ojhdtapp.parabox.core.util.NotificationUtil
import com.ojhdtapp.parabox.core.util.dataStore
import com.ojhdtapp.parabox.core.util.toDateAndTimeString
import com.google.mlkit.common.model.DownloadConditions
import com.google.mlkit.nl.entityextraction.*
import com.google.mlkit.nl.languageid.LanguageIdentification
import com.google.mlkit.nl.smartreply.*
import com.google.mlkit.nl.translate.TranslateLanguage
import com.google.mlkit.nl.translate.Translation
import com.google.mlkit.nl.translate.Translator
import com.google.mlkit.nl.translate.TranslatorOptions
import com.ojhdtapp.parabox.core.util.*
import com.ojhdtapp.parabox.data.local.AppDatabase
import com.ojhdtapp.parabox.data.local.entity.DownloadingState
import com.ojhdtapp.parabox.data.remote.dto.saveLocalResourcesToCloud
import com.ojhdtapp.parabox.domain.fcm.FcmApiHelper
import com.ojhdtapp.parabox.domain.fcm.FcmConstants
import com.ojhdtapp.parabox.domain.model.AppModel
import com.ojhdtapp.parabox.domain.model.File
import com.ojhdtapp.parabox.domain.model.message_content.getContentString
import com.ojhdtapp.parabox.domain.service.PluginListListener
import com.ojhdtapp.parabox.domain.service.PluginService
import com.ojhdtapp.parabox.domain.use_case.GetContacts
Expand All @@ -110,18 +113,17 @@ import com.ramcosta.composedestinations.animations.rememberAnimatedNavHostEngine
import com.ramcosta.composedestinations.navigation.dependency
import dagger.hilt.android.AndroidEntryPoint
import de.raphaelebner.roomdatabasebackup.core.RoomBackup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import linc.com.amplituda.Amplituda
import linc.com.amplituda.Compress
import java.io.IOException
import javax.inject.Inject
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlin.math.abs
import kotlin.math.roundToInt

Expand Down Expand Up @@ -182,6 +184,10 @@ class MainActivity : AppCompatActivity() {
private lateinit var backupLocationSelector: ActivityResultLauncher<String>
private lateinit var restoreLocationSelector: ActivityResultLauncher<Array<String>>

// ML
private var entityExtractor: EntityExtractor? = null
private var smartReplyGenerator: SmartReplyGenerator? = null

private fun openFile(file: File) {
file.downloadPath?.let {
val path = java.io.File(
Expand Down Expand Up @@ -282,7 +288,7 @@ class MainActivity : AppCompatActivity() {
start()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: IllegalStateException){
} catch (e: IllegalStateException) {
e.printStackTrace()
}
}
Expand Down Expand Up @@ -768,15 +774,15 @@ class MainActivity : AppCompatActivity() {
}
}

private fun queryConfigFromFireStore(){
private fun queryConfigFromFireStore() {
val db = Firebase.firestore
db.collection("config").get().addOnSuccessListener { result ->
if (result != null) {
val config = result.documents.firstOrNull()?.data

val fcm_url = config?.get("fcm_url")?.toString()
Log.d("parabox", "fcm_url: $fcm_url")
fcm_url?.let{
fcm_url?.let {
lifecycleScope.launch {
dataStore.edit { settings ->
settings[DataStoreKeys.SETTINGS_FCM_OFFICIAL_URL] = it
Expand All @@ -791,6 +797,35 @@ class MainActivity : AppCompatActivity() {
}
}

private fun initializeMLKit() {
lifecycleScope.launch {
val isEntityExtractionEnabled =
dataStore.data.first()[DataStoreKeys.SETTINGS_ML_KIT_ENTITY_EXTRACTION] ?: true
val isSmartReplyEnabled =
dataStore.data.first()[DataStoreKeys.SETTINGS_ML_KIT_SMART_REPLY] ?: true
val isTranslationEnabled =
dataStore.data.first()[DataStoreKeys.SETTINGS_ML_KIT_TRANSLATION] ?: true
if (isEntityExtractionEnabled) {
val tempEntityExtractor =
EntityExtraction.getClient(
EntityExtractorOptions.Builder(
AppCompatDelegate.getApplicationLocales()[0]?.toLanguageTag()?.let {
EntityExtractorOptions.fromLanguageTag(it)
} ?: EntityExtractorOptions.ENGLISH
).build())
tempEntityExtractor
.downloadModelIfNeeded()
.addOnSuccessListener { _ ->
entityExtractor = tempEntityExtractor
lifecycle.addObserver(entityExtractor!!)
}
}
if (isSmartReplyEnabled) {
smartReplyGenerator = SmartReply.getClient()
}
}
}

fun getGoogleLoginAuth(): GoogleSignInClient {
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
Expand All @@ -817,6 +852,124 @@ class MainActivity : AppCompatActivity() {
}
}

// ML
suspend fun getEntityAnnotationList(str: String): List<EntityAnnotation> {
return suspendCoroutine<List<EntityAnnotation>> { cot ->
Log.d("parabox", "getEntityAnnotationList: $str")
if (entityExtractor == null) cot.resume(emptyList<EntityAnnotation>())
else {
val params = EntityExtractionParams.Builder(str).build()
entityExtractor!!.annotate(params)
.addOnSuccessListener { result ->
cot.resume(result)
}
.addOnFailureListener {
it.printStackTrace()
cot.resumeWithException(it)
}
}
}
}

suspend fun getSmartReplyList(contactId: Long): List<SmartReplySuggestion> {
Log.d("parabox", "getSmartReplyList: $contactId")
if (smartReplyGenerator == null) return emptyList()
val conversation = withContext(Dispatchers.IO) {
appDatabase.messageDao.getMessagesWithLimit(listOf(contactId), 3)
.sortedBy { it.timestamp }.map {
if (it.sentByMe) {
TextMessage.createForLocalUser(it.contentString, it.timestamp)
} else {
TextMessage.createForRemoteUser(
it.contentString,
it.timestamp,
it.profile.name
)
}
}
}
return suspendCoroutine<List<SmartReplySuggestion>> { cot ->
Log.d("parabox", "getSmartReplyList: ${conversation.last().messageText}")
smartReplyGenerator!!.suggestReplies(conversation)
.addOnSuccessListener { result ->
if (result.status == SmartReplySuggestionResult.STATUS_NOT_SUPPORTED_LANGUAGE) {
cot.resume(emptyList())
} else if (result.status == SmartReplySuggestionResult.STATUS_SUCCESS) {
if (conversation.lastOrNull()?.isLocalUser == true) {
cot.resume(emptyList())
} else {
cot.resume(result.suggestions)
}
}
}
.addOnFailureListener {
it.printStackTrace()
cot.resumeWithException(it)
}
}
}

suspend fun getTranslation(originalText: String): String? {
return try {
val languageCode = getLanguageCode(originalText)
val currentLanguageTag =
AppCompatDelegate.getApplicationLocales()[0]?.toLanguageTag() ?: "en"
val options = TranslatorOptions.Builder()
.setSourceLanguage(TranslateLanguage.fromLanguageTag(languageCode)!!)
.setTargetLanguage(
TranslateLanguage.fromLanguageTag(
LanguageUtil.languageTagMapper(currentLanguageTag)
)!!
)
.build()
val conditions = DownloadConditions.Builder()
.requireWifi()
.build()
return suspendCoroutine { cot ->
val translator = Translation.getClient(options)
translator.downloadModelIfNeeded(conditions)
.addOnSuccessListener {
Log.d("parabox", "downloadModelIfNeeded: success")
translator.translate(originalText)
.addOnSuccessListener { translatedText ->
Log.d("parabox", "translated: $translatedText")
cot.resume(translatedText)
}
.addOnFailureListener {
it.printStackTrace()
cot.resumeWithException(it)
}.addOnCompleteListener {
translator.close()
}
}
.addOnFailureListener {
Log.d("parabox", "downloadModelIfNeeded: failed")
cot.resumeWithException(it)
}
}
} catch (e: Exception) {
e.printStackTrace()
null
}
}

suspend fun getLanguageCode(str: String): String {
return suspendCoroutine<String> { cot ->
val languageIdentifier = LanguageIdentification.getClient()
languageIdentifier.identifyLanguage(str)
.addOnSuccessListener { languageCode ->
if (languageCode == "und") {
cot.resume("en")
} else {
cot.resume(languageCode)
}
}
.addOnFailureListener {
cot.resume("en")
}
}
}

// Event
fun onEvent(event: ActivityEvent) {
when (event) {
Expand Down Expand Up @@ -848,13 +1001,13 @@ class MainActivity : AppCompatActivity() {
timestamp,
event.sendType
).also {

val dto = SendMessageDto(
contents = event.contents,
timestamp = timestamp,
pluginConnection = event.pluginConnection,
messageId = it
)

val enableFcm =
dataStore.data.first()[DataStoreKeys.SETTINGS_ENABLE_FCM] ?: false
val fcmRole = dataStore.data.first()[DataStoreKeys.SETTINGS_FCM_ROLE]
Expand All @@ -868,7 +1021,9 @@ class MainActivity : AppCompatActivity() {
val dtoWithoutUri = when {
fcmCloudStorage == FcmConstants.CloudStorage.GOOGLE_DRIVE.ordinal -> {
dto.copy(
contents = dto.contents.saveLocalResourcesToCloud(baseContext)
contents = dto.contents.saveLocalResourcesToCloud(
baseContext
)
)
}

Expand Down Expand Up @@ -1191,6 +1346,10 @@ class MainActivity : AppCompatActivity() {
// Query FireStore
queryConfigFromFireStore()

// ML-Kit
initializeMLKit()


WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
// System Ui
Expand Down
Loading

0 comments on commit 1cf9900

Please sign in to comment.