diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 158fd37d..22bf5752 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,6 +20,8 @@
+
+
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/AdaptersViewModels/ConversationsViewModel.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/AdaptersViewModels/ConversationsViewModel.kt
index f15ceb74..8e02f3e1 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/AdaptersViewModels/ConversationsViewModel.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/AdaptersViewModels/ConversationsViewModel.kt
@@ -13,14 +13,18 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import androidx.navigation.NavController
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import androidx.paging.liveData
import androidx.window.layout.WindowLayoutInfo
+import com.afkanerd.deku.ConversationsScreen
import com.afkanerd.deku.Datastore
+import com.afkanerd.deku.DefaultSMS.Commons.Helpers
import com.afkanerd.deku.DefaultSMS.Models.Conversations.Conversation
+import com.afkanerd.deku.DefaultSMS.Models.Conversations.ThreadedConversationsHandler
import com.afkanerd.deku.DefaultSMS.Models.NativeSMSDB
import com.afkanerd.deku.DefaultSMS.Models.SMSDatabaseWrapper
import com.afkanerd.deku.DefaultSMS.Models.ThreadsConfigurations
@@ -38,22 +42,18 @@ import kotlinx.serialization.json.Json
class ConversationsViewModel : ViewModel() {
-// var threadId by mutableStateOf("")
-// var address by mutableStateOf("")
-// var text by mutableStateOf("")
-// var searchQuery by mutableStateOf("")
-// var subscriptionId: Int by mutableIntStateOf(-1)
-
- var threadId = ""
- var address = ""
- var text = ""
- var searchQuery = ""
- var subscriptionId = -1
+ var threadId by mutableStateOf("")
+ var address by mutableStateOf("")
+ var text by mutableStateOf("")
+ var encryptedText by mutableStateOf("")
+ var searchQuery by mutableStateOf("")
+ var subscriptionId: Int by mutableIntStateOf(-1)
var importDetails by mutableStateOf("")
var selectedItems = mutableStateListOf()
var retryDeleteItem: MutableList = arrayListOf()
+ var selectedMessage: Conversation? = null
var liveData: LiveData>? = null
var remoteListenersLiveData: LiveData>? = null
@@ -475,4 +475,69 @@ class ConversationsViewModel : ViewModel() {
Telephony.Sms.MESSAGE_TYPE_DRAFT
Datastore.getDatastore(context).conversationDao().deleteEvery()
}
+
+ fun getMessage(context: Context, messageId: String): Conversation {
+ return Datastore.getDatastore(context).conversationDao().getMessage(messageId)
+ }
+
+ fun processIntents(
+ context: Context,
+ intent: Intent,
+ defaultRegion: String,
+ ): Triple?{
+ if(intent.action != null &&
+ ((intent.action == Intent.ACTION_SENDTO) || (intent.action == Intent.ACTION_SEND))) {
+ val text = if(intent.hasExtra("sms_body")) intent.getStringExtra("sms_body")
+ else if(intent.hasExtra("android.intent.extra.TEXT")) {
+ intent.getStringExtra("android.intent.extra.TEXT")
+ } else ""
+
+ val sendToString = intent.dataString
+
+ if ((sendToString != null &&
+ (sendToString.contains("smsto:") ||
+ sendToString.contains("sms:"))) || intent.hasExtra("address")
+ ) {
+ val address = Helpers.getFormatCompleteNumber(
+ if(intent.hasExtra("address")) intent.getStringExtra("address")
+ else sendToString, defaultRegion
+ )
+ val threadId = ThreadedConversationsHandler.get(context, address).thread_id
+ return Triple(address, threadId, text)
+ }
+ }
+ else if(intent.hasExtra("address")) {
+ var text = if(intent.hasExtra("android.intent.extra.TEXT"))
+ intent.getStringExtra("android.intent.extra.TEXT") else ""
+
+ val address = intent.getStringExtra("address")
+ val threadId = intent.getStringExtra("thread_id")
+ return Triple(address, threadId, text)
+ }
+ return null
+ }
+
+ fun navigateToConversation(
+ conversationsViewModel: ConversationsViewModel,
+ address: String,
+ threadId: String,
+ subscriptionId: Int?,
+ navController: NavController,
+ searchQuery: String? = ""
+ ) {
+ conversationsViewModel.address = address
+ conversationsViewModel.threadId = threadId
+ conversationsViewModel.searchQuery = searchQuery ?: ""
+ conversationsViewModel.subscriptionId = subscriptionId ?: -1
+ conversationsViewModel.liveData = null
+ if(conversationsViewModel.newLayoutInfo?.displayFeatures!!.isEmpty())
+ navController.navigate(ConversationsScreen)
+ }
+
+ fun loadNatives(context: Context, conversationViewModel: ConversationsViewModel) {
+ CoroutineScope(Dispatchers.Default).launch {
+ conversationViewModel.reset(context)
+ }
+ }
+
}
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/Extensions/Activities.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Extensions/Activities.kt
new file mode 100644
index 00000000..3941b135
--- /dev/null
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Extensions/Activities.kt
@@ -0,0 +1,12 @@
+package com.afkanerd.deku.DefaultSMS.Extensions
+
+import android.content.Context
+import android.content.ContextWrapper
+import androidx.activity.ComponentActivity
+
+
+fun Context.getActivity(): ComponentActivity? = when (this) {
+ is ComponentActivity -> this
+ is ContextWrapper -> baseContext.getActivity()
+ else -> null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/Models/DevMode.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Models/DevMode.kt
new file mode 100644
index 00000000..99c40cf3
--- /dev/null
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Models/DevMode.kt
@@ -0,0 +1,5 @@
+package com.afkanerd.deku.DefaultSMS.Models
+
+object DevMode {
+ val viewLogCat = "viewLogCat"
+}
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/Models/Encryption.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Models/Encryption.kt
new file mode 100644
index 00000000..f337dde7
--- /dev/null
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Models/Encryption.kt
@@ -0,0 +1,16 @@
+package com.afkanerd.deku.DefaultSMS.Models
+
+open class Encryption {
+
+ var id: Int = 0
+
+ var state: ByteArray? = null
+
+ var peerPublicKey: ByteArray? = null
+
+ var publicKey: ByteArray? = null
+
+ var peerAddress: String? = null
+
+ var version: Int = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/Settings/SettingsFragment.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Settings/SettingsFragment.kt
index 73b68c46..32b0b474 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/Settings/SettingsFragment.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/Settings/SettingsFragment.kt
@@ -1,7 +1,14 @@
package com.afkanerd.deku.DefaultSMS.Settings
+import android.content.Intent
+import android.preference.Preference
import androidx.appcompat.app.AppCompatDelegate
+import androidx.navigation.fragment.NavHostFragment
+import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceFragmentCompat
+import com.afkanerd.deku.DefaultSMS.Models.DevMode
+import com.afkanerd.deku.DefaultSMS.R
+import com.afkanerd.deku.MainActivity
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(
@@ -13,6 +20,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
val languagePreference =
findPreference(getString(com.afkanerd.deku.DefaultSMS.R.string.settings_locale))
+ val devModeLogCatPreference =
+ findPreference("dev_mode")
+
languagePreference!!.onPreferenceChangeListener = object :
androidx.preference.Preference.OnPreferenceChangeListener {
override fun onPreferenceChange(
@@ -33,5 +43,20 @@ class SettingsFragment : PreferenceFragmentCompat() {
return true
}
}
+
+ devModeLogCatPreference!!.onPreferenceClickListener = object:
+ androidx.preference.Preference.OnPreferenceClickListener {
+ override fun onPreferenceClick(preference: androidx.preference.Preference): Boolean {
+ startActivity(
+ Intent(requireContext(), MainActivity::class.java).apply {
+ setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME)
+ action = Intent.ACTION_VIEW
+ putExtra("view", DevMode.viewLogCat)
+ }
+ )
+ requireActivity().finish()
+ return true
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/SettingsActivity.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/SettingsActivity.kt
index be7b6944..0a4055d2 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/SettingsActivity.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/SettingsActivity.kt
@@ -6,6 +6,8 @@ import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
+import androidx.navigation.findNavController
+import androidx.navigation.fragment.NavHostFragment
import com.afkanerd.deku.DefaultSMS.Settings.SettingsFragment
import com.afkanerd.deku.MainActivity
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/Conversations.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/Conversations.kt
index ee98badf..4d118c77 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/Conversations.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/Conversations.kt
@@ -27,36 +27,22 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.SpanStyle
-import androidx.compose.ui.text.TextLinkStyles
-import androidx.compose.ui.text.buildAnnotatedString
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.text.style.TextDecoration
-import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
-import androidx.navigation.compose.rememberNavController
import com.afkanerd.deku.DefaultSMS.AdaptersViewModels.ConversationsViewModel
import com.afkanerd.deku.DefaultSMS.Commons.Helpers
import com.afkanerd.deku.DefaultSMS.Models.Conversations.Conversation
import com.afkanerd.deku.DefaultSMS.Models.SMSHandler.sendTextMessage
-import com.afkanerd.deku.DefaultSMS.ui.Conversations
import com.example.compose.AppTheme
-import sh.calvin.autolinktext.rememberAutoLinkText
enum class ConversationPositionTypes(val value: Int) {
NORMAL(0),
@@ -467,15 +453,15 @@ fun ConversationsMainDropDownMenu(
}
}
-private fun getPredefinedType(type: Int) : PredefinedTypes? {
+private fun getPredefinedType(type: Int) : ConversationsPredefinedTypes? {
when(type) {
Telephony.Sms.MESSAGE_TYPE_OUTBOX,
Telephony.Sms.MESSAGE_TYPE_QUEUED,
Telephony.Sms.MESSAGE_TYPE_SENT -> {
- return PredefinedTypes.OUTGOING
+ return ConversationsPredefinedTypes.OUTGOING
}
Telephony.Sms.MESSAGE_TYPE_INBOX -> {
- return PredefinedTypes.INCOMING
+ return ConversationsPredefinedTypes.INCOMING
}
}
return null
@@ -590,7 +576,7 @@ fun sendSMS(
)
}
-enum class PredefinedTypes {
+enum class ConversationsPredefinedTypes {
OUTGOING,
INCOMING
}
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ConversationsComponents.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ConversationsComponents.kt
index 476a2a4d..e3401f19 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ConversationsComponents.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ConversationsComponents.kt
@@ -8,6 +8,7 @@ import android.content.Context.CLIPBOARD_SERVICE
import android.content.Intent
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
+import android.provider.Telephony
import android.telephony.SmsManager
import android.util.Base64
import android.widget.Toast
@@ -27,6 +28,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -45,6 +47,7 @@ import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Delete
+import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.outlined.SimCard
import androidx.compose.material3.BottomAppBar
@@ -57,6 +60,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.SheetValue
+import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
@@ -89,17 +93,27 @@ import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
+import androidx.navigation.compose.rememberNavController
import com.afkanerd.deku.DefaultSMS.AdaptersViewModels.ConversationsViewModel
import com.afkanerd.deku.DefaultSMS.BuildConfig
import com.afkanerd.deku.DefaultSMS.Models.Conversations.Conversation
import com.afkanerd.deku.DefaultSMS.Models.SIMHandler
import com.afkanerd.deku.DefaultSMS.R
+import com.afkanerd.deku.DefaultSMS.ui.Conversations
import com.afkanerd.deku.MainActivity
+import com.example.compose.AppTheme
import com.jakewharton.rxbinding.view.RxMenuItem.icon
+import io.getstream.avatarview.AvatarView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.nio.file.WatchEvent
+import java.text.SimpleDateFormat
+import java.time.Instant
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+import java.util.Date
+import java.util.Locale
@Preview(showBackground = true)
@Composable
@@ -295,7 +309,7 @@ fun ChatCompose(
fontSize = 12.sp,
modifier = Modifier
.align(Alignment.End)
- .padding(end=8.dp)
+ .padding(end = 8.dp)
)
}
}
@@ -450,6 +464,83 @@ fun ShortCodeAlert(
)
}
+@Composable
+fun MessageInfoAlert(
+ conversation: Conversation,
+ dismissCallback: (() -> Unit)? = null,
+) {
+ val type = stringResource(R.string.text_message_1)
+ val priority = stringResource(R.string.normal)
+ AlertDialog(
+ backgroundColor = MaterialTheme.colorScheme.secondary,
+ title = {
+ Text(
+ stringResource(R.string.message_details),
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ },
+ text = {
+ Column {
+ Text(
+ stringResource(R.string.type, type),
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ Text(
+ stringResource(R.string.priority, priority),
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ if(conversation.type == Telephony.Sms.MESSAGE_TYPE_INBOX)
+ Text(
+ stringResource(R.string.from, conversation.address ?: ""),
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ Text(
+ stringResource(
+ R.string.to, if (conversation.type == Telephony.Sms.MESSAGE_TYPE_OUTBOX)
+ conversation.address ?: ""
+ else "N/A"
+ ),
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ Text(
+ stringResource(
+ R.string.sent, if (conversation.type == Telephony.Sms.MESSAGE_TYPE_OUTBOX)
+ formatDate(conversation.date?.toLong() ?: 0L)
+ else formatDate(conversation.date_sent?.toLong() ?: 0L)
+ ),
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ if(conversation.type == Telephony.Sms.MESSAGE_TYPE_INBOX)
+ Text(
+ stringResource(
+ R.string.received,
+ formatDate(conversation.date?.toLong() ?: 0L)
+ ),
+ color = MaterialTheme.colorScheme.onSecondary
+ )
+ }
+ },
+ onDismissRequest = { dismissCallback?.invoke() },
+ confirmButton = {},
+ dismissButton = {
+ TextButton(
+ onClick = { dismissCallback?.invoke() }
+ ) {
+ Text(
+ stringResource(R.string.close),
+ color = MaterialTheme.colorScheme.tertiaryContainer
+ )
+ }
+ }
+ )
+}
+
+fun formatDate(timestamp: Long): String {
+ val date = Date(timestamp)
+ val format = SimpleDateFormat("yyyy-MM-dd HH:ss", Locale.getDefault())
+ return format.format(date)
+}
@Preview
@Composable
@@ -506,6 +597,7 @@ fun SimChooser(
fun ConversationCrudBottomBar(
viewModel: ConversationsViewModel = ConversationsViewModel(),
items: List = emptyList(),
+ onInfoRequested: (Conversation) -> Unit = {},
onCompleted: (() -> Unit)? = null,
onCancel: (() -> Unit)? = null,
) {
@@ -530,6 +622,15 @@ fun ConversationCrudBottomBar(
Spacer(Modifier.weight(1f))
if(viewModel.selectedItems.size < 2) {
+ IconButton(onClick = {
+ val conversations = items.first {
+ it.message_id in viewModel.selectedItems
+ }
+ onInfoRequested(conversations)
+ }) {
+ Icon(Icons.Filled.Info, stringResource(R.string.message_information))
+ }
+
IconButton(onClick = {
val conversation = items.firstOrNull {
it.message_id in viewModel.selectedItems
@@ -606,3 +707,17 @@ private fun shareItem(context: Context, text: String) {
context.startActivity(shareIntent)
}
+@Preview
+@Composable
+fun MessageInfoAlert_Preview() {
+ AppTheme(darkTheme = true) {
+ val conversation = Conversation()
+ conversation.address = "+2371234567"
+ conversation.date = System.currentTimeMillis().toString()
+ conversation.date_sent = System.currentTimeMillis().toString()
+ conversation.type = Telephony.Sms.MESSAGE_TYPE_INBOX
+ MessageInfoAlert(
+ conversation
+ ) {}
+ }
+}
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ThreadsConversation.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ThreadsConversation.kt
index b4969412..aa3ccd5f 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ThreadsConversation.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/Components/ThreadsConversation.kt
@@ -80,6 +80,7 @@ import coil3.compose.AsyncImage
import com.afkanerd.deku.DefaultSMS.AboutActivity
import com.afkanerd.deku.DefaultSMS.AdaptersViewModels.ConversationsViewModel
import com.afkanerd.deku.DefaultSMS.BuildConfig
+import com.afkanerd.deku.DefaultSMS.Extensions.getActivity
import com.afkanerd.deku.DefaultSMS.Extensions.toHslColor
import com.afkanerd.deku.DefaultSMS.Models.Contacts
import com.afkanerd.deku.DefaultSMS.Models.Conversations.Conversation
@@ -610,6 +611,7 @@ fun ThreadsMainDropDown(
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME)
}
)
+ context.getActivity()?.finish()
}
)
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ComposeNewMain.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ComposeNewMain.kt
index 57b0380a..32f360a7 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ComposeNewMain.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ComposeNewMain.kt
@@ -150,7 +150,7 @@ fun ComposeNewMessage(
conversationsViewModel.threadId = ThreadedConversationsHandler.get(context,
conversationsViewModel.address).thread_id
- navigateToConversation(
+ conversationsViewModel.navigateToConversation(
conversationsViewModel = conversationsViewModel,
address = conversationsViewModel.address,
threadId = conversationsViewModel.threadId,
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ConversationsMain.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ConversationsMain.kt
index 882bf086..cccb3371 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ConversationsMain.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ConversationsMain.kt
@@ -117,6 +117,7 @@ import androidx.paging.compose.itemKey
import com.afkanerd.deku.DefaultSMS.Models.Conversations.ThreadedConversationsHandler.call
import com.afkanerd.deku.DefaultSMS.ui.Components.ConvenientMethods.deriveMetaDate
import com.afkanerd.deku.DefaultSMS.ui.Components.ConversationsMainDropDownMenu
+import com.afkanerd.deku.DefaultSMS.ui.Components.MessageInfoAlert
import com.afkanerd.deku.DefaultSMS.ui.Components.getConversationType
import com.afkanerd.deku.DefaultSMS.ui.Components.sendSMS
import kotlinx.coroutines.withContext
@@ -204,12 +205,12 @@ fun Conversations(
val isShortCode = if(inPreviewMode) false else Helpers.isShortCode(viewModel.address)
val defaultRegion = if(inPreviewMode) "cm" else Helpers.getUserCountry( context )
- var encryptedText by remember { mutableStateOf("") }
var shouldPulse by remember { mutableStateOf(false) }
val pulseRateMs by remember { mutableLongStateOf(3000L) }
var rememberDeleteAlert by remember { mutableStateOf(false) }
+ var openInfoAlert by remember { mutableStateOf(false) }
LaunchedEffect(inboxMessagesItems.loadState) {
println("Checking search...")
@@ -279,7 +280,7 @@ fun Conversations(
if(isSecured) {
LaunchedEffect(viewModel.text) {
if(viewModel.text.isBlank()) {
- encryptedText = ""
+ viewModel.encryptedText = ""
shouldPulse = false
} else shouldPulse = true
}
@@ -288,7 +289,7 @@ fun Conversations(
if(shouldPulse)
coroutineScope.launch {
delay(pulseRateMs)
- encryptedText = E2EEHandler.encryptMessage(
+ viewModel.encryptedText = E2EEHandler.encryptMessage(
context = context,
text = viewModel.text,
address = viewModel.address
@@ -457,10 +458,15 @@ fun Conversations(
)
},
bottomBar = {
- if(!selectedItems.isEmpty()) {
+ if(selectedItems.isNotEmpty()) {
ConversationCrudBottomBar(
viewModel,
inboxMessagesItems.itemSnapshotList.items,
+ onInfoRequested = {
+ openInfoAlert = true
+ viewModel.selectedMessage = it
+ selectedItems.clear()
+ },
onCompleted = { selectedItems.clear() }
) {
selectedItems.clear()
@@ -519,7 +525,7 @@ fun Conversations(
) {
ChatCompose(
value = viewModel.text,
- encryptedValue = encryptedText,
+ encryptedValue = viewModel.encryptedText,
subscriptionId = viewModel.subscriptionId,
shouldPulse = shouldPulse,
simCardChooserCallback = if(dualSim) {
@@ -539,7 +545,7 @@ fun Conversations(
conversationsViewModel = viewModel
) {
viewModel.text = ""
- encryptedText = ""
+ viewModel.encryptedText = ""
viewModel.clearDraft(context)
}
}
@@ -711,10 +717,19 @@ fun Conversations(
}
if(openAlertDialog) {
- ShortCodeAlert() {
+ ShortCodeAlert {
openAlertDialog = false
}
}
+
+ if(openInfoAlert) {
+ MessageInfoAlert(
+ viewModel.selectedMessage!!
+ ) {
+ viewModel.selectedMessage = null
+ openInfoAlert = false
+ }
+ }
}
if(showFailedRetryModal) {
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/LogcatMain.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/LogcatMain.kt
new file mode 100644
index 00000000..186447eb
--- /dev/null
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/LogcatMain.kt
@@ -0,0 +1,9 @@
+package com.afkanerd.deku.DefaultSMS.ui
+
+import androidx.compose.runtime.Composable
+
+@Composable
+fun LogcatMain() {
+
+}
+
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsConversationMain.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsConversationMain.kt
index c50056e6..6baca9bd 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsConversationMain.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsConversationMain.kt
@@ -117,66 +117,6 @@ enum class InboxType(val value: Int) {
}
}
-fun processIntents(
- context: Context,
- intent: Intent,
- defaultRegion: String,
-): Triple?{
- if(intent.action != null &&
- ((intent.action == Intent.ACTION_SENDTO) || (intent.action == Intent.ACTION_SEND))) {
- val text = if(intent.hasExtra("sms_body")) intent.getStringExtra("sms_body")
- else if(intent.hasExtra("android.intent.extra.TEXT")) {
- intent.getStringExtra("android.intent.extra.TEXT")
- } else ""
-
- val sendToString = intent.dataString
-
- if ((sendToString != null &&
- (sendToString.contains("smsto:") ||
- sendToString.contains("sms:"))) || intent.hasExtra("address")
- ) {
- val address = Helpers.getFormatCompleteNumber(
- if(intent.hasExtra("address")) intent.getStringExtra("address")
- else sendToString, defaultRegion
- )
- val threadId = ThreadedConversationsHandler.get(context, address).thread_id
- return Triple(address, threadId, text)
- }
- }
- else if(intent.hasExtra("address")) {
- var text = if(intent.hasExtra("android.intent.extra.TEXT"))
- intent.getStringExtra("android.intent.extra.TEXT") else ""
-
- val address = intent.getStringExtra("address")
- val threadId = intent.getStringExtra("thread_id")
- return Triple(address, threadId, text)
- }
- return null
-}
-
-fun navigateToConversation(
- conversationsViewModel: ConversationsViewModel,
- address: String,
- threadId: String,
- subscriptionId: Int?,
- navController: NavController,
- searchQuery: String? = ""
-) {
- conversationsViewModel.address = address
- conversationsViewModel.threadId = threadId
- conversationsViewModel.searchQuery = searchQuery ?: ""
- conversationsViewModel.subscriptionId = subscriptionId ?: -1
- conversationsViewModel.liveData = null
- if(conversationsViewModel.newLayoutInfo?.displayFeatures!!.isEmpty())
- navController.navigate(ConversationsScreen)
-}
-
-private fun loadNatives(context: Context, conversationViewModel: ConversationsViewModel) {
- CoroutineScope(Dispatchers.Default).launch {
- conversationViewModel.reset(context)
- }
-}
-
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class,
ExperimentalFoundationApi::class, ExperimentalPermissionsApi::class
)
@@ -199,14 +139,14 @@ fun ThreadConversationLayout(
LaunchedEffect(newIntent) {
newIntent?.let {
val defaultRegion = if(inPreviewMode) "cm" else Helpers.getUserCountry(context)
- processIntents(context, it, defaultRegion)?.let {
+ conversationsViewModel.processIntents(context, it, defaultRegion)?.let {
conversationsViewModel.setNewIntent(null)
it.first?.let{ address ->
it.second?.let { threadId ->
it.third?.let{ message ->
conversationsViewModel.text = message
}
- navigateToConversation(
+ conversationsViewModel.navigateToConversation(
conversationsViewModel = conversationsViewModel,
address = address,
threadId = threadId,
@@ -310,7 +250,7 @@ fun ThreadConversationLayout(
var rememberMenuExpanded by remember { mutableStateOf( false)}
ThreadsMainDropDown(
expanded=rememberMenuExpanded,
- conversationViewModel = conversationsViewModel
+ conversationViewModel = conversationsViewModel,
) {
rememberMenuExpanded = it
}
@@ -561,7 +501,7 @@ fun ThreadConversationLayout(
) {
if(!isDefault && inboxType != InboxType.REMOTE_LISTENER) {
DefaultCheckMain {
- loadNatives(context, conversationsViewModel)
+ conversationsViewModel.loadNatives(context, conversationsViewModel)
isDefault = true
}
}
@@ -749,8 +689,8 @@ fun ThreadConversationLayout(
modifier = Modifier.combinedClickable(
onClick = {
if(selectedItems.isEmpty()) {
- navigateToConversation(
- conversationsViewModel = conversationsViewModel,
+ conversationsViewModel.navigateToConversation(
+ conversationsViewModel,
address = message.address!!,
threadId = message.thread_id!!,
subscriptionId =
diff --git a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsSearchMain.kt b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsSearchMain.kt
index 0e8ce7b2..e1963201 100644
--- a/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsSearchMain.kt
+++ b/app/src/main/java/com/afkanerd/deku/DefaultSMS/ui/ThreadsSearchMain.kt
@@ -93,7 +93,7 @@ fun SearchThreadsMain(
if(viewModel.threadId != null) {
viewModel.liveData = MutableLiveData()
viewModel.threadId = null
- navigateToConversation(
+ conversationsViewModel.navigateToConversation(
conversationsViewModel = conversationsViewModel,
address = message.address!!,
threadId = message.thread_id!!,
@@ -179,7 +179,7 @@ fun SearchThreadsMain(
modifier = Modifier.combinedClickable(
onClick = {
viewModel.liveData = MutableLiveData()
- navigateToConversation(
+ conversationsViewModel.navigateToConversation(
conversationsViewModel = conversationsViewModel,
address = message.address!!,
threadId = message.thread_id!!,
diff --git a/app/src/main/java/com/afkanerd/deku/MainActivity.kt b/app/src/main/java/com/afkanerd/deku/MainActivity.kt
index 55eb814c..539fa4ff 100644
--- a/app/src/main/java/com/afkanerd/deku/MainActivity.kt
+++ b/app/src/main/java/com/afkanerd/deku/MainActivity.kt
@@ -1,8 +1,10 @@
package com.afkanerd.deku
import android.app.ComponentCaller
+import android.content.Context
import android.content.Intent
import android.os.Bundle
+import android.util.Log
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
@@ -44,12 +46,20 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.sp
+import com.afkanerd.deku.DefaultSMS.Models.DevMode
import com.afkanerd.deku.DefaultSMS.R
+import com.afkanerd.deku.DefaultSMS.ui.LogcatMain
import com.afkanerd.deku.RemoteListeners.Models.RemoteListener.RemoteListenerQueuesViewModel
import com.afkanerd.deku.RemoteListeners.Models.RemoteListener.RemoteListenersViewModel
import com.afkanerd.deku.RemoteListeners.ui.RMQAddComposable
import com.afkanerd.deku.RemoteListeners.ui.RMQMainComposable
import com.afkanerd.deku.RemoteListeners.ui.RMQQueuesComposable
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
+import java.io.BufferedReader
+import java.io.IOException
+import java.io.InputStreamReader
class MainActivity : AppCompatActivity(){
@@ -87,8 +97,14 @@ class MainActivity : AppCompatActivity(){
}
private fun handleIntent(intent: Intent) {
- intent.let {
- conversationViewModel.setNewIntent(it)
+ if(intent.action == Intent.ACTION_VIEW &&
+ intent.getStringExtra("view") == DevMode.viewLogCat) {
+ navController.navigate(LogcatScreen)
+ }
+ else {
+ intent.let {
+ conversationViewModel.setNewIntent(it)
+ }
}
}
@@ -97,7 +113,6 @@ class MainActivity : AppCompatActivity(){
setContent {
AppTheme {
navController = rememberNavController()
-
Surface(Modifier
.fillMaxSize()
) {
@@ -146,6 +161,9 @@ class MainActivity : AppCompatActivity(){
navController = navController
)
}
+ composable{
+ LogcatMain()
+ }
}
else {
composable{
@@ -246,4 +264,34 @@ class MainActivity : AppCompatActivity(){
conversationViewModel.insertDraft(applicationContext)
}
}
-}
\ No newline at end of file
+
+ override fun onResume() {
+ super.onResume()
+ readLogcat(applicationContext)
+ }
+}
+
+fun readLogcat(context: Context): Flow = flow {
+ val logBuilder = StringBuilder()
+ try {
+ // Execute logcat command with filter for app's logs
+ val process = Runtime.getRuntime().exec("logcat -d *:V")
+ val bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
+
+ // Get app's package name to filter logs
+ val packageName = context.packageName
+
+ var line: String?
+ while (bufferedReader.readLine().also { line = it } != null) {
+ // Filter logs containing app's package name
+ if (line?.contains(packageName) == true) {
+ emit(line)
+ }
+ }
+ bufferedReader.close()
+ process.destroy()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ emit(e.message.toString())
+ }
+}.flowOn(Dispatchers.IO)
\ No newline at end of file
diff --git a/app/src/main/java/com/afkanerd/deku/screens.kt b/app/src/main/java/com/afkanerd/deku/screens.kt
index 0ca96891..3121b042 100644
--- a/app/src/main/java/com/afkanerd/deku/screens.kt
+++ b/app/src/main/java/com/afkanerd/deku/screens.kt
@@ -20,3 +20,6 @@ object RemoteListenersScreen
object RemoteListenersQueuesScreen
@Serializable
object RemoteListenersAddScreen
+
+@Serializable
+object LogcatScreen
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 975d890d..8a1bcba7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -397,5 +397,17 @@
Disabling would turn off swipe gestures in the threads screen (to archive and delete). This is enabled by default
Enable Swipe
Behaviour
+ message information
+ Close
+ Message Details
+ Type: %1$s
+ Priority: %1$s
+ Text message
+ Normal
+ From: %1$s
+ To: %1$s
+ Sent: %1$s
+ Received: %1$s
+ Dev mode
\ No newline at end of file
diff --git a/app/src/main/res/xml/settings_preferences.xml b/app/src/main/res/xml/settings_preferences.xml
index fc9b9427..0645a398 100644
--- a/app/src/main/res/xml/settings_preferences.xml
+++ b/app/src/main/res/xml/settings_preferences.xml
@@ -26,6 +26,15 @@
+
+
+
+
+
diff --git a/version.properties b/version.properties
index 9ff5056c..67bcddf6 100644
--- a/version.properties
+++ b/version.properties
@@ -2,4 +2,4 @@ releaseVersion=0
stagingVersion=61
nightlyVersion=0
versionName=0.61.0
-tagVersion=67
\ No newline at end of file
+tagVersion=67