feat: Move over the contacts API
@@ -13,6 +13,8 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
import io.flutter.plugin.common.EventChannel
|
||||
import org.moxxy.moxxy_native.contacts.ContactsImplementation
|
||||
import org.moxxy.moxxy_native.contacts.MoxxyContactsApi
|
||||
import org.moxxy.moxxy_native.cryptography.CryptographyImplementation
|
||||
import org.moxxy.moxxy_native.cryptography.MoxxyCryptographyApi
|
||||
import org.moxxy.moxxy_native.notifications.MessagingNotification
|
||||
@@ -60,12 +62,19 @@ class MoxxyNativePlugin : FlutterPlugin, ActivityAware, MoxxyPickerApi, MoxxyNot
|
||||
private lateinit var activityClass: Class<Any>
|
||||
private lateinit var pickerListener: PickerResultListener
|
||||
private val cryptographyImplementation = CryptographyImplementation()
|
||||
private lateinit var contactsImplementation: ContactsImplementation
|
||||
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
context = flutterPluginBinding.applicationContext
|
||||
contactsImplementation = ContactsImplementation(context!!)
|
||||
|
||||
// Register the pigeon handlers
|
||||
MoxxyPickerApi.setUp(flutterPluginBinding.binaryMessenger, this)
|
||||
MoxxyNotificationsApi.setUp(flutterPluginBinding.binaryMessenger, this)
|
||||
MoxxyCryptographyApi.setUp(flutterPluginBinding.binaryMessenger, cryptographyImplementation)
|
||||
MoxxyContactsApi.setUp(flutterPluginBinding.binaryMessenger, contactsImplementation)
|
||||
|
||||
// Register the picker handler
|
||||
pickerListener = PickerResultListener(context!!)
|
||||
Log.d(TAG, "Attached to engine")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// Autogenerated from Pigeon (v11.0.1), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
package org.moxxy.moxxy_native.contacts
|
||||
|
||||
import android.util.Log
|
||||
import io.flutter.plugin.common.BasicMessageChannel
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.MessageCodec
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
private fun wrapResult(result: Any?): List<Any?> {
|
||||
return listOf(result)
|
||||
}
|
||||
|
||||
private fun wrapError(exception: Throwable): List<Any?> {
|
||||
if (exception is FlutterError) {
|
||||
return listOf(
|
||||
exception.code,
|
||||
exception.message,
|
||||
exception.details
|
||||
)
|
||||
} else {
|
||||
return listOf(
|
||||
exception.javaClass.simpleName,
|
||||
exception.toString(),
|
||||
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
||||
* @property code The error code.
|
||||
* @property message The error message.
|
||||
* @property details The error details. Must be a datatype supported by the api codec.
|
||||
*/
|
||||
class FlutterError (
|
||||
val code: String,
|
||||
override val message: String? = null,
|
||||
val details: Any? = null
|
||||
) : Throwable()
|
||||
|
||||
/** The type of icon to use when no avatar path is provided. */
|
||||
enum class FallbackIconType(val raw: Int) {
|
||||
NONE(0),
|
||||
PERSON(1),
|
||||
NOTES(2);
|
||||
|
||||
companion object {
|
||||
fun ofRaw(raw: Int): FallbackIconType? {
|
||||
return values().firstOrNull { it.raw == raw }
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface MoxxyContactsApi {
|
||||
fun recordSentMessage(name: String, jid: String, avatarPath: String?, fallbackIcon: FallbackIconType)
|
||||
|
||||
companion object {
|
||||
/** The codec used by MoxxyContactsApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
StandardMessageCodec()
|
||||
}
|
||||
/** Sets up an instance of `MoxxyContactsApi` to handle messages through the `binaryMessenger`. */
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: MoxxyContactsApi?) {
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.moxxy_native.MoxxyContactsApi.recordSentMessage", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val nameArg = args[0] as String
|
||||
val jidArg = args[1] as String
|
||||
val avatarPathArg = args[2] as String?
|
||||
val fallbackIconArg = FallbackIconType.ofRaw(args[3] as Int)!!
|
||||
var wrapped: List<Any?>
|
||||
try {
|
||||
api.recordSentMessage(nameArg, jidArg, avatarPathArg, fallbackIconArg)
|
||||
wrapped = listOf<Any?>(null)
|
||||
} catch (exception: Throwable) {
|
||||
wrapped = wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.moxxy.moxxy_native.contacts
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.core.app.Person
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import org.moxxy.moxxy_native.R
|
||||
|
||||
/*
|
||||
* Implementation of Moxxy's contact APIs.
|
||||
* */
|
||||
class ContactsImplementation(private val context: Context) : MoxxyContactsApi {
|
||||
override fun recordSentMessage(
|
||||
name: String,
|
||||
jid: String,
|
||||
avatarPath: String?,
|
||||
fallbackIcon: FallbackIconType
|
||||
) {
|
||||
val pkgName = context.packageName
|
||||
val intent = Intent(context, Class.forName("$pkgName.MainActivity")).apply {
|
||||
action = Intent.ACTION_SEND
|
||||
|
||||
// Compatibility with share_handler
|
||||
putExtra("conversationIdentifier", jid)
|
||||
}
|
||||
|
||||
val shortcutTarget = "$pkgName.dynamic_share_target"
|
||||
val shortcutBuilder = ShortcutInfoCompat.Builder(context, jid).apply {
|
||||
setShortLabel(name)
|
||||
setIsConversation()
|
||||
setCategories(setOf(shortcutTarget))
|
||||
setIntent(intent)
|
||||
setLongLived(true)
|
||||
}
|
||||
|
||||
val personBuilder = Person.Builder().apply {
|
||||
setKey(jid)
|
||||
setName(name)
|
||||
}
|
||||
|
||||
// Either set an avatar image OR a fallback icon
|
||||
if (avatarPath != null) {
|
||||
val icon = IconCompat.createWithAdaptiveBitmap(
|
||||
BitmapFactory.decodeFile(avatarPath),
|
||||
)
|
||||
shortcutBuilder.setIcon(icon)
|
||||
personBuilder.setIcon(icon)
|
||||
} else {
|
||||
val resourceId = when(fallbackIcon) {
|
||||
FallbackIconType.NONE, FallbackIconType.PERSON -> R.mipmap.person
|
||||
FallbackIconType.NOTES -> R.mipmap.notes
|
||||
}
|
||||
val icon = IconCompat.createWithResource(context, resourceId)
|
||||
shortcutBuilder.setIcon(icon)
|
||||
personBuilder.setIcon(icon)
|
||||
}
|
||||
|
||||
shortcutBuilder.setPerson(personBuilder.build())
|
||||
ShortcutManagerCompat.addDynamicShortcuts(
|
||||
context,
|
||||
listOf(shortcutBuilder.build()),
|
||||
)
|
||||
}
|
||||
}
|
||||
BIN
android/src/main/res/mipmap-hdpi/notes.png
Normal file
|
After Width: | Height: | Size: 911 B |
BIN
android/src/main/res/mipmap-hdpi/person.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
android/src/main/res/mipmap-mdpi/notes.png
Normal file
|
After Width: | Height: | Size: 701 B |
BIN
android/src/main/res/mipmap-mdpi/person.png
Normal file
|
After Width: | Height: | Size: 828 B |
BIN
android/src/main/res/mipmap-xhdpi/notes.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
android/src/main/res/mipmap-xhdpi/person.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
android/src/main/res/mipmap-xxhdpi/notes.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
android/src/main/res/mipmap-xxhdpi/person.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
android/src/main/res/mipmap-xxxhdpi/notes.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
android/src/main/res/mipmap-xxxhdpi/person.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |