Basic stuff
This commit is contained in:
		
							parent
							
								
									17642f9fab
								
							
						
					
					
						commit
						1771c0e1b6
					
				| @ -47,7 +47,7 @@ android { | ||||
|         applicationId "com.example.example" | ||||
|         // You can update the following values to match your application needs. | ||||
|         // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. | ||||
|         minSdkVersion flutter.minSdkVersion | ||||
|         minSdkVersion 26 | ||||
|         targetSdkVersion flutter.targetSdkVersion | ||||
|         versionCode flutterVersionCode.toInteger() | ||||
|         versionName flutterVersionName | ||||
|  | ||||
| @ -34,5 +34,5 @@ | ||||
| 
 | ||||
|    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | ||||
|    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||||
| 
 | ||||
|    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> | ||||
| </manifest> | ||||
|  | ||||
| @ -1,17 +1,49 @@ | ||||
| import 'dart:io'; | ||||
| import 'dart:math'; | ||||
| import 'dart:typed_data'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:file_picker/file_picker.dart'; | ||||
| import 'package:moxplatform/moxplatform.dart'; | ||||
| import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart'; | ||||
| import 'package:permission_handler/permission_handler.dart'; | ||||
| import 'package:file_picker/file_picker.dart'; | ||||
| 
 | ||||
| /// The id of the notification channel. | ||||
| const channelId = "me.polynom.moxplatform.testing3"; | ||||
| 
 | ||||
| void main() { | ||||
|   runApp(const MyApp()); | ||||
| } | ||||
| 
 | ||||
| class MyApp extends StatelessWidget { | ||||
| class Sender { | ||||
|   const Sender(this.name, this.jid); | ||||
| 
 | ||||
|   final String name; | ||||
| 
 | ||||
|   final String jid; | ||||
| } | ||||
| 
 | ||||
| class MyApp extends StatefulWidget { | ||||
|   const MyApp({Key? key}) : super(key: key); | ||||
| 
 | ||||
|   @override | ||||
|   MyAppState createState() => MyAppState(); | ||||
| } | ||||
| 
 | ||||
| class MyAppState extends State<MyApp> { | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
| 
 | ||||
|     initStateAsync(); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> initStateAsync() async { | ||||
|     await Permission.notification.request(); | ||||
| 
 | ||||
|     await MoxplatformPlugin.notifications.createNotificationChannel("Test notification channel", channelId, false); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return MaterialApp( | ||||
| @ -19,13 +51,23 @@ class MyApp extends StatelessWidget { | ||||
|       theme: ThemeData( | ||||
|         primarySwatch: Colors.blue, | ||||
|       ), | ||||
|       home: const MyHomePage(), | ||||
|       home: MyHomePage(), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class MyHomePage extends StatelessWidget { | ||||
|   const MyHomePage({super.key}); | ||||
|   MyHomePage({super.key}); | ||||
| 
 | ||||
|   /// List of "Message senders". | ||||
|   final List<Sender> senders = const [ | ||||
|     Sender('Mash Kyrielight', 'mash@example.org'), | ||||
|     Sender('Rio Tsukatsuki', 'rio@millenium'), | ||||
|     Sender('Raiden Shogun', 'raiden@tevhat'), | ||||
|   ]; | ||||
| 
 | ||||
|   /// List of sent messages. | ||||
|   List<NotificationMessage> messages = List<NotificationMessage>.empty(growable: true); | ||||
| 
 | ||||
|   Future<void> _cryptoTest() async { | ||||
|     final result = await FilePicker.platform.pickFiles(); | ||||
| @ -98,6 +140,41 @@ class MyHomePage extends StatelessWidget { | ||||
|               }, | ||||
|               child: const Text('Test recordSentMessage (notes fallback)'), | ||||
|             ), | ||||
|             ElevatedButton( | ||||
|               onPressed: () async { | ||||
|                 final result = await FilePicker.platform.pickFiles( | ||||
|                   type: FileType.image, | ||||
|                 ); | ||||
|                 print('Picked file: ${result?.files.single.path}'); | ||||
| 
 | ||||
|                 // Create a new message. | ||||
|                 final senderIndex = Random().nextInt(senders.length); | ||||
|                 final time = DateTime.now().millisecondsSinceEpoch; | ||||
|                 messages.add( | ||||
|                   NotificationMessage( | ||||
|                     jid: senders[senderIndex].jid, | ||||
|                     sender: senders[senderIndex].name, | ||||
|                     content: NotificationMessageContent( | ||||
|                       body: result != null ? null : 'Message #${messages.length}', | ||||
|                       mime: 'image/jpeg', | ||||
|                       path: result?.files.single.path, | ||||
|                     ), | ||||
|                     timestamp: time, | ||||
|                   ) | ||||
|                 ); | ||||
| 
 | ||||
|                 await Future<void>.delayed(const Duration(seconds: 4)); | ||||
|                 await MoxplatformPlugin.notifications.showMessagingNotification( | ||||
|                   MessagingNotification( | ||||
|                     id: 2343, | ||||
|                     title: 'Test conversation', | ||||
|                     messages: messages, | ||||
|                     channelId: channelId, | ||||
|                   ), | ||||
|                 ); | ||||
|               }, | ||||
|               child: const Text('Show messaging notification'), | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|  | ||||
| @ -38,6 +38,8 @@ dependencies: | ||||
|     version: 0.1.17+1 | ||||
| 
 | ||||
|   file_picker: 5.2.0+1 | ||||
| 
 | ||||
|   permission_handler: 10.4.3 | ||||
|      | ||||
|   # The following adds the Cupertino Icons font to your application. | ||||
|   # Use with the CupertinoIcons class for iOS style icons. | ||||
|  | ||||
| @ -5,4 +5,5 @@ class MoxplatformPlugin { | ||||
|   static MediaScannerImplementation get media => MoxplatformInterface.media; | ||||
|   static CryptographyImplementation get crypto => MoxplatformInterface.crypto; | ||||
|   static ContactsImplementation get contacts => MoxplatformInterface.contacts; | ||||
|   static NotificationsImplementation get notifications => MoxplatformInterface.notifications; | ||||
| } | ||||
|  | ||||
| @ -35,7 +35,8 @@ android { | ||||
|     } | ||||
| 
 | ||||
|     defaultConfig { | ||||
|         minSdkVersion 16 | ||||
|         // What Moxxy currently uses | ||||
|         minSdkVersion 26 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,11 +1,22 @@ | ||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|   package="me.polynom.moxplatform_android"> | ||||
|     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> | ||||
|     <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> | ||||
|     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> | ||||
|     <uses-permission android:name="android.permission.WAKE_LOCK"/> | ||||
| 
 | ||||
| 
 | ||||
|     <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 | ||||
|             android:enabled="true" | ||||
|             android:exported="true" | ||||
| @ -27,5 +38,6 @@ | ||||
|             </intent-filter> | ||||
|         </receiver> | ||||
| 
 | ||||
|         <receiver android:name=".NotificationReceiver" /> | ||||
|     </application> | ||||
| </manifest> | ||||
|  | ||||
| @ -6,6 +6,14 @@ const val TAG = "Moxplatform" | ||||
| // The size of the buffer to hashing, encryption, and decryption in bytes. | ||||
| const val BUFFER_SIZE = 8096 | ||||
| 
 | ||||
| // The data key for text entered in the notification's reply field | ||||
| const val REPLY_TEXT_KEY = "key_reply_text" | ||||
| 
 | ||||
| // The action for pressing the "Mark as read" button on a notification | ||||
| const val MARK_AS_READ_ACTION = "mark_as_read" | ||||
| // The key for the notification id to mark as read | ||||
| const val MARK_AS_READ_ID_KEY = "notification_id" | ||||
| 
 | ||||
| // TODO: Maybe try again to rewrite the entire plugin in Kotlin | ||||
| //const val METHOD_CHANNEL_KEY = "me.polynom.moxplatform_android" | ||||
| //const val BACKGROUND_METHOD_CHANNEL_KEY = METHOD_CHANNEL_KEY + "_bg" | ||||
|  | ||||
| @ -0,0 +1,6 @@ | ||||
| package me.polynom.moxplatform_android | ||||
| 
 | ||||
| import androidx.core.content.FileProvider | ||||
| 
 | ||||
| class MoxplatformFileProvider : FileProvider(R.xml.file_paths) { | ||||
| } | ||||
| @ -1,31 +1,39 @@ | ||||
| package me.polynom.moxplatform_android; | ||||
| 
 | ||||
| import static androidx.core.content.ContextCompat.getSystemService; | ||||
| import static me.polynom.moxplatform_android.ConstantsKt.MARK_AS_READ_ACTION; | ||||
| import static me.polynom.moxplatform_android.ConstantsKt.MARK_AS_READ_ID_KEY; | ||||
| import static me.polynom.moxplatform_android.ConstantsKt.REPLY_TEXT_KEY; | ||||
| import static me.polynom.moxplatform_android.RecordSentMessageKt.recordSentMessage; | ||||
| import static me.polynom.moxplatform_android.CryptoKt.*; | ||||
| import me.polynom.moxplatform_android.Notifications.*; | ||||
| 
 | ||||
| import android.app.ActivityManager; | ||||
| import android.app.NotificationChannel; | ||||
| import android.app.NotificationManager; | ||||
| import android.app.PendingIntent; | ||||
| import android.content.BroadcastReceiver; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.IntentFilter; | ||||
| import android.content.SharedPreferences; | ||||
| import android.graphics.BitmapFactory; | ||||
| import android.net.Uri; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.core.app.RemoteInput; | ||||
| import androidx.core.app.NotificationCompat; | ||||
| import androidx.core.app.NotificationManagerCompat; | ||||
| import androidx.core.app.Person; | ||||
| import androidx.core.content.ContextCompat; | ||||
| import androidx.core.graphics.drawable.IconCompat; | ||||
| import androidx.localbroadcastmanager.content.LocalBroadcastManager; | ||||
| 
 | ||||
| import java.io.FileInputStream; | ||||
| import java.security.MessageDigest; | ||||
| import java.io.File; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import javax.crypto.Cipher; | ||||
| import javax.crypto.CipherOutputStream; | ||||
| import javax.crypto.spec.IvParameterSpec; | ||||
| import javax.crypto.spec.SecretKeySpec; | ||||
| 
 | ||||
| import io.flutter.embedding.engine.plugins.FlutterPlugin; | ||||
| import io.flutter.embedding.engine.plugins.service.ServiceAware; | ||||
| import io.flutter.embedding.engine.plugins.service.ServicePluginBinding; | ||||
| @ -35,8 +43,10 @@ import io.flutter.plugin.common.MethodChannel.MethodCallHandler; | ||||
| import io.flutter.plugin.common.MethodChannel.Result; | ||||
| import io.flutter.plugin.common.PluginRegistry.Registrar; | ||||
| import io.flutter.plugin.common.JSONMethodCodec; | ||||
| import kotlin.Unit; | ||||
| import kotlin.jvm.functions.Function1; | ||||
| 
 | ||||
| public class MoxplatformAndroidPlugin extends BroadcastReceiver implements FlutterPlugin, MethodCallHandler, ServiceAware { | ||||
| public class MoxplatformAndroidPlugin extends BroadcastReceiver implements FlutterPlugin, MethodCallHandler, ServiceAware, NotificationsImplementationApi { | ||||
|   public static final String entrypointKey = "entrypoint_handle"; | ||||
|   public static final String extraDataKey = "extra_data"; | ||||
|   private static final String autoStartAtBootKey = "auto_start_at_boot"; | ||||
| @ -50,6 +60,8 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt | ||||
|   private MethodChannel channel; | ||||
|   private Context context; | ||||
| 
 | ||||
|   private FileProvider provider = new FileProvider(); | ||||
| 
 | ||||
|   public MoxplatformAndroidPlugin() { | ||||
|     _instances.add(this); | ||||
|   } | ||||
| @ -63,6 +75,8 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt | ||||
|     LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this.context); | ||||
|     localBroadcastManager.registerReceiver(this, new IntentFilter(methodChannelKey)); | ||||
| 
 | ||||
|     NotificationsImplementationApi.setup(flutterPluginBinding.getBinaryMessenger(), this); | ||||
| 
 | ||||
|     Log.d(TAG, "Attached to engine"); | ||||
|   } | ||||
| 
 | ||||
| @ -117,7 +131,7 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { | ||||
|   public void onMethodCall(@NonNull MethodCall call, @NonNull io.flutter.plugin.common.MethodChannel.Result result) { | ||||
|     switch (call.method) { | ||||
|       case "configure": | ||||
|         ArrayList args = (ArrayList) call.arguments; | ||||
| @ -262,4 +276,78 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt | ||||
|     Log.d(TAG, "Detached from service"); | ||||
|     this.service = null; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public void createNotificationChannel(@NonNull String title, @NonNull String id, @NonNull Boolean urgent) { | ||||
|       final NotificationChannel channel = new NotificationChannel( | ||||
|               id, | ||||
|               title, | ||||
|               urgent ? NotificationManager.IMPORTANCE_HIGH : NotificationManager.IMPORTANCE_DEFAULT | ||||
|       ); | ||||
|       channel.enableVibration(true); | ||||
|       channel.enableLights(true); | ||||
|       final NotificationManager manager = getSystemService(context, NotificationManager.class); | ||||
|       manager.createNotificationChannel(channel); | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|   public void showMessagingNotification(@NonNull MessagingNotification notification) { | ||||
|     // Create a reply button | ||||
|     // TODO: i18n | ||||
|     RemoteInput remoteInput = new RemoteInput.Builder(REPLY_TEXT_KEY).setLabel("Reply").build(); | ||||
|     final Intent replyIntent = new Intent(context, NotificationReceiver.class); | ||||
|     final PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); | ||||
|     // TODO: i18n | ||||
|     // TODO: Correct icon | ||||
|     final NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_service_icon, "Reply", replyPendingIntent) | ||||
|             .addRemoteInput(remoteInput) | ||||
|             .build(); | ||||
| 
 | ||||
|     // Create the "mark as read" button | ||||
|     final Intent markAsReadIntent = new Intent(context, NotificationReceiver.class); | ||||
|     markAsReadIntent.setAction(MARK_AS_READ_ACTION); | ||||
|     markAsReadIntent.putExtra(MARK_AS_READ_ID_KEY, notification.getId()); | ||||
|     // TODO: Replace with something more useful | ||||
|     markAsReadIntent.putExtra("title", notification.getTitle()); | ||||
|     final PendingIntent markAsReadPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, readIntent,PendingIntent.FLAG_CANCEL_CURRENT); | ||||
| 
 | ||||
|     final NotificationCompat.MessagingStyle style = new NotificationCompat.MessagingStyle("Me") | ||||
|             .setConversationTitle(notification.getTitle()); | ||||
|     for (final NotificationMessage message : notification.getMessages()) { | ||||
|       // Build the sender of the message | ||||
|       final Person.Builder personBuilder = new Person.Builder() | ||||
|               .setName(message.getSender()) | ||||
|               .setKey(message.getJid()); | ||||
|       if (message.getAvatarPath() != null) { | ||||
|         final IconCompat icon = IconCompat.createWithAdaptiveBitmap( | ||||
|                 BitmapFactory.decodeFile(message.getAvatarPath()) | ||||
|         ); | ||||
|         personBuilder.setIcon(icon); | ||||
|       } | ||||
| 
 | ||||
|       // Build the message | ||||
|       final String content = message.getContent().getBody() == null ? "" : message.getContent().getBody(); | ||||
|       final NotificationCompat.MessagingStyle.Message msg = new NotificationCompat.MessagingStyle.Message( | ||||
|               content, | ||||
|               message.getTimestamp(), | ||||
|               personBuilder.build() | ||||
|       ); | ||||
|       // Turn the image path to a content Uri, if a media file was specified | ||||
|       if (message.getContent().getMime() != null && message.getContent().getPath() != null) { | ||||
|         final Uri fileUri = androidx.core.content.FileProvider.getUriForFile(context, "me.polynom.moxplatform_android.fileprovider", new File(message.getContent().getPath())); | ||||
|         msg.setData(message.getContent().getMime(), fileUri); | ||||
|       } | ||||
| 
 | ||||
|       style.addMessage(msg); | ||||
|     } | ||||
| 
 | ||||
|     // Build the notification and send it | ||||
|     final NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, notification.getChannelId()) | ||||
|             .setStyle(style) | ||||
|             // TODO: This is wrong | ||||
|             .setSmallIcon(R.drawable.ic_service_icon) | ||||
|             .addAction(action) | ||||
|             .addAction(R.drawable.ic_service_icon, "Mark as read", markAsReadPendingIntent); | ||||
|     NotificationManagerCompat.from(context).notify(notification.getId().intValue(), notificationBuilder.build()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,28 @@ | ||||
| package me.polynom.moxplatform_android | ||||
| 
 | ||||
| import android.app.NotificationManager | ||||
| import android.content.BroadcastReceiver | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.util.Log | ||||
| import androidx.core.app.NotificationManagerCompat | ||||
| import androidx.core.app.RemoteInput | ||||
| 
 | ||||
| class NotificationReceiver : BroadcastReceiver() { | ||||
|     override fun onReceive(context: Context, intent: Intent) { | ||||
|         // If it is a mark as read, dismiss the entire notification and | ||||
|         // send a notification to the app. | ||||
|         // TODO: Notify app | ||||
|         if (intent.action == MARK_AS_READ_ACTION) { | ||||
|             Log.d("NotificationReceiver", "Marking ${intent.getStringExtra("title")} as read") | ||||
|             NotificationManagerCompat.from(context).cancel(intent.getLongExtra(MARK_AS_READ_ID_KEY, -1).toInt()) | ||||
|             return | ||||
|         } | ||||
| 
 | ||||
|         val remoteInput = RemoteInput.getResultsFromIntent(intent) ?: return | ||||
| 
 | ||||
|         val title = remoteInput.getCharSequence(REPLY_TEXT_KEY).toString() | ||||
|         Log.d("NotificationReceiver", title) | ||||
|         // TODO: Notify app | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,520 @@ | ||||
| // Autogenerated from Pigeon (v10.1.4), do not edit directly. | ||||
| // See also: https://pub.dev/packages/pigeon | ||||
| 
 | ||||
| package me.polynom.moxplatform_android; | ||||
| 
 | ||||
| import android.util.Log; | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| 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; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| /** Generated class from Pigeon. */ | ||||
| @SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) | ||||
| public class Notifications { | ||||
| 
 | ||||
|   /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ | ||||
|   public static class FlutterError extends RuntimeException { | ||||
| 
 | ||||
|     /** The error code. */ | ||||
|     public final String code; | ||||
| 
 | ||||
|     /** The error details. Must be a datatype supported by the api codec. */ | ||||
|     public final Object details; | ||||
| 
 | ||||
|     public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details)  | ||||
|     { | ||||
|       super(message); | ||||
|       this.code = code; | ||||
|       this.details = details; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @NonNull | ||||
|   protected static ArrayList<Object> wrapError(@NonNull Throwable exception) { | ||||
|     ArrayList<Object> errorList = new ArrayList<Object>(3); | ||||
|     if (exception instanceof FlutterError) { | ||||
|       FlutterError error = (FlutterError) exception; | ||||
|       errorList.add(error.code); | ||||
|       errorList.add(error.getMessage()); | ||||
|       errorList.add(error.details); | ||||
|     } else { | ||||
|       errorList.add(exception.toString()); | ||||
|       errorList.add(exception.getClass().getSimpleName()); | ||||
|       errorList.add( | ||||
|         "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); | ||||
|     } | ||||
|     return errorList; | ||||
|   } | ||||
| 
 | ||||
|   /** Generated class from Pigeon that represents data sent in messages. */ | ||||
|   public static final class NotificationMessageContent { | ||||
|     /** The textual body of the message. */ | ||||
|     private @Nullable String body; | ||||
| 
 | ||||
|     public @Nullable String getBody() { | ||||
|       return body; | ||||
|     } | ||||
| 
 | ||||
|     public void setBody(@Nullable String setterArg) { | ||||
|       this.body = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** The path and mime type of the media to show. */ | ||||
|     private @Nullable String mime; | ||||
| 
 | ||||
|     public @Nullable String getMime() { | ||||
|       return mime; | ||||
|     } | ||||
| 
 | ||||
|     public void setMime(@Nullable String setterArg) { | ||||
|       this.mime = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     private @Nullable String path; | ||||
| 
 | ||||
|     public @Nullable String getPath() { | ||||
|       return path; | ||||
|     } | ||||
| 
 | ||||
|     public void setPath(@Nullable String setterArg) { | ||||
|       this.path = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     public static final class Builder { | ||||
| 
 | ||||
|       private @Nullable String body; | ||||
| 
 | ||||
|       public @NonNull Builder setBody(@Nullable String setterArg) { | ||||
|         this.body = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable String mime; | ||||
| 
 | ||||
|       public @NonNull Builder setMime(@Nullable String setterArg) { | ||||
|         this.mime = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable String path; | ||||
| 
 | ||||
|       public @NonNull Builder setPath(@Nullable String setterArg) { | ||||
|         this.path = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       public @NonNull NotificationMessageContent build() { | ||||
|         NotificationMessageContent pigeonReturn = new NotificationMessageContent(); | ||||
|         pigeonReturn.setBody(body); | ||||
|         pigeonReturn.setMime(mime); | ||||
|         pigeonReturn.setPath(path); | ||||
|         return pigeonReturn; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     ArrayList<Object> toList() { | ||||
|       ArrayList<Object> toListResult = new ArrayList<Object>(3); | ||||
|       toListResult.add(body); | ||||
|       toListResult.add(mime); | ||||
|       toListResult.add(path); | ||||
|       return toListResult; | ||||
|     } | ||||
| 
 | ||||
|     static @NonNull NotificationMessageContent fromList(@NonNull ArrayList<Object> list) { | ||||
|       NotificationMessageContent pigeonResult = new NotificationMessageContent(); | ||||
|       Object body = list.get(0); | ||||
|       pigeonResult.setBody((String) body); | ||||
|       Object mime = list.get(1); | ||||
|       pigeonResult.setMime((String) mime); | ||||
|       Object path = list.get(2); | ||||
|       pigeonResult.setPath((String) path); | ||||
|       return pigeonResult; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** Generated class from Pigeon that represents data sent in messages. */ | ||||
|   public static final class NotificationMessage { | ||||
|     /** The sender of the message. */ | ||||
|     private @NonNull String sender; | ||||
| 
 | ||||
|     public @NonNull String getSender() { | ||||
|       return sender; | ||||
|     } | ||||
| 
 | ||||
|     public void setSender(@NonNull String setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"sender\" is null."); | ||||
|       } | ||||
|       this.sender = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** The jid of the sender. */ | ||||
|     private @NonNull String jid; | ||||
| 
 | ||||
|     public @NonNull String getJid() { | ||||
|       return jid; | ||||
|     } | ||||
| 
 | ||||
|     public void setJid(@NonNull String setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"jid\" is null."); | ||||
|       } | ||||
|       this.jid = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** The body of the message. */ | ||||
|     private @NonNull NotificationMessageContent content; | ||||
| 
 | ||||
|     public @NonNull NotificationMessageContent getContent() { | ||||
|       return content; | ||||
|     } | ||||
| 
 | ||||
|     public void setContent(@NonNull NotificationMessageContent setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"content\" is null."); | ||||
|       } | ||||
|       this.content = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** Milliseconds since epoch. */ | ||||
|     private @NonNull Long timestamp; | ||||
| 
 | ||||
|     public @NonNull Long getTimestamp() { | ||||
|       return timestamp; | ||||
|     } | ||||
| 
 | ||||
|     public void setTimestamp(@NonNull Long setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"timestamp\" is null."); | ||||
|       } | ||||
|       this.timestamp = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** The path to the avatar to use */ | ||||
|     private @Nullable String avatarPath; | ||||
| 
 | ||||
|     public @Nullable String getAvatarPath() { | ||||
|       return avatarPath; | ||||
|     } | ||||
| 
 | ||||
|     public void setAvatarPath(@Nullable String setterArg) { | ||||
|       this.avatarPath = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** Constructor is non-public to enforce null safety; use Builder. */ | ||||
|     NotificationMessage() {} | ||||
| 
 | ||||
|     public static final class Builder { | ||||
| 
 | ||||
|       private @Nullable String sender; | ||||
| 
 | ||||
|       public @NonNull Builder setSender(@NonNull String setterArg) { | ||||
|         this.sender = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable String jid; | ||||
| 
 | ||||
|       public @NonNull Builder setJid(@NonNull String setterArg) { | ||||
|         this.jid = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable NotificationMessageContent content; | ||||
| 
 | ||||
|       public @NonNull Builder setContent(@NonNull NotificationMessageContent setterArg) { | ||||
|         this.content = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable Long timestamp; | ||||
| 
 | ||||
|       public @NonNull Builder setTimestamp(@NonNull Long setterArg) { | ||||
|         this.timestamp = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable String avatarPath; | ||||
| 
 | ||||
|       public @NonNull Builder setAvatarPath(@Nullable String setterArg) { | ||||
|         this.avatarPath = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       public @NonNull NotificationMessage build() { | ||||
|         NotificationMessage pigeonReturn = new NotificationMessage(); | ||||
|         pigeonReturn.setSender(sender); | ||||
|         pigeonReturn.setJid(jid); | ||||
|         pigeonReturn.setContent(content); | ||||
|         pigeonReturn.setTimestamp(timestamp); | ||||
|         pigeonReturn.setAvatarPath(avatarPath); | ||||
|         return pigeonReturn; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     ArrayList<Object> toList() { | ||||
|       ArrayList<Object> toListResult = new ArrayList<Object>(5); | ||||
|       toListResult.add(sender); | ||||
|       toListResult.add(jid); | ||||
|       toListResult.add((content == null) ? null : content.toList()); | ||||
|       toListResult.add(timestamp); | ||||
|       toListResult.add(avatarPath); | ||||
|       return toListResult; | ||||
|     } | ||||
| 
 | ||||
|     static @NonNull NotificationMessage fromList(@NonNull ArrayList<Object> list) { | ||||
|       NotificationMessage pigeonResult = new NotificationMessage(); | ||||
|       Object sender = list.get(0); | ||||
|       pigeonResult.setSender((String) sender); | ||||
|       Object jid = list.get(1); | ||||
|       pigeonResult.setJid((String) jid); | ||||
|       Object content = list.get(2); | ||||
|       pigeonResult.setContent((content == null) ? null : NotificationMessageContent.fromList((ArrayList<Object>) content)); | ||||
|       Object timestamp = list.get(3); | ||||
|       pigeonResult.setTimestamp((timestamp == null) ? null : ((timestamp instanceof Integer) ? (Integer) timestamp : (Long) timestamp)); | ||||
|       Object avatarPath = list.get(4); | ||||
|       pigeonResult.setAvatarPath((String) avatarPath); | ||||
|       return pigeonResult; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** Generated class from Pigeon that represents data sent in messages. */ | ||||
|   public static final class MessagingNotification { | ||||
|     /** The title of the conversation. */ | ||||
|     private @NonNull String title; | ||||
| 
 | ||||
|     public @NonNull String getTitle() { | ||||
|       return title; | ||||
|     } | ||||
| 
 | ||||
|     public void setTitle(@NonNull String setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"title\" is null."); | ||||
|       } | ||||
|       this.title = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** The id of the notification. */ | ||||
|     private @NonNull Long id; | ||||
| 
 | ||||
|     public @NonNull Long getId() { | ||||
|       return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(@NonNull Long setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"id\" is null."); | ||||
|       } | ||||
|       this.id = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** The id of the notification channel the notification should appear on. */ | ||||
|     private @NonNull String channelId; | ||||
| 
 | ||||
|     public @NonNull String getChannelId() { | ||||
|       return channelId; | ||||
|     } | ||||
| 
 | ||||
|     public void setChannelId(@NonNull String setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"channelId\" is null."); | ||||
|       } | ||||
|       this.channelId = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** Messages to show. */ | ||||
|     private @NonNull List<NotificationMessage> messages; | ||||
| 
 | ||||
|     public @NonNull List<NotificationMessage> getMessages() { | ||||
|       return messages; | ||||
|     } | ||||
| 
 | ||||
|     public void setMessages(@NonNull List<NotificationMessage> setterArg) { | ||||
|       if (setterArg == null) { | ||||
|         throw new IllegalStateException("Nonnull field \"messages\" is null."); | ||||
|       } | ||||
|       this.messages = setterArg; | ||||
|     } | ||||
| 
 | ||||
|     /** Constructor is non-public to enforce null safety; use Builder. */ | ||||
|     MessagingNotification() {} | ||||
| 
 | ||||
|     public static final class Builder { | ||||
| 
 | ||||
|       private @Nullable String title; | ||||
| 
 | ||||
|       public @NonNull Builder setTitle(@NonNull String setterArg) { | ||||
|         this.title = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable Long id; | ||||
| 
 | ||||
|       public @NonNull Builder setId(@NonNull Long setterArg) { | ||||
|         this.id = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable String channelId; | ||||
| 
 | ||||
|       public @NonNull Builder setChannelId(@NonNull String setterArg) { | ||||
|         this.channelId = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       private @Nullable List<NotificationMessage> messages; | ||||
| 
 | ||||
|       public @NonNull Builder setMessages(@NonNull List<NotificationMessage> setterArg) { | ||||
|         this.messages = setterArg; | ||||
|         return this; | ||||
|       } | ||||
| 
 | ||||
|       public @NonNull MessagingNotification build() { | ||||
|         MessagingNotification pigeonReturn = new MessagingNotification(); | ||||
|         pigeonReturn.setTitle(title); | ||||
|         pigeonReturn.setId(id); | ||||
|         pigeonReturn.setChannelId(channelId); | ||||
|         pigeonReturn.setMessages(messages); | ||||
|         return pigeonReturn; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     ArrayList<Object> toList() { | ||||
|       ArrayList<Object> toListResult = new ArrayList<Object>(4); | ||||
|       toListResult.add(title); | ||||
|       toListResult.add(id); | ||||
|       toListResult.add(channelId); | ||||
|       toListResult.add(messages); | ||||
|       return toListResult; | ||||
|     } | ||||
| 
 | ||||
|     static @NonNull MessagingNotification fromList(@NonNull ArrayList<Object> list) { | ||||
|       MessagingNotification pigeonResult = new MessagingNotification(); | ||||
|       Object title = list.get(0); | ||||
|       pigeonResult.setTitle((String) title); | ||||
|       Object id = list.get(1); | ||||
|       pigeonResult.setId((id == null) ? null : ((id instanceof Integer) ? (Integer) id : (Long) id)); | ||||
|       Object channelId = list.get(2); | ||||
|       pigeonResult.setChannelId((String) channelId); | ||||
|       Object messages = list.get(3); | ||||
|       pigeonResult.setMessages((List<NotificationMessage>) messages); | ||||
|       return pigeonResult; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   private static class NotificationsImplementationApiCodec extends StandardMessageCodec { | ||||
|     public static final NotificationsImplementationApiCodec INSTANCE = new NotificationsImplementationApiCodec(); | ||||
| 
 | ||||
|     private NotificationsImplementationApiCodec() {} | ||||
| 
 | ||||
|     @Override | ||||
|     protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { | ||||
|       switch (type) { | ||||
|         case (byte) 128: | ||||
|           return MessagingNotification.fromList((ArrayList<Object>) readValue(buffer)); | ||||
|         case (byte) 129: | ||||
|           return NotificationMessage.fromList((ArrayList<Object>) readValue(buffer)); | ||||
|         case (byte) 130: | ||||
|           return NotificationMessageContent.fromList((ArrayList<Object>) readValue(buffer)); | ||||
|         default: | ||||
|           return super.readValueOfType(type, buffer); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { | ||||
|       if (value instanceof MessagingNotification) { | ||||
|         stream.write(128); | ||||
|         writeValue(stream, ((MessagingNotification) value).toList()); | ||||
|       } else if (value instanceof NotificationMessage) { | ||||
|         stream.write(129); | ||||
|         writeValue(stream, ((NotificationMessage) value).toList()); | ||||
|       } else if (value instanceof NotificationMessageContent) { | ||||
|         stream.write(130); | ||||
|         writeValue(stream, ((NotificationMessageContent) value).toList()); | ||||
|       } else { | ||||
|         super.writeValue(stream, value); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ | ||||
|   public interface NotificationsImplementationApi { | ||||
| 
 | ||||
|     void createNotificationChannel(@NonNull String title, @NonNull String id, @NonNull Boolean urgent); | ||||
| 
 | ||||
|     void showMessagingNotification(@NonNull MessagingNotification notification); | ||||
| 
 | ||||
|     /** The codec used by NotificationsImplementationApi. */ | ||||
|     static @NonNull MessageCodec<Object> getCodec() { | ||||
|       return NotificationsImplementationApiCodec.INSTANCE; | ||||
|     } | ||||
|     /**Sets up an instance of `NotificationsImplementationApi` to handle messages through the `binaryMessenger`. */ | ||||
|     static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable NotificationsImplementationApi api) { | ||||
|       { | ||||
|         BasicMessageChannel<Object> channel = | ||||
|             new BasicMessageChannel<>( | ||||
|                 binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.createNotificationChannel", getCodec()); | ||||
|         if (api != null) { | ||||
|           channel.setMessageHandler( | ||||
|               (message, reply) -> { | ||||
|                 ArrayList<Object> wrapped = new ArrayList<Object>(); | ||||
|                 ArrayList<Object> args = (ArrayList<Object>) message; | ||||
|                 String titleArg = (String) args.get(0); | ||||
|                 String idArg = (String) args.get(1); | ||||
|                 Boolean urgentArg = (Boolean) args.get(2); | ||||
|                 try { | ||||
|                   api.createNotificationChannel(titleArg, idArg, urgentArg); | ||||
|                   wrapped.add(0, null); | ||||
|                 } | ||||
|  catch (Throwable exception) { | ||||
|                   ArrayList<Object> wrappedError = wrapError(exception); | ||||
|                   wrapped = wrappedError; | ||||
|                 } | ||||
|                 reply.reply(wrapped); | ||||
|               }); | ||||
|         } else { | ||||
|           channel.setMessageHandler(null); | ||||
|         } | ||||
|       } | ||||
|       { | ||||
|         BasicMessageChannel<Object> channel = | ||||
|             new BasicMessageChannel<>( | ||||
|                 binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.showMessagingNotification", getCodec()); | ||||
|         if (api != null) { | ||||
|           channel.setMessageHandler( | ||||
|               (message, reply) -> { | ||||
|                 ArrayList<Object> wrapped = new ArrayList<Object>(); | ||||
|                 ArrayList<Object> args = (ArrayList<Object>) message; | ||||
|                 MessagingNotification notificationArg = (MessagingNotification) args.get(0); | ||||
|                 try { | ||||
|                   api.showMessagingNotification(notificationArg); | ||||
|                   wrapped.add(0, null); | ||||
|                 } | ||||
|  catch (Throwable exception) { | ||||
|                   ArrayList<Object> wrappedError = wrapError(exception); | ||||
|                   wrapped = wrappedError; | ||||
|                 } | ||||
|                 reply.reply(wrapped); | ||||
|               }); | ||||
|         } else { | ||||
|           channel.setMessageHandler(null); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,4 @@ | ||||
| <paths xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|    <!-- For testing --> | ||||
|    <cache-path name="file_picker" path="file_picker/"/> | ||||
| </paths> | ||||
| @ -0,0 +1,17 @@ | ||||
| import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart'; | ||||
| 
 | ||||
| class AndroidNotificationsImplementation extends NotificationsImplementation { | ||||
|   final NotificationsImplementationApi _api = NotificationsImplementationApi(); | ||||
| 
 | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> createNotificationChannel(String title, String id, bool urgent) async { | ||||
|     return _api.createNotificationChannel(title, id, urgent); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> showMessagingNotification(MessagingNotification notification) async { | ||||
|     return _api.showMessagingNotification(notification); | ||||
|   } | ||||
| } | ||||
| @ -2,6 +2,7 @@ import 'package:moxplatform_android/src/contacts_android.dart'; | ||||
| import 'package:moxplatform_android/src/crypto_android.dart'; | ||||
| import 'package:moxplatform_android/src/isolate_android.dart'; | ||||
| import 'package:moxplatform_android/src/media_android.dart'; | ||||
| import 'package:moxplatform_android/src/notifications_android.dart'; | ||||
| import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart'; | ||||
| 
 | ||||
| class MoxplatformAndroidPlugin extends MoxplatformInterface { | ||||
| @ -12,6 +13,7 @@ class MoxplatformAndroidPlugin extends MoxplatformInterface { | ||||
|     MoxplatformInterface.crypto = AndroidCryptographyImplementation(); | ||||
|     MoxplatformInterface.handler = AndroidIsolateHandler(); | ||||
|     MoxplatformInterface.media = AndroidMediaScannerImplementation(); | ||||
|     MoxplatformInterface.notifications = AndroidNotificationsImplementation(); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|  | ||||
| @ -41,4 +41,5 @@ dependencies: | ||||
| dev_dependencies: | ||||
|   flutter_test: | ||||
|     sdk: flutter | ||||
|   pigeon: 10.1.4 | ||||
|   very_good_analysis: ^3.0.1 | ||||
|  | ||||
| @ -9,4 +9,7 @@ export 'src/isolate.dart'; | ||||
| export 'src/isolate_stub.dart'; | ||||
| export 'src/media.dart'; | ||||
| export 'src/media_stub.dart'; | ||||
| export 'src/notifications.dart'; | ||||
| export 'src/notifications.g.dart'; | ||||
| export 'src/notifications_stub.dart'; | ||||
| export 'src/service.dart'; | ||||
|  | ||||
| @ -6,6 +6,8 @@ import 'package:moxplatform_platform_interface/src/isolate.dart'; | ||||
| import 'package:moxplatform_platform_interface/src/isolate_stub.dart'; | ||||
| import 'package:moxplatform_platform_interface/src/media.dart'; | ||||
| import 'package:moxplatform_platform_interface/src/media_stub.dart'; | ||||
| import 'package:moxplatform_platform_interface/src/notifications.dart'; | ||||
| import 'package:moxplatform_platform_interface/src/notifications_stub.dart'; | ||||
| import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | ||||
| 
 | ||||
| abstract class MoxplatformInterface extends PlatformInterface { | ||||
| @ -17,6 +19,7 @@ abstract class MoxplatformInterface extends PlatformInterface { | ||||
|   static MediaScannerImplementation media = StubMediaScannerImplementation(); | ||||
|   static CryptographyImplementation crypto = StubCryptographyImplementation(); | ||||
|   static ContactsImplementation contacts = StubContactsImplementation(); | ||||
|   static NotificationsImplementation notifications = StubNotificationsImplementation(); | ||||
| 
 | ||||
|   /// Return the current platform name. | ||||
|   Future<String?> getPlatformName(); | ||||
|  | ||||
| @ -0,0 +1,7 @@ | ||||
| import 'package:moxplatform_platform_interface/src/notifications.g.dart'; | ||||
| 
 | ||||
| abstract class NotificationsImplementation { | ||||
|   Future<void> createNotificationChannel(String title, String id, bool urgent); | ||||
| 
 | ||||
|   Future<void> showMessagingNotification(MessagingNotification notification); | ||||
| } | ||||
| @ -0,0 +1,216 @@ | ||||
| // Autogenerated from Pigeon (v10.1.4), do not edit directly. | ||||
| // See also: https://pub.dev/packages/pigeon | ||||
| // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import | ||||
| 
 | ||||
| import 'dart:async'; | ||||
| import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; | ||||
| 
 | ||||
| import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; | ||||
| import 'package:flutter/services.dart'; | ||||
| 
 | ||||
| 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({ | ||||
|     required this.sender, | ||||
|     required this.jid, | ||||
|     required this.content, | ||||
|     required this.timestamp, | ||||
|     this.avatarPath, | ||||
|   }); | ||||
| 
 | ||||
|   /// 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?>[ | ||||
|       sender, | ||||
|       jid, | ||||
|       content.encode(), | ||||
|       timestamp, | ||||
|       avatarPath, | ||||
|     ]; | ||||
|   } | ||||
| 
 | ||||
|   static NotificationMessage decode(Object result) { | ||||
|     result as List<Object?>; | ||||
|     return NotificationMessage( | ||||
|       sender: result[0]! as String, | ||||
|       jid: result[1]! as String, | ||||
|       content: NotificationMessageContent.decode(result[2]! as List<Object?>), | ||||
|       timestamp: result[3]! as int, | ||||
|       avatarPath: result[4] as String?, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class MessagingNotification { | ||||
|   MessagingNotification({ | ||||
|     required this.title, | ||||
|     required this.id, | ||||
|     required this.channelId, | ||||
|     required this.messages, | ||||
|   }); | ||||
| 
 | ||||
|   /// 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; | ||||
| 
 | ||||
|   /// Messages to show. | ||||
|   List<NotificationMessage?> messages; | ||||
| 
 | ||||
|   Object encode() { | ||||
|     return <Object?>[ | ||||
|       title, | ||||
|       id, | ||||
|       channelId, | ||||
|       messages, | ||||
|     ]; | ||||
|   } | ||||
| 
 | ||||
|   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, | ||||
|       messages: (result[3] as List<Object?>?)!.cast<NotificationMessage?>(), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class _NotificationsImplementationApiCodec extends StandardMessageCodec { | ||||
|   const _NotificationsImplementationApiCodec(); | ||||
|   @override | ||||
|   void writeValue(WriteBuffer buffer, Object? value) { | ||||
|     if (value is MessagingNotification) { | ||||
|       buffer.putUint8(128); | ||||
|       writeValue(buffer, value.encode()); | ||||
|     } else if (value is NotificationMessage) { | ||||
|       buffer.putUint8(129); | ||||
|       writeValue(buffer, value.encode()); | ||||
|     } else if (value is NotificationMessageContent) { | ||||
|       buffer.putUint8(130); | ||||
|       writeValue(buffer, value.encode()); | ||||
|     } else { | ||||
|       super.writeValue(buffer, value); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Object? readValueOfType(int type, ReadBuffer buffer) { | ||||
|     switch (type) { | ||||
|       case 128:  | ||||
|         return MessagingNotification.decode(readValue(buffer)!); | ||||
|       case 129:  | ||||
|         return NotificationMessage.decode(readValue(buffer)!); | ||||
|       case 130:  | ||||
|         return NotificationMessageContent.decode(readValue(buffer)!); | ||||
|       default: | ||||
|         return super.readValueOfType(type, buffer); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class NotificationsImplementationApi { | ||||
|   /// Constructor for [NotificationsImplementationApi].  The [binaryMessenger] named argument is | ||||
|   /// available for dependency injection.  If it is left null, the default | ||||
|   /// BinaryMessenger will be used which routes to the host platform. | ||||
|   NotificationsImplementationApi({BinaryMessenger? binaryMessenger}) | ||||
|       : _binaryMessenger = binaryMessenger; | ||||
|   final BinaryMessenger? _binaryMessenger; | ||||
| 
 | ||||
|   static const MessageCodec<Object?> codec = _NotificationsImplementationApiCodec(); | ||||
| 
 | ||||
|   Future<void> createNotificationChannel(String arg_title, String arg_id, bool arg_urgent) async { | ||||
|     final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>( | ||||
|         'dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.createNotificationChannel', codec, | ||||
|         binaryMessenger: _binaryMessenger); | ||||
|     final List<Object?>? replyList = | ||||
|         await channel.send(<Object?>[arg_title, arg_id, arg_urgent]) 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.NotificationsImplementationApi.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; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| import 'package:moxplatform_platform_interface/src/notifications.g.dart'; | ||||
| import 'package:moxplatform_platform_interface/src/notifications.dart'; | ||||
| 
 | ||||
| class StubNotificationsImplementation extends NotificationsImplementation { | ||||
|   @override | ||||
|   Future<void> createNotificationChannel(String title, String id, bool urgent) async {} | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> showMessagingNotification(MessagingNotification notification) async {} | ||||
| } | ||||
							
								
								
									
										77
									
								
								pigeons/notifications.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								pigeons/notifications.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| import 'package:pigeon/pigeon.dart'; | ||||
| 
 | ||||
| @ConfigurePigeon( | ||||
|   PigeonOptions( | ||||
|     dartOut: 'packages/moxplatform_platform_interface/lib/src/notifications.g.dart', | ||||
|     //kotlinOut: 'packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Notifications.g.kt', | ||||
|     //kotlinOptions: KotlinOptions( | ||||
|     //  package: 'me.polynom.moxplatform_android', | ||||
|     //), | ||||
|     javaOut: 'packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Notifications.java', | ||||
|     javaOptions: JavaOptions( | ||||
|       package: 'me.polynom.moxplatform_android', | ||||
|     ), | ||||
|   ), | ||||
| ) | ||||
| 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, | ||||
|   ); | ||||
| 
 | ||||
|   /// 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.messages, this.channelId); | ||||
| 
 | ||||
|   /// 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; | ||||
| 
 | ||||
|   /// Messages to show. | ||||
|   final List<NotificationMessage?> messages; | ||||
| } | ||||
| 
 | ||||
| @HostApi() | ||||
| abstract class NotificationsImplementationApi { | ||||
|   void createNotificationChannel(String title, String id, bool urgent); | ||||
| 
 | ||||
|   void showMessagingNotification(MessagingNotification notification); | ||||
| } | ||||
| @ -4,3 +4,4 @@ environment: | ||||
|   sdk: '>=2.18.0 <3.0.0' | ||||
| dev_dependencies: | ||||
|   melos: ^3.1.1 | ||||
|   pigeon: 10.1.4 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user