mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: add text/plain intent to send message (#1389)
This commit is contained in:
parent
716a3f535f
commit
d76eac258b
7 changed files with 228 additions and 0 deletions
1
.idea/inspectionProfiles/Project_Default.xml
generated
1
.idea/inspectionProfiles/Project_Default.xml
generated
|
|
@ -2,6 +2,7 @@
|
|||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
|
|
|
|||
|
|
@ -154,6 +154,12 @@
|
|||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:autoVerify="true">
|
||||
<!-- The QR codes to share channel settings are shared as meshtastic URLS
|
||||
|
||||
|
|
@ -222,6 +228,7 @@
|
|||
<action android:name="com.atakmap.app.component" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ import com.geeksville.mesh.ui.components.ScannedQrCodeDialog
|
|||
import com.geeksville.mesh.ui.map.MapFragment
|
||||
import com.geeksville.mesh.ui.navigateToMessages
|
||||
import com.geeksville.mesh.ui.navigateToNavGraph
|
||||
import com.geeksville.mesh.ui.navigateToShareMessage
|
||||
import com.geeksville.mesh.ui.theme.AppTheme
|
||||
import com.geeksville.mesh.util.Exceptions
|
||||
import com.geeksville.mesh.util.LanguageUtils
|
||||
|
|
@ -337,6 +338,13 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
Intent.ACTION_MAIN -> {
|
||||
}
|
||||
|
||||
Intent.ACTION_SEND -> {
|
||||
val text = intent.getStringExtra(Intent.EXTRA_TEXT)
|
||||
if (text != null) {
|
||||
shareMessages(text)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
warn("Unexpected action $appLinkAction")
|
||||
}
|
||||
|
|
@ -607,6 +615,13 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
}
|
||||
}
|
||||
|
||||
private fun shareMessages(message: String?) {
|
||||
model.setCurrentTab(0)
|
||||
if (message != null) {
|
||||
supportFragmentManager.navigateToShareMessage(message)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@ internal fun FragmentManager.navigateToMessages(contactKey: String) {
|
|||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
internal fun FragmentManager.navigateToPreInitMessages(contactKey: String, message: String) {
|
||||
val messagesFragment = MessagesFragment().apply {
|
||||
arguments = bundleOf("contactKey" to contactKey, "message" to message)
|
||||
}
|
||||
beginTransaction()
|
||||
.add(R.id.mainActivityLayout, messagesFragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MessagesFragment : Fragment(), Logging {
|
||||
|
|
@ -123,6 +132,9 @@ class MessagesFragment : Fragment(), Logging {
|
|||
}
|
||||
|
||||
contactKey = arguments?.getString("contactKey").toString()
|
||||
if (arguments?.getString("message") != null) {
|
||||
binding.messageInputText.setText(arguments?.getString("message").toString())
|
||||
}
|
||||
val channelIndex = contactKey[0].digitToIntOrNull()
|
||||
val nodeId = contactKey.substring(1)
|
||||
val channelName = channelIndex?.let { model.channels.value.getChannel(it)?.name }
|
||||
|
|
|
|||
128
app/src/main/java/com/geeksville/mesh/ui/ShareFragment.kt
Normal file
128
app/src/main/java/com/geeksville/mesh/ui/ShareFragment.kt
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package com.geeksville.mesh.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.geeksville.mesh.android.Logging
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.databinding.ShareFragmentBinding
|
||||
import com.geeksville.mesh.model.Contact
|
||||
import com.geeksville.mesh.model.UIViewModel
|
||||
import com.geeksville.mesh.ui.theme.AppTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
internal fun FragmentManager.navigateToShareMessage(message: String) {
|
||||
val shareFragment = ShareFragment().apply {
|
||||
arguments = bundleOf("message" to message)
|
||||
}
|
||||
beginTransaction()
|
||||
.add(R.id.mainActivityLayout, shareFragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
@AndroidEntryPoint
|
||||
class ShareFragment : ScreenFragment("Messages"), Logging {
|
||||
|
||||
private val model: UIViewModel by activityViewModels()
|
||||
private var _binding: ShareFragmentBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and onDestroyView.
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private val contacts get() = model.contactList.value
|
||||
private var selectedContact = mutableStateOf("")
|
||||
|
||||
private fun shareMessage(contact: Contact) {
|
||||
debug("calling MessagesFragment filter:${contact.contactKey}")
|
||||
parentFragmentManager.navigateToPreInitMessages(
|
||||
contact.contactKey,
|
||||
arguments?.getString("message").toString()
|
||||
)
|
||||
}
|
||||
|
||||
private fun onClick(contact: Contact) {
|
||||
if (selectedContact.value == contact.contactKey) {
|
||||
selectedContact.value = ""
|
||||
binding.shareButton.isEnabled = false
|
||||
} else {
|
||||
selectedContact.value = contact.contactKey
|
||||
binding.shareButton.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = ShareFragmentBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.toolbar.setNavigationOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
}
|
||||
|
||||
binding.shareButton.isEnabled = false
|
||||
|
||||
binding.shareButton.setOnClickListener {
|
||||
debug("User clicked shareButton")
|
||||
val contact = contacts.find { c -> c.contactKey == selectedContact.value }
|
||||
if (contact != null) {
|
||||
shareMessage(contact)
|
||||
}
|
||||
}
|
||||
|
||||
binding.contactListView.setContent {
|
||||
val contacts by model.contactList.collectAsStateWithLifecycle()
|
||||
AppTheme {
|
||||
ShareContactListView(
|
||||
contacts = contacts,
|
||||
selectedContact = selectedContact.value,
|
||||
onClick = ::onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShareContactListView(
|
||||
contacts: List<Contact>,
|
||||
selectedContact: String,
|
||||
onClick: (Contact) -> Unit,
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize(),
|
||||
contentPadding = PaddingValues(6.dp),
|
||||
) {
|
||||
items(contacts, key = { it.contactKey }) { contact ->
|
||||
val selected = contact.contactKey == selectedContact
|
||||
ContactItem(
|
||||
contact = contact,
|
||||
selected = selected,
|
||||
onClick = { onClick(contact) },
|
||||
onLongClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
63
app/src/main/res/layout/share_fragment.xml
Normal file
63
app/src/main/res/layout/share_fragment.xml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorAdvancedBackground">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/MyToolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/toolbarBackground"
|
||||
android:title="@string/share_to"
|
||||
app:title="@string/share_to"
|
||||
app:layout_constraintHeight_min="?attr/actionBarSize"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navigationIcon="?android:attr/homeAsUpIndicator"
|
||||
app:titleMargin="4dp" />
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/contactListView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_margin="8dp"
|
||||
android:contentDescription="@string/text_messages"
|
||||
app:layout_constraintBottom_toTopOf="@+id/quickChatView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar">
|
||||
|
||||
</androidx.compose.ui.platform.ComposeView>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/quickChatView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/shareButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/quickChatLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal" />
|
||||
</HorizontalScrollView>
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/shareButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:contentDescription="@string/share_message"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:srcCompat="@drawable/ic_twotone_send_24" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -290,6 +290,8 @@
|
|||
<string name="fair">Fair</string>
|
||||
<string name="good">Good</string>
|
||||
<string name="none_quality">None</string>
|
||||
<string name="share_to">Share to…</string>
|
||||
<string name="share_message">Share message</string>
|
||||
<string name="signal">Signal</string>
|
||||
<string name="signal_quality">Signal Quality</string>
|
||||
<string name="traceroute_log">Traceroute Log</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue