chore(android,base,interface): Move notification stuff into Moxxy
This commit is contained in:
parent
7cc2d0e4be
commit
f2b140de18
@ -4,7 +4,5 @@ class MoxplatformPlugin {
|
|||||||
static IsolateHandler get handler => MoxplatformInterface.handler;
|
static IsolateHandler get handler => MoxplatformInterface.handler;
|
||||||
static CryptographyImplementation get crypto => MoxplatformInterface.crypto;
|
static CryptographyImplementation get crypto => MoxplatformInterface.crypto;
|
||||||
static ContactsImplementation get contacts => MoxplatformInterface.contacts;
|
static ContactsImplementation get contacts => MoxplatformInterface.contacts;
|
||||||
static NotificationsImplementation get notifications =>
|
|
||||||
MoxplatformInterface.notifications;
|
|
||||||
static PlatformImplementation get platform => MoxplatformInterface.platform;
|
static PlatformImplementation get platform => MoxplatformInterface.platform;
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,6 @@
|
|||||||
|
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
<provider
|
|
||||||
android:name="me.polynom.moxplatform_android.MoxplatformFileProvider"
|
|
||||||
android:authorities="me.polynom.moxplatform_android.fileprovider"
|
|
||||||
android:exported="false"
|
|
||||||
android:grantUriPermissions="true">
|
|
||||||
<meta-data
|
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
||||||
android:resource="@xml/file_paths" />
|
|
||||||
</provider>
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
@ -38,7 +28,5 @@
|
|||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".NotificationReceiver" />
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +0,0 @@
|
|||||||
package me.polynom.moxplatform_android
|
|
||||||
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
|
|
||||||
class MoxplatformFileProvider : FileProvider(R.xml.file_paths) {
|
|
||||||
}
|
|
@ -6,13 +6,12 @@ import static androidx.core.content.ContextCompat.startActivity;
|
|||||||
import static me.polynom.moxplatform_android.ConstantsKt.MOXPLATFORM_FILEPROVIDER_ID;
|
import static me.polynom.moxplatform_android.ConstantsKt.MOXPLATFORM_FILEPROVIDER_ID;
|
||||||
import static me.polynom.moxplatform_android.ConstantsKt.SHARED_PREFERENCES_KEY;
|
import static me.polynom.moxplatform_android.ConstantsKt.SHARED_PREFERENCES_KEY;
|
||||||
import static me.polynom.moxplatform_android.CryptoKt.*;
|
import static me.polynom.moxplatform_android.CryptoKt.*;
|
||||||
import static me.polynom.moxplatform_android.NotificationsKt.createNotificationChannelsImpl;
|
|
||||||
import static me.polynom.moxplatform_android.NotificationsKt.createNotificationGroupsImpl;
|
|
||||||
import static me.polynom.moxplatform_android.RecordSentMessageKt.*;
|
import static me.polynom.moxplatform_android.RecordSentMessageKt.*;
|
||||||
import static me.polynom.moxplatform_android.ThumbnailsKt.generateVideoThumbnailImplementation;
|
import static me.polynom.moxplatform_android.ThumbnailsKt.generateVideoThumbnailImplementation;
|
||||||
|
|
||||||
import me.polynom.moxplatform_android.Api.*;
|
import me.polynom.moxplatform_android.Api.*;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
@ -60,7 +59,7 @@ import io.flutter.plugin.common.JSONMethodCodec;
|
|||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
|
|
||||||
public class MoxplatformAndroidPlugin extends BroadcastReceiver implements FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler, ServiceAware, MoxplatformApi {
|
public class MoxplatformAndroidPlugin extends BroadcastReceiver implements FlutterPlugin, MethodCallHandler, ServiceAware, MoxplatformApi {
|
||||||
public static final String entrypointKey = "entrypoint_handle";
|
public static final String entrypointKey = "entrypoint_handle";
|
||||||
public static final String extraDataKey = "extra_data";
|
public static final String extraDataKey = "extra_data";
|
||||||
private static final String autoStartAtBootKey = "auto_start_at_boot";
|
private static final String autoStartAtBootKey = "auto_start_at_boot";
|
||||||
@ -71,8 +70,8 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
private static final List<MoxplatformAndroidPlugin> _instances = new ArrayList<>();
|
private static final List<MoxplatformAndroidPlugin> _instances = new ArrayList<>();
|
||||||
private BackgroundService service;
|
private BackgroundService service;
|
||||||
private MethodChannel channel;
|
private MethodChannel channel;
|
||||||
private static EventChannel notificationChannel;
|
|
||||||
public static EventSink notificationSink;
|
public static Activity activity;
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
@ -86,10 +85,6 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
channel.setMethodCallHandler(this);
|
channel.setMethodCallHandler(this);
|
||||||
context = flutterPluginBinding.getApplicationContext();
|
context = flutterPluginBinding.getApplicationContext();
|
||||||
|
|
||||||
notificationChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), "me.polynom/notification_stream");
|
|
||||||
notificationChannel.setStreamHandler(this);
|
|
||||||
|
|
||||||
|
|
||||||
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this.context);
|
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this.context);
|
||||||
localBroadcastManager.registerReceiver(this, new IntentFilter(methodChannelKey));
|
localBroadcastManager.registerReceiver(this, new IntentFilter(methodChannelKey));
|
||||||
|
|
||||||
@ -102,6 +97,7 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(registrar.context());
|
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(registrar.context());
|
||||||
final MoxplatformAndroidPlugin plugin = new MoxplatformAndroidPlugin();
|
final MoxplatformAndroidPlugin plugin = new MoxplatformAndroidPlugin();
|
||||||
localBroadcastManager.registerReceiver(plugin, new IntentFilter(methodChannelKey));
|
localBroadcastManager.registerReceiver(plugin, new IntentFilter(methodChannelKey));
|
||||||
|
activity = registrar.activity();
|
||||||
|
|
||||||
final MethodChannel channel = new MethodChannel(registrar.messenger(), "me.polynom/background_service_android", JSONMethodCodec.INSTANCE);
|
final MethodChannel channel = new MethodChannel(registrar.messenger(), "me.polynom/background_service_android", JSONMethodCodec.INSTANCE);
|
||||||
channel.setMethodCallHandler(plugin);
|
channel.setMethodCallHandler(plugin);
|
||||||
@ -110,18 +106,6 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
Log.d(TAG, "Registered against registrar");
|
Log.d(TAG, "Registered against registrar");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancel(Object arguments) {
|
|
||||||
Log.d(TAG, "Removed listener");
|
|
||||||
notificationSink = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onListen(Object arguments, EventChannel.EventSink eventSink) {
|
|
||||||
Log.d(TAG, "Attached listener");
|
|
||||||
notificationSink = eventSink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Store the entrypoint handle and extra data for the background service.
|
/// Store the entrypoint handle and extra data for the background service.
|
||||||
private void configure(long entrypointHandle, String extraData) {
|
private void configure(long entrypointHandle, String extraData) {
|
||||||
SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
|
SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE);
|
||||||
@ -226,60 +210,6 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
this.service = null;
|
this.service = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createNotificationGroups(@NonNull List<NotificationGroup> groups) {
|
|
||||||
createNotificationGroupsImpl(context, groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteNotificationGroups(@NonNull List<String> ids) {
|
|
||||||
final NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
|
|
||||||
for (final String id : ids) {
|
|
||||||
notificationManager.deleteNotificationChannelGroup(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createNotificationChannels(@NonNull List<Api.NotificationChannel> channels) {
|
|
||||||
createNotificationChannelsImpl(context, channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteNotificationChannels(@NonNull List<String> ids) {
|
|
||||||
final NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
|
|
||||||
for (final String id : ids) {
|
|
||||||
notificationManager.deleteNotificationChannel(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessagingNotification(@NonNull MessagingNotification notification) {
|
|
||||||
NotificationsKt.showMessagingNotification(context, notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showNotification(@NonNull RegularNotification notification) {
|
|
||||||
NotificationsKt.showNotification(context, notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dismissNotification(@NonNull Long id) {
|
|
||||||
NotificationManagerCompat.from(context).cancel(id.intValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNotificationSelfAvatar(@NonNull String path) {
|
|
||||||
NotificationDataManager.INSTANCE.setAvatarPath(context, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNotificationI18n(@NonNull NotificationI18nData data) {
|
|
||||||
// Configure i18n
|
|
||||||
NotificationDataManager.INSTANCE.setYou(context, data.getYou());
|
|
||||||
NotificationDataManager.INSTANCE.setReply(context, data.getReply());
|
|
||||||
NotificationDataManager.INSTANCE.setMarkAsRead(context, data.getMarkAsRead());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String getPersistentDataPath() {
|
public String getPersistentDataPath() {
|
||||||
@ -349,9 +279,4 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
public Boolean generateVideoThumbnail(@NonNull String src, @NonNull String dest, @NonNull Long maxWidth) {
|
public Boolean generateVideoThumbnail(@NonNull String src, @NonNull String dest, @NonNull Long maxWidth) {
|
||||||
return generateVideoThumbnailImplementation(src, dest, maxWidth);
|
return generateVideoThumbnailImplementation(src, dest, maxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void eventStub(@NonNull NotificationEvent event) {
|
|
||||||
// Stub to trick pigeon into
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
package me.polynom.moxplatform_android
|
|
||||||
|
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.drawable.Icon
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import androidx.core.app.NotificationManagerCompat
|
|
||||||
import androidx.core.app.Person
|
|
||||||
import androidx.core.app.RemoteInput
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import me.polynom.moxplatform_android.Api.NotificationEvent
|
|
||||||
import java.io.File
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
class NotificationReceiver : BroadcastReceiver() {
|
|
||||||
/*
|
|
||||||
* Dismisses the notification through which we received @intent.
|
|
||||||
* */
|
|
||||||
private fun dismissNotification(context: Context, intent: Intent) {
|
|
||||||
// Dismiss the notification
|
|
||||||
val notificationId = intent.getLongExtra(NOTIFICATION_EXTRA_ID_KEY, -1).toInt()
|
|
||||||
if (notificationId != -1) {
|
|
||||||
NotificationManagerCompat.from(context).cancel(
|
|
||||||
notificationId,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Log.e("NotificationReceiver", "No id specified. Cannot dismiss notification")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findActiveNotification(context: Context, id: Int): Notification? {
|
|
||||||
return (context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
|
|
||||||
.activeNotifications
|
|
||||||
.find { it.id == id }?.notification
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extractPayloadMapFromIntent(intent: Intent): Map<String?, String?> {
|
|
||||||
val extras = mutableMapOf<String?, String?>()
|
|
||||||
intent.extras?.keySet()!!.forEach {
|
|
||||||
Log.d(TAG, "Checking $it -> ${intent.extras!!.get(it)}")
|
|
||||||
if (it.startsWith("payload_")) {
|
|
||||||
Log.d(TAG, "Adding $it")
|
|
||||||
extras[it.substring(8)] = intent.extras!!.getString(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return extras
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleMarkAsRead(context: Context, intent: Intent) {
|
|
||||||
MoxplatformAndroidPlugin.notificationSink?.success(
|
|
||||||
NotificationEvent().apply {
|
|
||||||
id = intent.getLongExtra(NOTIFICATION_EXTRA_ID_KEY, -1)
|
|
||||||
jid = intent.getStringExtra(NOTIFICATION_EXTRA_JID_KEY)!!
|
|
||||||
type = Api.NotificationEventType.MARK_AS_READ
|
|
||||||
payload = null
|
|
||||||
extra = extractPayloadMapFromIntent(intent)
|
|
||||||
}.toList()
|
|
||||||
)
|
|
||||||
|
|
||||||
NotificationManagerCompat.from(context).cancel(intent.getLongExtra(MARK_AS_READ_ID_KEY, -1).toInt())
|
|
||||||
dismissNotification(context, intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleReply(context: Context, intent: Intent) {
|
|
||||||
val remoteInput = RemoteInput.getResultsFromIntent(intent) ?: return
|
|
||||||
val replyPayload = remoteInput.getCharSequence(REPLY_TEXT_KEY)
|
|
||||||
MoxplatformAndroidPlugin.notificationSink?.success(
|
|
||||||
NotificationEvent().apply {
|
|
||||||
id = intent.getLongExtra(NOTIFICATION_EXTRA_ID_KEY, -1)
|
|
||||||
jid = intent.getStringExtra(NOTIFICATION_EXTRA_JID_KEY)!!
|
|
||||||
type = Api.NotificationEventType.REPLY
|
|
||||||
payload = replyPayload.toString()
|
|
||||||
extra = extractPayloadMapFromIntent(intent)
|
|
||||||
}.toList()
|
|
||||||
)
|
|
||||||
|
|
||||||
val id = intent.getLongExtra(NOTIFICATION_EXTRA_ID_KEY, -1).toInt()
|
|
||||||
if (id == -1) {
|
|
||||||
Log.e(TAG, "Failed to find notification id for reply")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
val notification = findActiveNotification(context, id)
|
|
||||||
if (notification == null) {
|
|
||||||
Log.e(TAG, "Failed to find notification for id $id")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thanks https://medium.com/@sidorovroman3/android-how-to-use-messagingstyle-for-notifications-without-caching-messages-c414ef2b816c
|
|
||||||
val recoveredStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(notification)!!
|
|
||||||
val newStyle = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
|
||||||
Notification.MessagingStyle(
|
|
||||||
android.app.Person.Builder().apply {
|
|
||||||
setName(NotificationDataManager.getYou(context))
|
|
||||||
|
|
||||||
// Set an avatar, if we have one
|
|
||||||
val avatarPath = NotificationDataManager.getAvatarPath(context)
|
|
||||||
if (avatarPath != null) {
|
|
||||||
setIcon(
|
|
||||||
Icon.createWithAdaptiveBitmap(
|
|
||||||
BitmapFactory.decodeFile(avatarPath)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
)
|
|
||||||
else Notification.MessagingStyle(NotificationDataManager.getYou(context))
|
|
||||||
|
|
||||||
newStyle.apply {
|
|
||||||
conversationTitle = recoveredStyle.conversationTitle
|
|
||||||
recoveredStyle.messages.forEach {
|
|
||||||
// Check if we have to request (or refresh) the content URI to be able to still
|
|
||||||
// see the embedded image.
|
|
||||||
val mime = it.extras.getString(NOTIFICATION_MESSAGE_EXTRA_MIME)
|
|
||||||
val path = it.extras.getString(NOTIFICATION_MESSAGE_EXTRA_PATH)
|
|
||||||
val message = Notification.MessagingStyle.Message(it.text, it.timestamp, it.sender)
|
|
||||||
if (mime != null && path != null) {
|
|
||||||
// Request a new URI from the file provider to ensure we can still see the image
|
|
||||||
// in the notification
|
|
||||||
val fileUri = FileProvider.getUriForFile(
|
|
||||||
context,
|
|
||||||
MOXPLATFORM_FILEPROVIDER_ID,
|
|
||||||
File(path),
|
|
||||||
)
|
|
||||||
message.setData(
|
|
||||||
mime,
|
|
||||||
fileUri,
|
|
||||||
)
|
|
||||||
|
|
||||||
// As we're creating a new message, also recreate the additional metadata
|
|
||||||
message.extras.apply {
|
|
||||||
putString(NOTIFICATION_MESSAGE_EXTRA_MIME, mime)
|
|
||||||
putString(NOTIFICATION_MESSAGE_EXTRA_PATH, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the old message
|
|
||||||
addMessage(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append our new message
|
|
||||||
newStyle.addMessage(
|
|
||||||
Notification.MessagingStyle.Message(
|
|
||||||
replyPayload!!,
|
|
||||||
Instant.now().toEpochMilli(),
|
|
||||||
null as CharSequence?
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Post the new notification
|
|
||||||
val recoveredBuilder = Notification.Builder.recoverBuilder(context, notification).apply {
|
|
||||||
style = newStyle
|
|
||||||
setOnlyAlertOnce(true)
|
|
||||||
}
|
|
||||||
NotificationManagerCompat.from(context).notify(id, recoveredBuilder.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleTap(context: Context, intent: Intent) {
|
|
||||||
MoxplatformAndroidPlugin.notificationSink?.success(
|
|
||||||
NotificationEvent().apply {
|
|
||||||
id = intent.getLongExtra(NOTIFICATION_EXTRA_ID_KEY, -1)
|
|
||||||
jid = intent.getStringExtra(NOTIFICATION_EXTRA_JID_KEY)!!
|
|
||||||
type = Api.NotificationEventType.OPEN
|
|
||||||
payload = null
|
|
||||||
extra = extractPayloadMapFromIntent(intent)
|
|
||||||
}.toList()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bring the app into the foreground
|
|
||||||
val tapIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)!!
|
|
||||||
context.startActivity(tapIntent)
|
|
||||||
|
|
||||||
// Dismiss the notification
|
|
||||||
dismissNotification(context, intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
// TODO: We need to be careful to ensure that the Flutter engine is running.
|
|
||||||
// If it's not, we have to start it. However, that's only an issue when we expect to
|
|
||||||
// receive notifications while not running, i.e. Push Notifications.
|
|
||||||
when (intent.action) {
|
|
||||||
MARK_AS_READ_ACTION -> handleMarkAsRead(context, intent)
|
|
||||||
REPLY_ACTION -> handleReply(context, intent)
|
|
||||||
TAP_ACTION -> handleTap(context, intent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,328 +0,0 @@
|
|||||||
package me.polynom.moxplatform_android
|
|
||||||
|
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationChannel
|
|
||||||
import android.app.NotificationChannelGroup
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Build
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import androidx.core.app.NotificationManagerCompat
|
|
||||||
import androidx.core.app.Person
|
|
||||||
import androidx.core.app.RemoteInput
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Holds "persistent" data for notifications, like i18n strings. While not useful now, this is
|
|
||||||
* useful for when the app is dead and we receive a notification.
|
|
||||||
* */
|
|
||||||
object NotificationDataManager {
|
|
||||||
private var you: String? = null
|
|
||||||
private var markAsRead: String? = null
|
|
||||||
private var reply: String? = null
|
|
||||||
|
|
||||||
private var fetchedAvatarPath = false
|
|
||||||
private var avatarPath: String? = null
|
|
||||||
|
|
||||||
private fun getString(context: Context, key: String, fallback: String): String {
|
|
||||||
return context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)!!.getString(key, fallback)!!
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setString(context: Context, key: String, value: String) {
|
|
||||||
val prefs = context.getSharedPreferences(SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
|
||||||
prefs.edit()
|
|
||||||
.putString(key, value)
|
|
||||||
.apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getYou(context: Context): String {
|
|
||||||
if (you == null) you = getString(context, SHARED_PREFERENCES_YOU_KEY, "You")
|
|
||||||
return you!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setYou(context: Context, value: String) {
|
|
||||||
setString(context, SHARED_PREFERENCES_YOU_KEY, value)
|
|
||||||
you = value
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMarkAsRead(context: Context): String {
|
|
||||||
if (markAsRead == null) markAsRead = getString(context, SHARED_PREFERENCES_MARK_AS_READ_KEY, "Mark as read")
|
|
||||||
return markAsRead!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setMarkAsRead(context: Context, value: String) {
|
|
||||||
setString(context, SHARED_PREFERENCES_MARK_AS_READ_KEY, value)
|
|
||||||
markAsRead = value
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getReply(context: Context): String {
|
|
||||||
if (reply != null) reply = getString(context, SHARED_PREFERENCES_REPLY_KEY, "Reply")
|
|
||||||
return reply!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setReply(context: Context, value: String) {
|
|
||||||
setString(context, SHARED_PREFERENCES_REPLY_KEY, value)
|
|
||||||
reply = value
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAvatarPath(context: Context): String? {
|
|
||||||
if (avatarPath == null && !fetchedAvatarPath) {
|
|
||||||
val path = getString(context, SHARED_PREFERENCES_AVATAR_KEY, "")
|
|
||||||
if (path.isNotEmpty()) {
|
|
||||||
avatarPath = path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return avatarPath
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAvatarPath(context: Context, value: String) {
|
|
||||||
setString(context, SHARED_PREFERENCES_AVATAR_KEY, value)
|
|
||||||
fetchedAvatarPath = true
|
|
||||||
avatarPath = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createNotificationGroupsImpl(context: Context, groups: List<Api.NotificationGroup>) {
|
|
||||||
val notificationManager = context.getSystemService(NotificationManager::class.java)
|
|
||||||
for (group in groups) {
|
|
||||||
notificationManager.createNotificationChannelGroup(
|
|
||||||
NotificationChannelGroup(group.id, group.description),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createNotificationChannelsImpl(context: Context, channels: List<Api.NotificationChannel>) {
|
|
||||||
val notificationManager = context.getSystemService(NotificationManager::class.java)
|
|
||||||
for (channel in channels) {
|
|
||||||
val importance = when(channel.importance) {
|
|
||||||
Api.NotificationChannelImportance.DEFAULT -> NotificationManager.IMPORTANCE_DEFAULT
|
|
||||||
Api.NotificationChannelImportance.MIN -> NotificationManager.IMPORTANCE_MIN
|
|
||||||
Api.NotificationChannelImportance.HIGH -> NotificationManager.IMPORTANCE_HIGH
|
|
||||||
}
|
|
||||||
val notificationChannel = NotificationChannel(channel.id, channel.title, importance).apply {
|
|
||||||
description = channel.description
|
|
||||||
|
|
||||||
enableVibration(channel.vibration)
|
|
||||||
enableLights(channel.enableLights)
|
|
||||||
setShowBadge(channel.showBadge)
|
|
||||||
if (channel.groupId != null) {
|
|
||||||
group = channel.groupId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
notificationManager.createNotificationChannel(notificationChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Show a messaging style notification described by @notification.
|
|
||||||
fun showMessagingNotification(context: Context, notification: Api.MessagingNotification) {
|
|
||||||
// Build the actions
|
|
||||||
// -> Reply action
|
|
||||||
val remoteInput = RemoteInput.Builder(REPLY_TEXT_KEY).apply {
|
|
||||||
setLabel(NotificationDataManager.getReply(context))
|
|
||||||
}.build()
|
|
||||||
val replyIntent = Intent(context, NotificationReceiver::class.java).apply {
|
|
||||||
action = REPLY_ACTION
|
|
||||||
putExtra(NOTIFICATION_EXTRA_JID_KEY, notification.jid)
|
|
||||||
putExtra(NOTIFICATION_EXTRA_ID_KEY, notification.id)
|
|
||||||
|
|
||||||
notification.extra?.forEach {
|
|
||||||
putExtra("payload_${it.key}", it.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val replyPendingIntent = PendingIntent.getBroadcast(
|
|
||||||
context.applicationContext,
|
|
||||||
0,
|
|
||||||
replyIntent,
|
|
||||||
PendingIntent.FLAG_MUTABLE,
|
|
||||||
)
|
|
||||||
val replyAction = NotificationCompat.Action.Builder(
|
|
||||||
R.drawable.reply,
|
|
||||||
NotificationDataManager.getReply(context),
|
|
||||||
replyPendingIntent,
|
|
||||||
).apply {
|
|
||||||
addRemoteInput(remoteInput)
|
|
||||||
setAllowGeneratedReplies(true)
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
// -> Mark as read action
|
|
||||||
val markAsReadIntent = Intent(context, NotificationReceiver::class.java).apply {
|
|
||||||
action = MARK_AS_READ_ACTION
|
|
||||||
putExtra(NOTIFICATION_EXTRA_JID_KEY, notification.jid)
|
|
||||||
putExtra(NOTIFICATION_EXTRA_ID_KEY, notification.id)
|
|
||||||
|
|
||||||
notification.extra?.forEach {
|
|
||||||
putExtra("payload_${it.key}", it.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val markAsReadPendingIntent = PendingIntent.getBroadcast(
|
|
||||||
context.applicationContext,
|
|
||||||
0,
|
|
||||||
markAsReadIntent,
|
|
||||||
PendingIntent.FLAG_IMMUTABLE,
|
|
||||||
)
|
|
||||||
val markAsReadAction = NotificationCompat.Action.Builder(
|
|
||||||
R.drawable.mark_as_read,
|
|
||||||
NotificationDataManager.getMarkAsRead(context),
|
|
||||||
markAsReadPendingIntent,
|
|
||||||
).build()
|
|
||||||
|
|
||||||
// -> Tap action
|
|
||||||
// Thanks https://github.com/MaikuB/flutter_local_notifications/blob/master/flutter_local_notifications/android/src/main/java/com/dexterous/flutterlocalnotifications/FlutterLocalNotificationsPlugin.java#L246
|
|
||||||
val tapIntent = Intent(context, NotificationReceiver::class.java).apply {
|
|
||||||
action = TAP_ACTION
|
|
||||||
putExtra(NOTIFICATION_EXTRA_JID_KEY, notification.jid)
|
|
||||||
putExtra(NOTIFICATION_EXTRA_ID_KEY, notification.id)
|
|
||||||
|
|
||||||
notification.extra?.forEach {
|
|
||||||
putExtra("payload_${it.key}", it.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val tapPendingIntent = PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
notification.id.toInt(),
|
|
||||||
tapIntent,
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
|
|
||||||
// Build the notification
|
|
||||||
val selfPerson = Person.Builder().apply {
|
|
||||||
setName(NotificationDataManager.getYou(context))
|
|
||||||
|
|
||||||
// Set an avatar, if we have one
|
|
||||||
val avatarPath = NotificationDataManager.getAvatarPath(context)
|
|
||||||
if (avatarPath != null) {
|
|
||||||
setIcon(
|
|
||||||
IconCompat.createWithAdaptiveBitmap(
|
|
||||||
BitmapFactory.decodeFile(avatarPath),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
val style = NotificationCompat.MessagingStyle(selfPerson);
|
|
||||||
style.isGroupConversation = notification.isGroupchat
|
|
||||||
if (notification.isGroupchat) {
|
|
||||||
style.conversationTitle = notification.title
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in notification.messages.indices) {
|
|
||||||
val message = notification.messages[i]
|
|
||||||
|
|
||||||
// Build the sender
|
|
||||||
// NOTE: Note that we set it to null if message.sender == null because otherwise this results in
|
|
||||||
// a bogus Person object which messes with the "self-message" display as Android expects
|
|
||||||
// null in that case.
|
|
||||||
val sender = if (message.sender == null)
|
|
||||||
null
|
|
||||||
else Person.Builder().apply {
|
|
||||||
setName(message.sender)
|
|
||||||
setKey(message.jid)
|
|
||||||
|
|
||||||
// Set the avatar, if available
|
|
||||||
if (message.avatarPath != null) {
|
|
||||||
try {
|
|
||||||
setIcon(
|
|
||||||
IconCompat.createWithAdaptiveBitmap(
|
|
||||||
BitmapFactory.decodeFile(message.avatarPath),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} catch (ex: Throwable) {
|
|
||||||
Log.w(TAG, "Failed to open avatar at ${message.avatarPath}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
// Build the message
|
|
||||||
val body = message.content.body ?: ""
|
|
||||||
val msg = NotificationCompat.MessagingStyle.Message(
|
|
||||||
body,
|
|
||||||
message.timestamp,
|
|
||||||
sender,
|
|
||||||
)
|
|
||||||
// If we got an image, turn it into a content URI and set it
|
|
||||||
if (message.content.mime != null && message.content.path != null) {
|
|
||||||
val fileUri = FileProvider.getUriForFile(
|
|
||||||
context,
|
|
||||||
MOXPLATFORM_FILEPROVIDER_ID,
|
|
||||||
File(message.content.path),
|
|
||||||
)
|
|
||||||
msg.apply {
|
|
||||||
setData(message.content.mime, fileUri)
|
|
||||||
|
|
||||||
extras.apply {
|
|
||||||
putString(NOTIFICATION_MESSAGE_EXTRA_MIME, message.content.mime)
|
|
||||||
putString(NOTIFICATION_MESSAGE_EXTRA_PATH, message.content.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the message
|
|
||||||
style.addMessage(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assemble the notification
|
|
||||||
val finalNotification = NotificationCompat.Builder(context, notification.channelId).apply {
|
|
||||||
setStyle(style)
|
|
||||||
// NOTE: It's okay to use the service icon here as I cannot get Android to display the
|
|
||||||
// actual logo. So we'll have to make do with the silhouette and the color purple.
|
|
||||||
setSmallIcon(R.drawable.ic_service_icon)
|
|
||||||
color = Color.argb(255, 207, 74, 255)
|
|
||||||
setColorized(true)
|
|
||||||
|
|
||||||
// Tap action
|
|
||||||
setContentIntent(tapPendingIntent)
|
|
||||||
|
|
||||||
// Notification actions
|
|
||||||
addAction(replyAction)
|
|
||||||
addAction(markAsReadAction)
|
|
||||||
|
|
||||||
// Groupchat title
|
|
||||||
if (notification.isGroupchat) {
|
|
||||||
setContentTitle(notification.title)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent grouping with the foreground service
|
|
||||||
if (notification.groupId != null) {
|
|
||||||
setGroup(notification.groupId)
|
|
||||||
}
|
|
||||||
|
|
||||||
setAllowSystemGeneratedContextualActions(true)
|
|
||||||
setCategory(Notification.CATEGORY_MESSAGE)
|
|
||||||
|
|
||||||
// Prevent no notification when we replied before
|
|
||||||
setOnlyAlertOnce(false)
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
// Post the notification
|
|
||||||
NotificationManagerCompat.from(context).notify(
|
|
||||||
notification.id.toInt(),
|
|
||||||
finalNotification,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showNotification(context: Context, notification: Api.RegularNotification) {
|
|
||||||
val builtNotification = NotificationCompat.Builder(context, notification.channelId).apply {
|
|
||||||
setContentTitle(notification.title)
|
|
||||||
setContentText(notification.body)
|
|
||||||
|
|
||||||
when (notification.icon) {
|
|
||||||
Api.NotificationIcon.ERROR -> setSmallIcon(R.drawable.error)
|
|
||||||
Api.NotificationIcon.WARNING -> setSmallIcon(R.drawable.warning)
|
|
||||||
Api.NotificationIcon.NONE -> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notification.groupId != null) {
|
|
||||||
setGroup(notification.groupId)
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
// Post the notification
|
|
||||||
NotificationManagerCompat.from(context).notify(notification.id.toInt(), builtNotification)
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<!-- For testing -->
|
|
||||||
<cache-path name="file_picker" path="file_picker/"/>
|
|
||||||
|
|
||||||
<!-- Moxxy -->
|
|
||||||
<files-path name="media" path="media/" />
|
|
||||||
</paths>
|
|
@ -1,64 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
|
||||||
|
|
||||||
class AndroidNotificationsImplementation extends NotificationsImplementation {
|
|
||||||
final MoxplatformApi _api = MoxplatformApi();
|
|
||||||
|
|
||||||
final EventChannel _channel =
|
|
||||||
const EventChannel('me.polynom/notification_stream');
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> createNotificationChannels(
|
|
||||||
List<NotificationChannel> channels) async {
|
|
||||||
return _api.createNotificationChannels(channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteNotificationChannels(List<String> ids) {
|
|
||||||
return _api.deleteNotificationChannels(ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> createNotificationGroups(List<NotificationGroup> groups) async {
|
|
||||||
return _api.createNotificationGroups(groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteNotificationGroups(List<String> ids) {
|
|
||||||
return _api.deleteNotificationGroups(ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> showMessagingNotification(
|
|
||||||
MessagingNotification notification,
|
|
||||||
) async {
|
|
||||||
return _api.showMessagingNotification(notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> showNotification(RegularNotification notification) async {
|
|
||||||
return _api.showNotification(notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> dismissNotification(int id) async {
|
|
||||||
return _api.dismissNotification(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> setNotificationSelfAvatar(String path) async {
|
|
||||||
return _api.setNotificationSelfAvatar(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> setI18n(NotificationI18nData data) {
|
|
||||||
return _api.setNotificationI18n(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<NotificationEvent> getEventStream() => _channel
|
|
||||||
.receiveBroadcastStream()
|
|
||||||
.cast<Object>()
|
|
||||||
.map(NotificationEvent.decode);
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:moxplatform_android/src/contacts_android.dart';
|
import 'package:moxplatform_android/src/contacts_android.dart';
|
||||||
import 'package:moxplatform_android/src/crypto_android.dart';
|
import 'package:moxplatform_android/src/crypto_android.dart';
|
||||||
import 'package:moxplatform_android/src/isolate_android.dart';
|
import 'package:moxplatform_android/src/isolate_android.dart';
|
||||||
import 'package:moxplatform_android/src/notifications_android.dart';
|
|
||||||
import 'package:moxplatform_android/src/platform_android.dart';
|
import 'package:moxplatform_android/src/platform_android.dart';
|
||||||
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ class MoxplatformAndroidPlugin extends MoxplatformInterface {
|
|||||||
MoxplatformInterface.contacts = AndroidContactsImplementation();
|
MoxplatformInterface.contacts = AndroidContactsImplementation();
|
||||||
MoxplatformInterface.crypto = AndroidCryptographyImplementation();
|
MoxplatformInterface.crypto = AndroidCryptographyImplementation();
|
||||||
MoxplatformInterface.handler = AndroidIsolateHandler();
|
MoxplatformInterface.handler = AndroidIsolateHandler();
|
||||||
MoxplatformInterface.notifications = AndroidNotificationsImplementation();
|
|
||||||
MoxplatformInterface.platform = AndroidPlatformImplementation();
|
MoxplatformInterface.platform = AndroidPlatformImplementation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@ export 'src/crypto_stub.dart';
|
|||||||
export 'src/interface.dart';
|
export 'src/interface.dart';
|
||||||
export 'src/isolate.dart';
|
export 'src/isolate.dart';
|
||||||
export 'src/isolate_stub.dart';
|
export 'src/isolate_stub.dart';
|
||||||
export 'src/notifications.dart';
|
|
||||||
export 'src/notifications_stub.dart';
|
|
||||||
export 'src/platform.dart';
|
export 'src/platform.dart';
|
||||||
export 'src/platform_stub.dart';
|
export 'src/platform_stub.dart';
|
||||||
export 'src/service.dart';
|
export 'src/service.dart';
|
||||||
|
@ -8,18 +8,6 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
|
|||||||
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
|
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
enum NotificationIcon {
|
|
||||||
warning,
|
|
||||||
error,
|
|
||||||
none,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NotificationEventType {
|
|
||||||
markAsRead,
|
|
||||||
reply,
|
|
||||||
open,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CipherAlgorithm {
|
enum CipherAlgorithm {
|
||||||
aes128GcmNoPadding,
|
aes128GcmNoPadding,
|
||||||
aes256GcmNoPadding,
|
aes256GcmNoPadding,
|
||||||
@ -32,295 +20,6 @@ enum FallbackIconType {
|
|||||||
notes,
|
notes,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NotificationChannelImportance {
|
|
||||||
MIN,
|
|
||||||
HIGH,
|
|
||||||
DEFAULT,
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationMessageContent {
|
|
||||||
NotificationMessageContent({
|
|
||||||
this.body,
|
|
||||||
this.mime,
|
|
||||||
this.path,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The textual body of the message.
|
|
||||||
String? body;
|
|
||||||
|
|
||||||
/// The path and mime type of the media to show.
|
|
||||||
String? mime;
|
|
||||||
|
|
||||||
String? path;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
body,
|
|
||||||
mime,
|
|
||||||
path,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NotificationMessageContent decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return NotificationMessageContent(
|
|
||||||
body: result[0] as String?,
|
|
||||||
mime: result[1] as String?,
|
|
||||||
path: result[2] as String?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationMessage {
|
|
||||||
NotificationMessage({
|
|
||||||
this.groupId,
|
|
||||||
this.sender,
|
|
||||||
this.jid,
|
|
||||||
required this.content,
|
|
||||||
required this.timestamp,
|
|
||||||
this.avatarPath,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The grouping key for the notification.
|
|
||||||
String? groupId;
|
|
||||||
|
|
||||||
/// The sender of the message.
|
|
||||||
String? sender;
|
|
||||||
|
|
||||||
/// The jid of the sender.
|
|
||||||
String? jid;
|
|
||||||
|
|
||||||
/// The body of the message.
|
|
||||||
NotificationMessageContent content;
|
|
||||||
|
|
||||||
/// Milliseconds since epoch.
|
|
||||||
int timestamp;
|
|
||||||
|
|
||||||
/// The path to the avatar to use
|
|
||||||
String? avatarPath;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
groupId,
|
|
||||||
sender,
|
|
||||||
jid,
|
|
||||||
content.encode(),
|
|
||||||
timestamp,
|
|
||||||
avatarPath,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NotificationMessage decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return NotificationMessage(
|
|
||||||
groupId: result[0] as String?,
|
|
||||||
sender: result[1] as String?,
|
|
||||||
jid: result[2] as String?,
|
|
||||||
content: NotificationMessageContent.decode(result[3]! as List<Object?>),
|
|
||||||
timestamp: result[4]! as int,
|
|
||||||
avatarPath: result[5] as String?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessagingNotification {
|
|
||||||
MessagingNotification({
|
|
||||||
required this.title,
|
|
||||||
required this.id,
|
|
||||||
required this.channelId,
|
|
||||||
required this.jid,
|
|
||||||
required this.messages,
|
|
||||||
required this.isGroupchat,
|
|
||||||
this.groupId,
|
|
||||||
this.extra,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The title of the conversation.
|
|
||||||
String title;
|
|
||||||
|
|
||||||
/// The id of the notification.
|
|
||||||
int id;
|
|
||||||
|
|
||||||
/// The id of the notification channel the notification should appear on.
|
|
||||||
String channelId;
|
|
||||||
|
|
||||||
/// The JID of the chat in which the notifications happen.
|
|
||||||
String jid;
|
|
||||||
|
|
||||||
/// Messages to show.
|
|
||||||
List<NotificationMessage?> messages;
|
|
||||||
|
|
||||||
/// Flag indicating whether this notification is from a groupchat or not.
|
|
||||||
bool isGroupchat;
|
|
||||||
|
|
||||||
/// The id for notification grouping.
|
|
||||||
String? groupId;
|
|
||||||
|
|
||||||
/// Additional data to include.
|
|
||||||
Map<String?, String?>? extra;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
title,
|
|
||||||
id,
|
|
||||||
channelId,
|
|
||||||
jid,
|
|
||||||
messages,
|
|
||||||
isGroupchat,
|
|
||||||
groupId,
|
|
||||||
extra,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static MessagingNotification decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return MessagingNotification(
|
|
||||||
title: result[0]! as String,
|
|
||||||
id: result[1]! as int,
|
|
||||||
channelId: result[2]! as String,
|
|
||||||
jid: result[3]! as String,
|
|
||||||
messages: (result[4] as List<Object?>?)!.cast<NotificationMessage?>(),
|
|
||||||
isGroupchat: result[5]! as bool,
|
|
||||||
groupId: result[6] as String?,
|
|
||||||
extra: (result[7] as Map<Object?, Object?>?)?.cast<String?, String?>(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RegularNotification {
|
|
||||||
RegularNotification({
|
|
||||||
required this.title,
|
|
||||||
required this.body,
|
|
||||||
required this.channelId,
|
|
||||||
this.groupId,
|
|
||||||
required this.id,
|
|
||||||
required this.icon,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The title of the notification.
|
|
||||||
String title;
|
|
||||||
|
|
||||||
/// The body of the notification.
|
|
||||||
String body;
|
|
||||||
|
|
||||||
/// The id of the channel to show the notification on.
|
|
||||||
String channelId;
|
|
||||||
|
|
||||||
/// The id for notification grouping.
|
|
||||||
String? groupId;
|
|
||||||
|
|
||||||
/// The id of the notification.
|
|
||||||
int id;
|
|
||||||
|
|
||||||
/// The icon to use.
|
|
||||||
NotificationIcon icon;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
title,
|
|
||||||
body,
|
|
||||||
channelId,
|
|
||||||
groupId,
|
|
||||||
id,
|
|
||||||
icon.index,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static RegularNotification decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return RegularNotification(
|
|
||||||
title: result[0]! as String,
|
|
||||||
body: result[1]! as String,
|
|
||||||
channelId: result[2]! as String,
|
|
||||||
groupId: result[3] as String?,
|
|
||||||
id: result[4]! as int,
|
|
||||||
icon: NotificationIcon.values[result[5]! as int],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationEvent {
|
|
||||||
NotificationEvent({
|
|
||||||
required this.id,
|
|
||||||
required this.jid,
|
|
||||||
required this.type,
|
|
||||||
this.payload,
|
|
||||||
this.extra,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The notification id.
|
|
||||||
int id;
|
|
||||||
|
|
||||||
/// The JID the notification was for.
|
|
||||||
String jid;
|
|
||||||
|
|
||||||
/// The type of event.
|
|
||||||
NotificationEventType type;
|
|
||||||
|
|
||||||
/// An optional payload.
|
|
||||||
/// - type == NotificationType.reply: The reply message text.
|
|
||||||
/// Otherwise: undefined.
|
|
||||||
String? payload;
|
|
||||||
|
|
||||||
/// Extra data. Only set when type == NotificationType.reply.
|
|
||||||
Map<String?, String?>? extra;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
id,
|
|
||||||
jid,
|
|
||||||
type.index,
|
|
||||||
payload,
|
|
||||||
extra,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NotificationEvent decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return NotificationEvent(
|
|
||||||
id: result[0]! as int,
|
|
||||||
jid: result[1]! as String,
|
|
||||||
type: NotificationEventType.values[result[2]! as int],
|
|
||||||
payload: result[3] as String?,
|
|
||||||
extra: (result[4] as Map<Object?, Object?>?)?.cast<String?, String?>(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationI18nData {
|
|
||||||
NotificationI18nData({
|
|
||||||
required this.reply,
|
|
||||||
required this.markAsRead,
|
|
||||||
required this.you,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The content of the reply button.
|
|
||||||
String reply;
|
|
||||||
|
|
||||||
/// The content of the "mark as read" button.
|
|
||||||
String markAsRead;
|
|
||||||
|
|
||||||
/// The text to show when *you* reply.
|
|
||||||
String you;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
reply,
|
|
||||||
markAsRead,
|
|
||||||
you,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NotificationI18nData decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return NotificationI18nData(
|
|
||||||
reply: result[0]! as String,
|
|
||||||
markAsRead: result[1]! as String,
|
|
||||||
you: result[2]! as String,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CryptographyResult {
|
class CryptographyResult {
|
||||||
CryptographyResult({
|
CryptographyResult({
|
||||||
required this.plaintextHash,
|
required this.plaintextHash,
|
||||||
@ -347,88 +46,6 @@ class CryptographyResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationGroup {
|
|
||||||
NotificationGroup({
|
|
||||||
required this.id,
|
|
||||||
required this.description,
|
|
||||||
});
|
|
||||||
|
|
||||||
String id;
|
|
||||||
|
|
||||||
String description;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
id,
|
|
||||||
description,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NotificationGroup decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return NotificationGroup(
|
|
||||||
id: result[0]! as String,
|
|
||||||
description: result[1]! as String,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationChannel {
|
|
||||||
NotificationChannel({
|
|
||||||
required this.title,
|
|
||||||
required this.description,
|
|
||||||
required this.id,
|
|
||||||
required this.importance,
|
|
||||||
required this.showBadge,
|
|
||||||
this.groupId,
|
|
||||||
required this.vibration,
|
|
||||||
required this.enableLights,
|
|
||||||
});
|
|
||||||
|
|
||||||
String title;
|
|
||||||
|
|
||||||
String description;
|
|
||||||
|
|
||||||
String id;
|
|
||||||
|
|
||||||
NotificationChannelImportance importance;
|
|
||||||
|
|
||||||
bool showBadge;
|
|
||||||
|
|
||||||
String? groupId;
|
|
||||||
|
|
||||||
bool vibration;
|
|
||||||
|
|
||||||
bool enableLights;
|
|
||||||
|
|
||||||
Object encode() {
|
|
||||||
return <Object?>[
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
id,
|
|
||||||
importance.index,
|
|
||||||
showBadge,
|
|
||||||
groupId,
|
|
||||||
vibration,
|
|
||||||
enableLights,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
static NotificationChannel decode(Object result) {
|
|
||||||
result as List<Object?>;
|
|
||||||
return NotificationChannel(
|
|
||||||
title: result[0]! as String,
|
|
||||||
description: result[1]! as String,
|
|
||||||
id: result[2]! as String,
|
|
||||||
importance: NotificationChannelImportance.values[result[3]! as int],
|
|
||||||
showBadge: result[4]! as bool,
|
|
||||||
groupId: result[5] as String?,
|
|
||||||
vibration: result[6]! as bool,
|
|
||||||
enableLights: result[7]! as bool,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MoxplatformApiCodec extends StandardMessageCodec {
|
class _MoxplatformApiCodec extends StandardMessageCodec {
|
||||||
const _MoxplatformApiCodec();
|
const _MoxplatformApiCodec();
|
||||||
@override
|
@override
|
||||||
@ -436,30 +53,6 @@ class _MoxplatformApiCodec extends StandardMessageCodec {
|
|||||||
if (value is CryptographyResult) {
|
if (value is CryptographyResult) {
|
||||||
buffer.putUint8(128);
|
buffer.putUint8(128);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is MessagingNotification) {
|
|
||||||
buffer.putUint8(129);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is NotificationChannel) {
|
|
||||||
buffer.putUint8(130);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is NotificationEvent) {
|
|
||||||
buffer.putUint8(131);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is NotificationGroup) {
|
|
||||||
buffer.putUint8(132);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is NotificationI18nData) {
|
|
||||||
buffer.putUint8(133);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is NotificationMessage) {
|
|
||||||
buffer.putUint8(134);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is NotificationMessageContent) {
|
|
||||||
buffer.putUint8(135);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else if (value is RegularNotification) {
|
|
||||||
buffer.putUint8(136);
|
|
||||||
writeValue(buffer, value.encode());
|
|
||||||
} else {
|
} else {
|
||||||
super.writeValue(buffer, value);
|
super.writeValue(buffer, value);
|
||||||
}
|
}
|
||||||
@ -470,22 +63,6 @@ class _MoxplatformApiCodec extends StandardMessageCodec {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 128:
|
case 128:
|
||||||
return CryptographyResult.decode(readValue(buffer)!);
|
return CryptographyResult.decode(readValue(buffer)!);
|
||||||
case 129:
|
|
||||||
return MessagingNotification.decode(readValue(buffer)!);
|
|
||||||
case 130:
|
|
||||||
return NotificationChannel.decode(readValue(buffer)!);
|
|
||||||
case 131:
|
|
||||||
return NotificationEvent.decode(readValue(buffer)!);
|
|
||||||
case 132:
|
|
||||||
return NotificationGroup.decode(readValue(buffer)!);
|
|
||||||
case 133:
|
|
||||||
return NotificationI18nData.decode(readValue(buffer)!);
|
|
||||||
case 134:
|
|
||||||
return NotificationMessage.decode(readValue(buffer)!);
|
|
||||||
case 135:
|
|
||||||
return NotificationMessageContent.decode(readValue(buffer)!);
|
|
||||||
case 136:
|
|
||||||
return RegularNotification.decode(readValue(buffer)!);
|
|
||||||
default:
|
default:
|
||||||
return super.readValueOfType(type, buffer);
|
return super.readValueOfType(type, buffer);
|
||||||
}
|
}
|
||||||
@ -502,224 +79,13 @@ class MoxplatformApi {
|
|||||||
|
|
||||||
static const MessageCodec<Object?> codec = _MoxplatformApiCodec();
|
static const MessageCodec<Object?> codec = _MoxplatformApiCodec();
|
||||||
|
|
||||||
/// Notification APIs
|
|
||||||
Future<void> createNotificationGroups(
|
|
||||||
List<NotificationGroup?> arg_groups) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.createNotificationGroups',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_groups]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteNotificationGroups(List<String?> arg_ids) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.deleteNotificationGroups',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_ids]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> createNotificationChannels(
|
|
||||||
List<NotificationChannel?> arg_channels) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.createNotificationChannels',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_channels]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteNotificationChannels(List<String?> arg_ids) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.deleteNotificationChannels',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_ids]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> showMessagingNotification(
|
|
||||||
MessagingNotification arg_notification) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.showMessagingNotification',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_notification]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> showNotification(RegularNotification arg_notification) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.showNotification',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_notification]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> dismissNotification(int arg_id) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.dismissNotification',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_id]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setNotificationSelfAvatar(String arg_path) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.setNotificationSelfAvatar',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_path]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setNotificationI18n(NotificationI18nData arg_data) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.setNotificationI18n',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_data]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Platform APIs
|
/// Platform APIs
|
||||||
Future<String> getPersistentDataPath() async {
|
Future<String> getPersistentDataPath() async {
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getPersistentDataPath',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getPersistentDataPath', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
|
final List<Object?>? replyList =
|
||||||
|
await channel.send(null) as List<Object?>?;
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -743,10 +109,10 @@ class MoxplatformApi {
|
|||||||
|
|
||||||
Future<String> getCacheDataPath() async {
|
Future<String> getCacheDataPath() async {
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getCacheDataPath',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getCacheDataPath', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
|
final List<Object?>? replyList =
|
||||||
|
await channel.send(null) as List<Object?>?;
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -770,10 +136,10 @@ class MoxplatformApi {
|
|||||||
|
|
||||||
Future<void> openBatteryOptimisationSettings() async {
|
Future<void> openBatteryOptimisationSettings() async {
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.openBatteryOptimisationSettings',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.openBatteryOptimisationSettings', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
|
final List<Object?>? replyList =
|
||||||
|
await channel.send(null) as List<Object?>?;
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -792,10 +158,10 @@ class MoxplatformApi {
|
|||||||
|
|
||||||
Future<bool> isIgnoringBatteryOptimizations() async {
|
Future<bool> isIgnoringBatteryOptimizations() async {
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.isIgnoringBatteryOptimizations',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.isIgnoringBatteryOptimizations', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
|
final List<Object?>? replyList =
|
||||||
|
await channel.send(null) as List<Object?>?;
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -818,18 +184,12 @@ class MoxplatformApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Contacts APIs
|
/// Contacts APIs
|
||||||
Future<void> recordSentMessage(String arg_name, String arg_jid,
|
Future<void> recordSentMessage(String arg_name, String arg_jid, String? arg_avatarPath, FallbackIconType arg_fallbackIcon) async {
|
||||||
String? arg_avatarPath, FallbackIconType arg_fallbackIcon) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.recordSentMessage',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.recordSentMessage', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(<Object?>[
|
final List<Object?>? replyList =
|
||||||
arg_name,
|
await channel.send(<Object?>[arg_name, arg_jid, arg_avatarPath, arg_fallbackIcon.index]) as List<Object?>?;
|
||||||
arg_jid,
|
|
||||||
arg_avatarPath,
|
|
||||||
arg_fallbackIcon.index
|
|
||||||
]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -847,25 +207,12 @@ class MoxplatformApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Cryptography APIs
|
/// Cryptography APIs
|
||||||
Future<CryptographyResult?> encryptFile(
|
Future<CryptographyResult?> encryptFile(String arg_sourcePath, String arg_destPath, Uint8List arg_key, Uint8List arg_iv, CipherAlgorithm arg_algorithm, String arg_hashSpec) async {
|
||||||
String arg_sourcePath,
|
|
||||||
String arg_destPath,
|
|
||||||
Uint8List arg_key,
|
|
||||||
Uint8List arg_iv,
|
|
||||||
CipherAlgorithm arg_algorithm,
|
|
||||||
String arg_hashSpec) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.encryptFile',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.encryptFile', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(<Object?>[
|
final List<Object?>? replyList =
|
||||||
arg_sourcePath,
|
await channel.send(<Object?>[arg_sourcePath, arg_destPath, arg_key, arg_iv, arg_algorithm.index, arg_hashSpec]) as List<Object?>?;
|
||||||
arg_destPath,
|
|
||||||
arg_key,
|
|
||||||
arg_iv,
|
|
||||||
arg_algorithm.index,
|
|
||||||
arg_hashSpec
|
|
||||||
]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -882,25 +229,12 @@ class MoxplatformApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<CryptographyResult?> decryptFile(
|
Future<CryptographyResult?> decryptFile(String arg_sourcePath, String arg_destPath, Uint8List arg_key, Uint8List arg_iv, CipherAlgorithm arg_algorithm, String arg_hashSpec) async {
|
||||||
String arg_sourcePath,
|
|
||||||
String arg_destPath,
|
|
||||||
Uint8List arg_key,
|
|
||||||
Uint8List arg_iv,
|
|
||||||
CipherAlgorithm arg_algorithm,
|
|
||||||
String arg_hashSpec) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.decryptFile',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.decryptFile', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel.send(<Object?>[
|
final List<Object?>? replyList =
|
||||||
arg_sourcePath,
|
await channel.send(<Object?>[arg_sourcePath, arg_destPath, arg_key, arg_iv, arg_algorithm.index, arg_hashSpec]) as List<Object?>?;
|
||||||
arg_destPath,
|
|
||||||
arg_key,
|
|
||||||
arg_iv,
|
|
||||||
arg_algorithm.index,
|
|
||||||
arg_hashSpec
|
|
||||||
]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -917,14 +251,12 @@ class MoxplatformApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List?> hashFile(
|
Future<Uint8List?> hashFile(String arg_sourcePath, String arg_hashSpec) async {
|
||||||
String arg_sourcePath, String arg_hashSpec) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.hashFile',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.hashFile', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel
|
final List<Object?>? replyList =
|
||||||
.send(<Object?>[arg_sourcePath, arg_hashSpec]) as List<Object?>?;
|
await channel.send(<Object?>[arg_sourcePath, arg_hashSpec]) as List<Object?>?;
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -942,14 +274,12 @@ class MoxplatformApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Media APIs
|
/// Media APIs
|
||||||
Future<bool> generateVideoThumbnail(
|
Future<bool> generateVideoThumbnail(String arg_src, String arg_dest, int arg_maxWidth) async {
|
||||||
String arg_src, String arg_dest, int arg_maxWidth) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.generateVideoThumbnail',
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.generateVideoThumbnail', codec,
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList = await channel
|
final List<Object?>? replyList =
|
||||||
.send(<Object?>[arg_src, arg_dest, arg_maxWidth]) as List<Object?>?;
|
await channel.send(<Object?>[arg_src, arg_dest, arg_maxWidth]) as List<Object?>?;
|
||||||
if (replyList == null) {
|
if (replyList == null) {
|
||||||
throw PlatformException(
|
throw PlatformException(
|
||||||
code: 'channel-error',
|
code: 'channel-error',
|
||||||
@ -970,28 +300,4 @@ class MoxplatformApi {
|
|||||||
return (replyList[0] as bool?)!;
|
return (replyList[0] as bool?)!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stubs
|
|
||||||
Future<void> eventStub(NotificationEvent arg_event) async {
|
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.eventStub',
|
|
||||||
codec,
|
|
||||||
binaryMessenger: _binaryMessenger);
|
|
||||||
final List<Object?>? replyList =
|
|
||||||
await channel.send(<Object?>[arg_event]) as List<Object?>?;
|
|
||||||
if (replyList == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'channel-error',
|
|
||||||
message: 'Unable to establish connection on channel.',
|
|
||||||
);
|
|
||||||
} else if (replyList.length > 1) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: replyList[0]! as String,
|
|
||||||
message: replyList[1] as String?,
|
|
||||||
details: replyList[2],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ import 'package:moxplatform_platform_interface/src/crypto.dart';
|
|||||||
import 'package:moxplatform_platform_interface/src/crypto_stub.dart';
|
import 'package:moxplatform_platform_interface/src/crypto_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/isolate.dart';
|
import 'package:moxplatform_platform_interface/src/isolate.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/isolate_stub.dart';
|
import 'package:moxplatform_platform_interface/src/isolate_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/notifications.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/src/notifications_stub.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/src/platform.dart';
|
import 'package:moxplatform_platform_interface/src/platform.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/platform_stub.dart';
|
import 'package:moxplatform_platform_interface/src/platform_stub.dart';
|
||||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||||
@ -21,8 +19,6 @@ abstract class MoxplatformInterface extends PlatformInterface {
|
|||||||
static IsolateHandler handler = StubIsolateHandler();
|
static IsolateHandler handler = StubIsolateHandler();
|
||||||
static CryptographyImplementation crypto = StubCryptographyImplementation();
|
static CryptographyImplementation crypto = StubCryptographyImplementation();
|
||||||
static ContactsImplementation contacts = StubContactsImplementation();
|
static ContactsImplementation contacts = StubContactsImplementation();
|
||||||
static NotificationsImplementation notifications =
|
|
||||||
StubNotificationsImplementation();
|
|
||||||
static PlatformImplementation platform = StubPlatformImplementation();
|
static PlatformImplementation platform = StubPlatformImplementation();
|
||||||
|
|
||||||
/// Return the current platform name.
|
/// Return the current platform name.
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'package:moxplatform_platform_interface/src/api.g.dart';
|
|
||||||
|
|
||||||
abstract class NotificationsImplementation {
|
|
||||||
/// Creates a notification channel with the name [title] and id [id]. If [urgent] is true, then
|
|
||||||
/// it configures the channel as carrying urgent information.
|
|
||||||
Future<void> createNotificationChannels(List<NotificationChannel> channels);
|
|
||||||
|
|
||||||
Future<void> deleteNotificationChannels(List<String> ids);
|
|
||||||
|
|
||||||
/// Creates notification groups.
|
|
||||||
Future<void> createNotificationGroups(List<NotificationGroup> groups);
|
|
||||||
|
|
||||||
Future<void> deleteNotificationGroups(List<String> ids);
|
|
||||||
|
|
||||||
/// Shows a notification [notification] in the messaging style with everyting it needs.
|
|
||||||
Future<void> showMessagingNotification(MessagingNotification notification);
|
|
||||||
|
|
||||||
/// Shows a regular notification [notification].
|
|
||||||
Future<void> showNotification(RegularNotification notification);
|
|
||||||
|
|
||||||
/// Dismisses the notification with id [id].
|
|
||||||
Future<void> dismissNotification(int id);
|
|
||||||
|
|
||||||
/// Sets the path to the self-avatar for in-notification replies.
|
|
||||||
Future<void> setNotificationSelfAvatar(String path);
|
|
||||||
|
|
||||||
/// Configures the i18n data for usage in notifications.
|
|
||||||
Future<void> setI18n(NotificationI18nData data);
|
|
||||||
|
|
||||||
Stream<NotificationEvent> getEventStream();
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'package:moxplatform_platform_interface/src/api.g.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/src/notifications.dart';
|
|
||||||
|
|
||||||
class StubNotificationsImplementation extends NotificationsImplementation {
|
|
||||||
@override
|
|
||||||
Future<void> createNotificationChannels(
|
|
||||||
List<NotificationChannel> channels,
|
|
||||||
) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteNotificationChannels(
|
|
||||||
List<String> ids,
|
|
||||||
) async {}
|
|
||||||
|
|
||||||
Future<void> createNotificationGroups(
|
|
||||||
List<NotificationGroup> groups,
|
|
||||||
) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteNotificationGroups(
|
|
||||||
List<String> ids,
|
|
||||||
) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> showMessagingNotification(
|
|
||||||
MessagingNotification notification,
|
|
||||||
) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> showNotification(RegularNotification notification) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> dismissNotification(int id) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> setNotificationSelfAvatar(String path) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> setI18n(NotificationI18nData data) async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Stream<NotificationEvent> getEventStream() {
|
|
||||||
return StreamController<NotificationEvent>().stream;
|
|
||||||
}
|
|
||||||
}
|
|
193
pigeons/api.dart
193
pigeons/api.dart
@ -13,152 +13,6 @@ import 'package:pigeon/pigeon.dart';
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
class NotificationMessageContent {
|
|
||||||
const NotificationMessageContent(
|
|
||||||
this.body,
|
|
||||||
this.mime,
|
|
||||||
this.path,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// The textual body of the message.
|
|
||||||
final String? body;
|
|
||||||
|
|
||||||
/// The path and mime type of the media to show.
|
|
||||||
final String? mime;
|
|
||||||
final String? path;
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationMessage {
|
|
||||||
const NotificationMessage(
|
|
||||||
this.sender,
|
|
||||||
this.content,
|
|
||||||
this.jid,
|
|
||||||
this.timestamp,
|
|
||||||
this.avatarPath, {
|
|
||||||
this.groupId,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The grouping key for the notification.
|
|
||||||
final String? groupId;
|
|
||||||
|
|
||||||
/// The sender of the message.
|
|
||||||
final String? sender;
|
|
||||||
|
|
||||||
/// The jid of the sender.
|
|
||||||
final String? jid;
|
|
||||||
|
|
||||||
/// The body of the message.
|
|
||||||
final NotificationMessageContent content;
|
|
||||||
|
|
||||||
/// Milliseconds since epoch.
|
|
||||||
final int timestamp;
|
|
||||||
|
|
||||||
/// The path to the avatar to use
|
|
||||||
final String? avatarPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessagingNotification {
|
|
||||||
const MessagingNotification(this.title, this.id, this.jid, this.messages, this.channelId, this.isGroupchat, this.extra, {this.groupId});
|
|
||||||
|
|
||||||
/// The title of the conversation.
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
/// The id of the notification.
|
|
||||||
final int id;
|
|
||||||
|
|
||||||
/// The id of the notification channel the notification should appear on.
|
|
||||||
final String channelId;
|
|
||||||
|
|
||||||
/// The JID of the chat in which the notifications happen.
|
|
||||||
final String jid;
|
|
||||||
|
|
||||||
/// Messages to show.
|
|
||||||
final List<NotificationMessage?> messages;
|
|
||||||
|
|
||||||
/// Flag indicating whether this notification is from a groupchat or not.
|
|
||||||
final bool isGroupchat;
|
|
||||||
|
|
||||||
/// The id for notification grouping.
|
|
||||||
final String? groupId;
|
|
||||||
|
|
||||||
/// Additional data to include.
|
|
||||||
final Map<String?, String?>? extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NotificationIcon {
|
|
||||||
warning,
|
|
||||||
error,
|
|
||||||
none,
|
|
||||||
}
|
|
||||||
|
|
||||||
class RegularNotification {
|
|
||||||
const RegularNotification(this.title, this.body, this.channelId, this.id, this.icon, {this.groupId});
|
|
||||||
|
|
||||||
/// The title of the notification.
|
|
||||||
final String title;
|
|
||||||
|
|
||||||
/// The body of the notification.
|
|
||||||
final String body;
|
|
||||||
|
|
||||||
/// The id of the channel to show the notification on.
|
|
||||||
final String channelId;
|
|
||||||
|
|
||||||
/// The id for notification grouping.
|
|
||||||
final String? groupId;
|
|
||||||
|
|
||||||
/// The id of the notification.
|
|
||||||
final int id;
|
|
||||||
|
|
||||||
/// The icon to use.
|
|
||||||
final NotificationIcon icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NotificationEventType {
|
|
||||||
markAsRead,
|
|
||||||
reply,
|
|
||||||
open,
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationEvent {
|
|
||||||
const NotificationEvent(
|
|
||||||
this.id,
|
|
||||||
this.jid,
|
|
||||||
this.type,
|
|
||||||
this.payload,
|
|
||||||
this.extra,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// The notification id.
|
|
||||||
final int id;
|
|
||||||
|
|
||||||
/// The JID the notification was for.
|
|
||||||
final String jid;
|
|
||||||
|
|
||||||
/// The type of event.
|
|
||||||
final NotificationEventType type;
|
|
||||||
|
|
||||||
/// An optional payload.
|
|
||||||
/// - type == NotificationType.reply: The reply message text.
|
|
||||||
/// Otherwise: undefined.
|
|
||||||
final String? payload;
|
|
||||||
|
|
||||||
/// Extra data. Only set when type == NotificationType.reply.
|
|
||||||
final Map<String?, String?>? extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationI18nData {
|
|
||||||
const NotificationI18nData(this.reply, this.markAsRead, this.you);
|
|
||||||
|
|
||||||
/// The content of the reply button.
|
|
||||||
final String reply;
|
|
||||||
|
|
||||||
/// The content of the "mark as read" button.
|
|
||||||
final String markAsRead;
|
|
||||||
|
|
||||||
/// The text to show when *you* reply.
|
|
||||||
final String you;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CipherAlgorithm {
|
enum CipherAlgorithm {
|
||||||
aes128GcmNoPadding,
|
aes128GcmNoPadding,
|
||||||
aes256GcmNoPadding,
|
aes256GcmNoPadding,
|
||||||
@ -178,52 +32,8 @@ enum FallbackIconType {
|
|||||||
notes;
|
notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationGroup {
|
|
||||||
const NotificationGroup(this.id, this.description);
|
|
||||||
final String id;
|
|
||||||
final String description;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NotificationChannelImportance {
|
|
||||||
MIN,
|
|
||||||
HIGH,
|
|
||||||
DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
class NotificationChannel {
|
|
||||||
const NotificationChannel(
|
|
||||||
this.id,
|
|
||||||
this.title,
|
|
||||||
this.description, {
|
|
||||||
this.importance = NotificationChannelImportance.DEFAULT,
|
|
||||||
this.showBadge = true,
|
|
||||||
this.groupId,
|
|
||||||
this.vibration = true,
|
|
||||||
this.enableLights = true,
|
|
||||||
});
|
|
||||||
final String title;
|
|
||||||
final String description;
|
|
||||||
final String id;
|
|
||||||
final NotificationChannelImportance importance;
|
|
||||||
final bool showBadge;
|
|
||||||
final String? groupId;
|
|
||||||
final bool vibration;
|
|
||||||
final bool enableLights;
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
abstract class MoxplatformApi {
|
abstract class MoxplatformApi {
|
||||||
/// Notification APIs
|
|
||||||
void createNotificationGroups(List<NotificationGroup> groups);
|
|
||||||
void deleteNotificationGroups(List<String> ids);
|
|
||||||
void createNotificationChannels(List<NotificationChannel> channels);
|
|
||||||
void deleteNotificationChannels(List<String> ids);
|
|
||||||
void showMessagingNotification(MessagingNotification notification);
|
|
||||||
void showNotification(RegularNotification notification);
|
|
||||||
void dismissNotification(int id);
|
|
||||||
void setNotificationSelfAvatar(String path);
|
|
||||||
void setNotificationI18n(NotificationI18nData data);
|
|
||||||
|
|
||||||
/// Platform APIs
|
/// Platform APIs
|
||||||
String getPersistentDataPath();
|
String getPersistentDataPath();
|
||||||
String getCacheDataPath();
|
String getCacheDataPath();
|
||||||
@ -240,7 +50,4 @@ abstract class MoxplatformApi {
|
|||||||
|
|
||||||
/// Media APIs
|
/// Media APIs
|
||||||
bool generateVideoThumbnail(String src, String dest, int maxWidth);
|
bool generateVideoThumbnail(String src, String dest, int maxWidth);
|
||||||
|
|
||||||
/// Stubs
|
|
||||||
void eventStub(NotificationEvent event);
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user