feat: Add input status related API; update synchronization monitoring related API.
This commit is contained in:
parent
cade0091a7
commit
29b43d03ac
@ -2,6 +2,7 @@ package io.openim.flutter_openim_sdk.listener;
|
|||||||
|
|
||||||
import io.openim.flutter_openim_sdk.util.CommonUtil;
|
import io.openim.flutter_openim_sdk.util.CommonUtil;
|
||||||
|
|
||||||
|
|
||||||
public class OnConversationListener implements open_im_sdk_callback.OnConversationListener {
|
public class OnConversationListener implements open_im_sdk_callback.OnConversationListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -213,4 +213,22 @@ public class ConversationManager extends BaseManager {
|
|||||||
value(methodCall, "ex")
|
value(methodCall, "ex")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void changeInputStates(MethodCall methodCall, MethodChannel.Result result) {
|
||||||
|
Open_im_sdk.changeInputStates(
|
||||||
|
new OnBaseListener(result, methodCall),
|
||||||
|
value(methodCall, "operationID"),
|
||||||
|
value(methodCall, "conversationID"),
|
||||||
|
value(methodCall, "focus")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getInputStates(MethodCall methodCall, MethodChannel.Result result) {
|
||||||
|
Open_im_sdk.getInputStates(
|
||||||
|
new OnBaseListener(result, methodCall),
|
||||||
|
value(methodCall, "operationID"),
|
||||||
|
value(methodCall, "conversationID"),
|
||||||
|
value(methodCall, "userID")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '11.0'
|
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
@ -2,8 +2,8 @@ PODS:
|
|||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_openim_sdk (0.0.1):
|
- flutter_openim_sdk (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- OpenIMSDKCore (= 3.4.0)
|
- OpenIMSDKCore (= 3.8.1-rc.0)
|
||||||
- OpenIMSDKCore (3.4.0)
|
- OpenIMSDKCore (3.8.1-rc.0)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
@ -20,10 +20,10 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_openim_sdk/ios"
|
:path: ".symlinks/plugins/flutter_openim_sdk/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_openim_sdk: 54d1c836ff60ebb5b99d246521ef0cb1d834fb13
|
flutter_openim_sdk: 754e4ad0177918ce2c37dfba63973db26ce89c90
|
||||||
OpenIMSDKCore: 47e0e830afe0d2dd905ad3dda255e6a6d26a555c
|
OpenIMSDKCore: 0c92e9e3eb2a91b6b6528e7781a1e28ed42bc518
|
||||||
|
|
||||||
PODFILE CHECKSUM: 7368163408c647b7eb699d0d788ba6718e18fb8d
|
PODFILE CHECKSUM: d4ba08011ff3d270b662299a448a7c436eb30089
|
||||||
|
|
||||||
COCOAPODS: 1.13.0
|
COCOAPODS: 1.14.3
|
||||||
|
@ -344,6 +344,7 @@
|
|||||||
DEVELOPMENT_TEAM = BDLHL8GNFV;
|
DEVELOPMENT_TEAM = BDLHL8GNFV;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -476,6 +477,7 @@
|
|||||||
DEVELOPMENT_TEAM = BDLHL8GNFV;
|
DEVELOPMENT_TEAM = BDLHL8GNFV;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@ -500,6 +502,7 @@
|
|||||||
DEVELOPMENT_TEAM = BDLHL8GNFV;
|
DEVELOPMENT_TEAM = BDLHL8GNFV;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -21,14 +21,17 @@ public class ConversationManager: BaseServiceManager {
|
|||||||
self["setConversationPrivateChat"] = setConversationPrivateChat
|
self["setConversationPrivateChat"] = setConversationPrivateChat
|
||||||
self["clearConversationAndDeleteAllMsg"] = clearConversationAndDeleteAllMsg
|
self["clearConversationAndDeleteAllMsg"] = clearConversationAndDeleteAllMsg
|
||||||
self["deleteConversationAndDeleteAllMsg"] = deleteConversationAndDeleteAllMsg
|
self["deleteConversationAndDeleteAllMsg"] = deleteConversationAndDeleteAllMsg
|
||||||
self["deleteAllConversationFromLocal"] = deleteAllConversationFromLocal
|
|
||||||
self["resetConversationGroupAtType"] = resetConversationGroupAtType
|
self["resetConversationGroupAtType"] = resetConversationGroupAtType
|
||||||
self["getAtAllTag"] = getAtAllTag
|
self["getAtAllTag"] = getAtAllTag
|
||||||
self["setGlobalRecvMessageOpt"] = setGlobalRecvMessageOpt
|
self["setGlobalRecvMessageOpt"] = setGlobalRecvMessageOpt
|
||||||
self["setConversationBurnDuration"] = setConversationBurnDuration
|
self["setConversationBurnDuration"] = setConversationBurnDuration
|
||||||
|
self["setConversationIsMsgDestruct"] = setConversationIsMsgDestruct
|
||||||
|
self["setConversationMsgDestructTime"] = setConversationMsgDestructTime
|
||||||
self["hideAllConversations"] = hideAllConversations
|
self["hideAllConversations"] = hideAllConversations
|
||||||
self["searchConversation"] = searchConversation
|
self["searchConversation"] = searchConversation
|
||||||
self["setConversationEx"] = setConversationEx
|
self["setConversationEx"] = setConversationEx
|
||||||
|
self["changeInputStates"] = changeInputStates
|
||||||
|
self["getInputStates"] = getInputStates
|
||||||
}
|
}
|
||||||
|
|
||||||
func setConversationListener(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
func setConversationListener(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
@ -116,8 +119,16 @@ public class ConversationManager: BaseServiceManager {
|
|||||||
Open_im_sdkSetConversationBurnDuration(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[int32: "burnDuration"])
|
Open_im_sdkSetConversationBurnDuration(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[int32: "burnDuration"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setConversationIsMsgDestruct(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
|
Open_im_sdkSetConversationIsMsgDestruct(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[bool: "isMsgDestruct"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func setConversationMsgDestructTime(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
|
Open_im_sdkSetConversationMsgDestructTime(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[int64: "duration"])
|
||||||
|
}
|
||||||
|
|
||||||
func hideAllConversations(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
func hideAllConversations(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
Open_im_sdkHideAllConversations(BaseCallback(result: result), methodCall[string: "operationID"])
|
Open_im_sdkHideAllConversations(BaseCallback(result: result), methodCall[string: "operationID"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchConversation(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
func searchConversation(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
@ -125,7 +136,15 @@ public class ConversationManager: BaseServiceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setConversationEx(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
func setConversationEx(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
Open_im_sdkSetConversationEx(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[jsonString: "ex"])
|
Open_im_sdkSetConversationEx(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[string: "ex"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func changeInputStates(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
|
Open_im_sdkChangeInputStates(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[bool: "focus"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInputStates(methodCall: FlutterMethodCall, result: @escaping FlutterResult){
|
||||||
|
Open_im_sdkGetInputStates(BaseCallback(result: result), methodCall[string: "operationID"], methodCall[string: "conversationID"], methodCall[string: "userID"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,5 +34,6 @@ export 'src/models/message.dart';
|
|||||||
export 'src/models/notification_info.dart';
|
export 'src/models/notification_info.dart';
|
||||||
export 'src/models/search_info.dart';
|
export 'src/models/search_info.dart';
|
||||||
export 'src/models/user_info.dart';
|
export 'src/models/user_info.dart';
|
||||||
|
export 'src/models/input_status_changed_data.dart';
|
||||||
export 'src/openim.dart';
|
export 'src/openim.dart';
|
||||||
export 'src/utils.dart';
|
export 'src/utils.dart';
|
||||||
|
@ -5,6 +5,7 @@ class OnConnectListener {
|
|||||||
Function()? onConnecting;
|
Function()? onConnecting;
|
||||||
Function()? onKickedOffline;
|
Function()? onKickedOffline;
|
||||||
Function()? onUserTokenExpired;
|
Function()? onUserTokenExpired;
|
||||||
|
Function()? onUserTokenInvalid;
|
||||||
|
|
||||||
OnConnectListener({
|
OnConnectListener({
|
||||||
this.onConnectFailed,
|
this.onConnectFailed,
|
||||||
@ -12,6 +13,7 @@ class OnConnectListener {
|
|||||||
this.onConnecting,
|
this.onConnecting,
|
||||||
this.onKickedOffline,
|
this.onKickedOffline,
|
||||||
this.onUserTokenExpired,
|
this.onUserTokenExpired,
|
||||||
|
this.onUserTokenInvalid,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// SDK failed to connect to the server
|
/// SDK failed to connect to the server
|
||||||
@ -38,4 +40,8 @@ class OnConnectListener {
|
|||||||
void userTokenExpired() {
|
void userTokenExpired() {
|
||||||
onUserTokenExpired?.call();
|
onUserTokenExpired?.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void userTokenInvalid() {
|
||||||
|
onUserTokenInvalid?.call();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
|
import 'package:flutter_openim_sdk/flutter_openim_sdk.dart';
|
||||||
|
|
||||||
/// Conversation Listener
|
/// Conversation Listener
|
||||||
@ -5,17 +6,21 @@ class OnConversationListener {
|
|||||||
Function(List<ConversationInfo> list)? onConversationChanged;
|
Function(List<ConversationInfo> list)? onConversationChanged;
|
||||||
Function(List<ConversationInfo> list)? onNewConversation;
|
Function(List<ConversationInfo> list)? onNewConversation;
|
||||||
Function(int count)? onTotalUnreadMessageCountChanged;
|
Function(int count)? onTotalUnreadMessageCountChanged;
|
||||||
Function()? onSyncServerFailed;
|
Function(bool? reinstalled)? onSyncServerStart;
|
||||||
Function()? onSyncServerFinish;
|
Function(int? progress)? onSyncServerProgress;
|
||||||
Function()? onSyncServerStart;
|
Function(bool? reinstalled)? onSyncServerFinish;
|
||||||
|
Function(bool? reinstalled)? onSyncServerFailed;
|
||||||
|
ValueChanged<InputStatusChangedData>? onInputStatusChanged;
|
||||||
|
|
||||||
OnConversationListener({
|
OnConversationListener({
|
||||||
this.onConversationChanged,
|
this.onConversationChanged,
|
||||||
this.onNewConversation,
|
this.onNewConversation,
|
||||||
this.onTotalUnreadMessageCountChanged,
|
this.onTotalUnreadMessageCountChanged,
|
||||||
this.onSyncServerFailed,
|
|
||||||
this.onSyncServerFinish,
|
|
||||||
this.onSyncServerStart,
|
this.onSyncServerStart,
|
||||||
|
this.onSyncServerProgress,
|
||||||
|
this.onSyncServerFinish,
|
||||||
|
this.onSyncServerFailed,
|
||||||
|
this.onInputStatusChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Conversations have changed
|
/// Conversations have changed
|
||||||
@ -33,15 +38,23 @@ class OnConversationListener {
|
|||||||
onTotalUnreadMessageCountChanged?.call(count);
|
onTotalUnreadMessageCountChanged?.call(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncServerFailed() {
|
void syncServerStart(bool? reinstalled) {
|
||||||
onSyncServerFailed?.call();
|
onSyncServerStart?.call(reinstalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncServerFinish() {
|
void syncServerProgress(int? progress) {
|
||||||
onSyncServerFinish?.call();
|
onSyncServerProgress?.call(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncServerStart() {
|
void syncServerFailed(bool? reinstalled) {
|
||||||
onSyncServerStart?.call();
|
onSyncServerFailed?.call(reinstalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncServerFinish(bool? reinstalled) {
|
||||||
|
onSyncServerFinish?.call(reinstalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void conversationUserInputStatusChanged(InputStatusChangedData data) {
|
||||||
|
onInputStatusChanged?.call(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,14 +361,13 @@ class ConversationManager {
|
|||||||
String? ex,
|
String? ex,
|
||||||
String? operationID,
|
String? operationID,
|
||||||
}) {
|
}) {
|
||||||
return _channel
|
return _channel.invokeMethod(
|
||||||
.invokeMethod(
|
'setConversationEx',
|
||||||
'setConversationEx',
|
_buildParam({
|
||||||
_buildParam({
|
'conversationID': conversationID,
|
||||||
'conversationID': conversationID,
|
'ex': ex,
|
||||||
'ex': ex,
|
"operationID": Utils.checkOperationID(operationID),
|
||||||
"operationID": Utils.checkOperationID(operationID),
|
}));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Custom Sort for Conversation List
|
/// Custom Sort for Conversation List
|
||||||
@ -391,6 +390,45 @@ class ConversationManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Future changeInputStates({
|
||||||
|
required String conversationID,
|
||||||
|
required bool focus,
|
||||||
|
String? operationID,
|
||||||
|
}) {
|
||||||
|
return _channel.invokeMethod(
|
||||||
|
'changeInputStates',
|
||||||
|
_buildParam(
|
||||||
|
{
|
||||||
|
'focus': focus,
|
||||||
|
'conversationID': conversationID,
|
||||||
|
'operationID': Utils.checkOperationID(operationID),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<int>?> getInputStates(
|
||||||
|
String conversationID,
|
||||||
|
String userID, {
|
||||||
|
String? operationID,
|
||||||
|
}) {
|
||||||
|
return _channel
|
||||||
|
.invokeMethod(
|
||||||
|
'getInputStates',
|
||||||
|
_buildParam(
|
||||||
|
{
|
||||||
|
'conversationID': conversationID,
|
||||||
|
'userID': userID,
|
||||||
|
'operationID': Utils.checkOperationID(operationID),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.then((value) {
|
||||||
|
final result = Utils.toListMap(value);
|
||||||
|
return List<int>.from(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static Map _buildParam(Map param) {
|
static Map _buildParam(Map param) {
|
||||||
param["ManagerName"] = "conversationManager";
|
param["ManagerName"] = "conversationManager";
|
||||||
log('param: $param');
|
log('param: $param');
|
||||||
|
@ -56,6 +56,9 @@ class IMManager {
|
|||||||
case 'onUserTokenExpired':
|
case 'onUserTokenExpired':
|
||||||
_connectListener.userTokenExpired();
|
_connectListener.userTokenExpired();
|
||||||
break;
|
break;
|
||||||
|
case 'onUserTokenInvalid':
|
||||||
|
_connectListener.userTokenInvalid();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (call.method == ListenerType.userListener) {
|
} else if (call.method == ListenerType.userListener) {
|
||||||
String type = call.arguments['type'];
|
String type = call.arguments['type'];
|
||||||
@ -184,14 +187,17 @@ class IMManager {
|
|||||||
dynamic data = call.arguments['data'];
|
dynamic data = call.arguments['data'];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'onSyncServerStart':
|
case 'onSyncServerStart':
|
||||||
conversationManager.listener.syncServerStart();
|
print('dart onSyncServerStart: $data');
|
||||||
|
conversationManager.listener.syncServerStart(data);
|
||||||
|
break;
|
||||||
|
case 'onSyncServerProgress':
|
||||||
|
conversationManager.listener.syncServerProgress(data);
|
||||||
break;
|
break;
|
||||||
case 'onSyncServerFinish':
|
case 'onSyncServerFinish':
|
||||||
conversationManager.listener.syncServerFinish();
|
conversationManager.listener.syncServerFinish(data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'onSyncServerFailed':
|
case 'onSyncServerFailed':
|
||||||
conversationManager.listener.syncServerFailed();
|
conversationManager.listener.syncServerFailed(data);
|
||||||
break;
|
break;
|
||||||
case 'onNewConversation':
|
case 'onNewConversation':
|
||||||
var list = Utils.toList(data, (map) => ConversationInfo.fromJson(map));
|
var list = Utils.toList(data, (map) => ConversationInfo.fromJson(map));
|
||||||
@ -204,6 +210,10 @@ class IMManager {
|
|||||||
case 'onTotalUnreadMessageCountChanged':
|
case 'onTotalUnreadMessageCountChanged':
|
||||||
conversationManager.listener.totalUnreadMessageCountChanged(data ?? 0);
|
conversationManager.listener.totalUnreadMessageCountChanged(data ?? 0);
|
||||||
break;
|
break;
|
||||||
|
case 'onConversationUserInputStatusChanged':
|
||||||
|
final i = Utils.toObj(data, (map) => InputStatusChangedData.fromJson(map));
|
||||||
|
conversationManager.listener.conversationUserInputStatusChanged(i);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (call.method == ListenerType.friendListener) {
|
} else if (call.method == ListenerType.friendListener) {
|
||||||
String type = call.arguments['type'];
|
String type = call.arguments['type'];
|
||||||
|
24
lib/src/models/input_status_changed_data.dart
Normal file
24
lib/src/models/input_status_changed_data.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
class InputStatusChangedData {
|
||||||
|
final String userID;
|
||||||
|
final String conversationID;
|
||||||
|
final List<int>? platformIDs;
|
||||||
|
|
||||||
|
InputStatusChangedData({
|
||||||
|
required this.userID,
|
||||||
|
required this.conversationID,
|
||||||
|
this.platformIDs,
|
||||||
|
});
|
||||||
|
|
||||||
|
InputStatusChangedData.fromJson(Map<String, dynamic> json)
|
||||||
|
: userID = json['userID'],
|
||||||
|
conversationID = json['conversationID'],
|
||||||
|
platformIDs = List<int>.from(json['platformIDs'] ?? []);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final data = <String, dynamic>{};
|
||||||
|
data['userID'] = userID;
|
||||||
|
data['conversationID'] = conversationID;
|
||||||
|
data['platformIDs'] = platformIDs;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user