Skip to content

Commit

Permalink
feat: chat events listener
Browse files Browse the repository at this point in the history
  • Loading branch information
Mastersam07 committed Oct 3, 2024
1 parent 224ac7d commit e690e81
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 37 deletions.
60 changes: 44 additions & 16 deletions android/src/main/java/tech/mastersam/livechat/LivechatPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,23 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.EventChannel.StreamHandler;

import com.livechatinc.inappchat.ChatWindowConfiguration;
import com.livechatinc.inappchat.ChatWindowErrorType;
import com.livechatinc.inappchat.ChatWindowView;
import com.livechatinc.inappchat.models.NewMessageModel;

import java.util.HashMap;

public class LivechatPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
private MethodChannel channel;
private MethodChannel methodChannel;
private EventChannel eventChannel;
private Context context;
private Activity activity;
private ChatWindowView windowView;
private EventChannel.EventSink events;

@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
Expand All @@ -36,8 +42,21 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin
}

private void setupChannel(BinaryMessenger messenger) {
channel = new MethodChannel(messenger, "livechatt");
channel.setMethodCallHandler(this);
methodChannel = new MethodChannel(messenger, "livechatt");
methodChannel.setMethodCallHandler(this);

eventChannel = new EventChannel(messenger, "livechatt/events");
eventChannel.setStreamHandler(new StreamHandler() {
@Override
public void onListen(Object arguments, EventChannel.EventSink eventSink) {
events = eventSink; // Capture the event sink for pushing events later
}

@Override
public void onCancel(Object arguments) {
events = null; // Clear the event sink when not in use
}
});
}

@Override
Expand Down Expand Up @@ -94,12 +113,14 @@ public void onNewMessage(NewMessageModel message) {
// Notify Flutter about the new message
HashMap<String, Object> messageData = new HashMap<>();
messageData.put("text", message.getText());
channel.invokeMethod("onNewMessage", messageData);
events.success(messageData);
}

@Override
public void onChatWindowVisibilityChanged(boolean visible) {
channel.invokeMethod("onChatVisibilityChanged", visible);
if (events != null) {
events.success("onChatWindowVisibilityChanged: " + visible);
}
}

@Override
Expand All @@ -114,17 +135,21 @@ public void onRequestAudioPermissions(String[] permissions, int requestCode) {

@Override
public boolean onError(ChatWindowErrorType errorType, int errorCode, String errorDescription) {
HashMap<String, Object> errorData = new HashMap<>();
errorData.put("errorType", errorType.toString());
errorData.put("errorCode", errorCode);
errorData.put("errorDescription", errorDescription);
channel.invokeMethod("onError", errorData);
if (events != null) {
HashMap<String, Object> errorData = new HashMap<>();
errorData.put("errorType", errorType.toString());
errorData.put("errorCode", errorCode);
errorData.put("errorDescription", errorDescription);
events.success(errorData); // Push error event to Flutter
}
return true;
}

@Override
public boolean handleUri(Uri uri) {
channel.invokeMethod("handleUri", uri.toString());
if (events != null) {
events.success("handleUri: " + uri.toString());
}
return true;
}
});
Expand Down Expand Up @@ -162,13 +187,16 @@ public void onAttachedToActivity(ActivityPluginBinding binding) {

@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
teardownChannel();
teardownChannels();
}

private void teardownChannel() {
if (channel != null) {
channel.setMethodCallHandler(null);
channel = null;
private void teardownChannels() {
if (methodChannel != null) {
methodChannel.setMethodCallHandler(null);
methodChannel = null;
}
if (eventChannel != null) {
eventChannel.setStreamHandler(null);
}
}

Expand Down
32 changes: 11 additions & 21 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:livechatt/livechatt.dart';
Expand Down Expand Up @@ -37,26 +36,17 @@ class _SupportState extends State<Support> {
@override
void initState() {
super.initState();
initPlatformState();
}

// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String? platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await Livechat.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}

// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;

setState(() {
_platformVersion = platformVersion;
Livechat.newMessages.listen((message) {
print('New message: $message');
});
Livechat.visibilityChanges.listen((isVisible) {
print('Chat window is visible: $isVisible');
});
Livechat.errors.listen((error) {
print('Error: ${error['errorDescription']}');
});
Livechat.uriHandlers.listen((uri) {
print('Custom URI clicked: $uri');
});
}

Expand Down
31 changes: 31 additions & 0 deletions lib/livechatt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/services.dart';

class Livechat {
static const MethodChannel _channel = const MethodChannel('livechatt');
static const EventChannel _eventChannel = EventChannel('livechatt/events');

/// Get platform version
static Future<String?> get platformVersion async {
Expand All @@ -23,4 +24,34 @@ class Livechat {
'customParams': customParams,
});
}

/// Clear chat session
static Future<void> clearSession() async {
await _channel.invokeMethod('clearSession');
}

/// Listen to chat events: new messages, errors, visibility changes, etc.
static Stream<dynamic> get chatEvents =>
_eventChannel.receiveBroadcastStream();

/// Start listening for new messages
static Stream<String> get newMessages => chatEvents
.where((event) => event is Map && event.containsKey('text'))
.map((event) => event['text'] as String);

/// Start listening for visibility changes
static Stream<bool> get visibilityChanges => chatEvents
.where((event) =>
event is String && event.contains('onChatWindowVisibilityChanged'))
.map((event) => event.endsWith('true'));

/// Start listening for errors
static Stream<Map<String, dynamic>> get errors => chatEvents
.where((event) => event is Map && event.containsKey('errorDescription'))
.map((event) => event as Map<String, dynamic>);

/// Handle URIs
static Stream<String> get uriHandlers => chatEvents
.where((event) => event is String && event.contains('handleUri'))
.map((event) => event.replaceFirst('handleUri: ', ''));
}

0 comments on commit e690e81

Please sign in to comment.