135 lines
6.3 KiB
Markdown
135 lines
6.3 KiB
Markdown
# mattermost_push_plugin
|
|
|
|
An Android-first Flutter plugin for receiving Mattermost push notifications, displaying system notifications, handling tap events, processing inline replies, delivering ACKs, and securely storing device tokens, authentication tokens, and signing keys.
|
|
|
|
---
|
|
|
|
## Support Matrix
|
|
|
|
| Platform | Support Status | Native Features Implemented |
|
|
|---|---|---|
|
|
| **Android** | **Full (Production Ready)** | Kotlin, Native FCM Service, Room DB, JJWT Verification, OkHttp ACK Client, Notification Builder, Inline Reply Receiver, Dismiss Receiver |
|
|
| **iOS** | No-op Scaffold (Stub) | Future roadmap milestone |
|
|
| **macOS** | No-op Scaffold (Stub) | Future roadmap milestone |
|
|
|
|
---
|
|
|
|
## Core Responsibilities
|
|
|
|
This plugin isolates the Mattermost push notification domain logic from the host application.
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[Mattermost Server] -->|Secure JWT Push| B(Plugin Native FCM Service)
|
|
B -->|1. Signature Verification JJWT| C{Valid?}
|
|
C -->|Yes| D[2. Store & Build Notification]
|
|
C -->|No| E[Drop Push]
|
|
D -->|3. OkHttp ACK API| A
|
|
D -->|4. Display System Notification| F(Android Status Bar)
|
|
F -->|Tap Notification| G[5. Method Channel Opened Event]
|
|
F -->|Inline Reply| H[6. Broadcast Reply Receiver]
|
|
H -->|Deliver via OkHttp| A
|
|
G -->|Flutter Stream| I(Host App Navigation)
|
|
```
|
|
|
|
---
|
|
|
|
## Public Dart API Reference
|
|
|
|
Get the singleton instance via `MattermostPushPlugin.instance`.
|
|
|
|
### 1. Initialization
|
|
|
|
Initialize the plugin channel subscriptions, listen to token refreshes, and request notification permissions:
|
|
|
|
```dart
|
|
import 'package:mattermost_push_plugin/mattermost_push_plugin.dart';
|
|
|
|
await MattermostPushPlugin.instance.initialize();
|
|
```
|
|
|
|
### 2. Streams & Callbacks
|
|
|
|
Set up listeners and navigation callbacks inside your app initialization flow:
|
|
|
|
```dart
|
|
// 1. Listen to raw native notification events (Message, Clear, Session, etc.)
|
|
MattermostPushPlugin.instance.onNotification.listen((data) {
|
|
print("Raw push received: $data");
|
|
});
|
|
|
|
// 2. Listen to user interaction (notification tap) events
|
|
MattermostPushPlugin.instance.onNotificationOpened.listen((event) {
|
|
print("Notification clicked! Channel: ${event.channelId}, Root: ${event.rootId}");
|
|
});
|
|
|
|
// 3. Register navigation handlers (automatically triggered by onNotificationOpened)
|
|
MattermostPushPlugin.instance.onNavigateToChannel = (String serverUrl, String channelId) {
|
|
// Navigate the app to the specific channel
|
|
};
|
|
|
|
MattermostPushPlugin.instance.onNavigateToThread = (String serverUrl, String rootId) {
|
|
// Navigate the app to the specific CRT thread
|
|
};
|
|
|
|
// 4. Triggered when the device token is registered/refreshed
|
|
MattermostPushPlugin.instance.onDeviceTokenReady = (String deviceToken) {
|
|
// e.g. "android_rn-v2:YOUR_FCM_TOKEN"
|
|
// Send this token to the Mattermost server for token registration
|
|
};
|
|
```
|
|
|
|
### 3. Credential & Signing Key Storing
|
|
|
|
Securely write server-specific secrets to native persistent storage. These are required by the native service to decrypt and verify the authenticity of push messages.
|
|
|
|
```dart
|
|
// Save authenticating token for HTTP ACK requests
|
|
await MattermostPushPlugin.instance.setAuthToken(
|
|
"https://mattermost.example.com",
|
|
"YOUR_USER_AUTH_TOKEN",
|
|
identifier: "user_session_id", // optional
|
|
);
|
|
|
|
// Save public signing key for verification
|
|
await MattermostPushPlugin.instance.setSigningKey(
|
|
"https://mattermost.example.com",
|
|
"YOUR_SERVER_PUBLIC_SIGNING_KEY",
|
|
);
|
|
|
|
// Clear token on logout
|
|
await MattermostPushPlugin.instance.clearAuthToken("https://mattermost.example.com");
|
|
|
|
// Fetch the formatted device token
|
|
String? token = await MattermostPushPlugin.instance.getDeviceToken();
|
|
```
|
|
|
|
---
|
|
|
|
## Host App Integration & Responsibilities
|
|
|
|
The host application (`apps/mobile`) acts as the consumer of the plugin and is responsible for:
|
|
|
|
1. **Firebase Configuration**: Include the `google-services.json` in `android/app/` and initialize Firebase in the Dart main block.
|
|
2. **Authentication Flow**: Call `setAuthToken` and `setSigningKey` on successful Mattermost login, and `clearAuthToken` on logout.
|
|
3. **App Navigation**: Implement `onNavigateToChannel` and `onNavigateToThread` callbacks to route users inside the Flutter UI.
|
|
4. **FCM Token Registration**: Send the formatted token received in `onDeviceTokenReady` to the Mattermost server.
|
|
|
|
### Firebase Messaging Manifest Collision Guard
|
|
This plugin implements a custom Android FCM service (`MattermostFirebaseMessagingService`) that consumes incoming FCM payloads. To prevent manifest merge collisions with the standard Flutter `firebase_messaging` library, the plugin's `AndroidManifest.xml` disables the generic Flutter Firebase service via `tools:node="remove"`.
|
|
Ensure that the host app does not redeclare duplicate FCM services unless explicitly configured to do so.
|
|
|
|
---
|
|
|
|
## Verification & Manual Smoke Testing Checklist
|
|
|
|
Since full end-to-end FCM flows cannot be automated in headless test runners, verify functionality manually using the following checklist:
|
|
|
|
- [ ] **FCM Payload Receipt**: Verify that sending an FCM notification payload targeting the host application successfully wakes up `MattermostFirebaseMessagingService`.
|
|
- [ ] **Signature Verification**: Ensure that a valid push payload signed by the Mattermost server's private key compiles and passes the native JJWT verification using the stored signing key.
|
|
- [ ] **Notification Display**: Verify the system notification builds with the correct title, message, avatar (if supplied), and CRT threading hierarchy.
|
|
- [ ] **ACK Delivery**: Verify the plugin sends a HTTP `POST` receipt delivery ACK back to the Mattermost server and logs a `200 OK` or `201 Created` response.
|
|
- [ ] **Notification Tap & Route**: Tap the system notification and verify the host app launches/resumes, triggers the `onNotificationOpened` stream, and executes the designated navigation callback.
|
|
- [ ] **Inline Reply Action**: Click "Reply" directly on the system notification. Type a reply, press send, and verify the native broadcast receiver intercepts the text, writes it to the local Room database, and sends it via HTTP to the Mattermost API.
|
|
- [ ] **Notification Dismiss (Clear)**: Swipe away or dismiss a notification and verify the `NotificationDismissService` is triggered, clearing the corresponding notification records natively.
|
|
- [ ] **Token Storage & Generation**: Ensure the generated token has the correct `android_rn-v2:` prefix and is saved securely in the device's native database/shared preferences.
|