feat(*): add sender to files pack result
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
export 'nearby_device_base.dart';
|
||||
export 'nearby_message_base.dart';
|
||||
export 'nearby_message_content_base.dart';
|
||||
export 'nearby_message_content_base.dart';
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export 'nearby_device_mapper.dart';
|
||||
export 'nearby_received_interface.dart';
|
||||
export 'nearby_outgoing_interface.dart';
|
||||
export 'nearby_outgoing_interface.dart';
|
||||
|
||||
@@ -32,5 +32,3 @@ abstract interface class NearbyDeviceMapper {
|
||||
///
|
||||
NearbyDeviceBase? mapToDevice(dynamic value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,5 +3,6 @@ export 'nearby_device_status.dart';
|
||||
export 'nearby_message.dart';
|
||||
export 'nearby_message_content.dart';
|
||||
export 'communication_channel_state.dart';
|
||||
export 'nearby_file.dart';
|
||||
export 'nearby_file_info.dart';
|
||||
export 'nearby_message_content_type.dart';
|
||||
export 'nearby_files_pack.dart';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:io';
|
||||
import 'package:nearby_service/nearby_service.dart';
|
||||
|
||||
///
|
||||
@@ -8,46 +7,7 @@ import 'package:nearby_service/nearby_service.dart';
|
||||
/// From the communication channel, you usually get
|
||||
/// the [NearbyMessageFilesRequest] request first.
|
||||
/// After that, you can send positive [NearbyMessageFilesResponse] and
|
||||
/// get the list of [NearbyFile].
|
||||
///
|
||||
final class NearbyFile {
|
||||
///
|
||||
/// Pass [info] assigned to file to be sent.
|
||||
///
|
||||
const NearbyFile({
|
||||
required this.info,
|
||||
required this.file,
|
||||
});
|
||||
|
||||
///
|
||||
/// Quick info about the file
|
||||
///
|
||||
final NearbyFileInfo info;
|
||||
|
||||
///
|
||||
/// A file that you can save in your phone if needed
|
||||
///
|
||||
final File file;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is NearbyFile &&
|
||||
runtimeType == other.runtimeType &&
|
||||
info == other.info &&
|
||||
file == other.file;
|
||||
|
||||
@override
|
||||
int get hashCode => info.hashCode ^ file.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'NearbyFile{info: $info, file: $file}';
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Quick info about the file
|
||||
/// get the list of [NearbyFileInfo].
|
||||
///
|
||||
class NearbyFileInfo {
|
||||
///
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:nearby_service/nearby_service.dart';
|
||||
|
||||
///
|
||||
/// Used to provide result [files] that was got from [sender].
|
||||
///
|
||||
/// Can be received from [NearbyServiceFilesListener] only.
|
||||
///
|
||||
class ReceivedNearbyFilesPack implements NearbyReceivedInterface {
|
||||
const ReceivedNearbyFilesPack({
|
||||
required this.sender,
|
||||
required this.files,
|
||||
});
|
||||
|
||||
factory ReceivedNearbyFilesPack.fromJson(Map<String, dynamic>? json) {
|
||||
return ReceivedNearbyFilesPack(
|
||||
sender: NearbyDeviceInfo.fromJson(json?['sender']),
|
||||
files: [
|
||||
...?(json?['files'] as List?)?.map(
|
||||
(e) => NearbyFileInfo.fromJson(e as Map<String, dynamic>),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
final NearbyDeviceInfo sender;
|
||||
|
||||
final List<NearbyFileInfo> files;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'sender': sender.toJson(),
|
||||
'files': [
|
||||
...files.map((e) => e.toJson()),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ReceivedNearbyFilesPack &&
|
||||
runtimeType == other.runtimeType &&
|
||||
sender == other.sender &&
|
||||
files == other.files;
|
||||
|
||||
@override
|
||||
int get hashCode => sender.hashCode ^ files.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'NearbyFilesPack{sender: $sender, files: $files}';
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ class NearbyConnectionAndroidInfo {
|
||||
final bool isGroupOwner;
|
||||
|
||||
///
|
||||
/// Indicates if the current device is the group owner.
|
||||
/// Indicates if a p2p group has been successfully formed.
|
||||
/// Source [WifiP2pInfo documentation](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pInfo)
|
||||
///
|
||||
final bool groupFormed;
|
||||
|
||||
@@ -18,15 +18,15 @@ final class NearbyAndroidDevice extends NearbyDeviceBase {
|
||||
///
|
||||
NearbyAndroidDevice({
|
||||
required String deviceName,
|
||||
required super.status,
|
||||
required this.deviceAddress,
|
||||
required this.isGroupOwner,
|
||||
required this.isServiceDiscoveryCapable,
|
||||
required this.primaryDeviceType,
|
||||
required this.wpsKeypadSupported,
|
||||
required this.wpsPbcSupported,
|
||||
required this.wpsDisplaySupported,
|
||||
this.isGroupOwner = false,
|
||||
this.isServiceDiscoveryCapable = false,
|
||||
this.primaryDeviceType = kNearbyUnknown,
|
||||
this.wpsKeypadSupported = false,
|
||||
this.wpsPbcSupported = false,
|
||||
this.wpsDisplaySupported = false,
|
||||
this.secondaryDeviceType,
|
||||
super.status = NearbyDeviceStatus.unavailable,
|
||||
}) : super(
|
||||
info: NearbyDeviceInfo(
|
||||
displayName: deviceName,
|
||||
|
||||
@@ -65,9 +65,8 @@ class NearbyAndroidService extends NearbyService {
|
||||
/// Note! Requires [NearbyAndroidDevice] to be passed.
|
||||
///
|
||||
@override
|
||||
Future<bool> disconnect(NearbyDeviceBase device) {
|
||||
_requireAndroidDevice(device);
|
||||
return NearbyServiceAndroidPlatform.instance.disconnect(device.info.id);
|
||||
Future<bool> disconnect([NearbyDeviceBase? device]) {
|
||||
return NearbyServiceAndroidPlatform.instance.disconnect();
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -51,7 +51,7 @@ abstract class NearbyServiceAndroidPlatform extends PlatformInterface {
|
||||
throw UnimplementedError('connect() has not been implemented.');
|
||||
}
|
||||
|
||||
Future<bool> disconnect(String deviceAddress) {
|
||||
Future<bool> disconnect() {
|
||||
throw UnimplementedError('disconnect() has not been implemented.');
|
||||
}
|
||||
|
||||
|
||||
@@ -57,12 +57,8 @@ class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> disconnect(String deviceAddress) async {
|
||||
return (await methodChannel.invokeMethod<bool?>(
|
||||
"disconnect",
|
||||
{"deviceAddress": deviceAddress},
|
||||
)) ??
|
||||
false;
|
||||
Future<bool> disconnect() async {
|
||||
return (await methodChannel.invokeMethod<bool?>("disconnect")) ?? false;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -11,6 +11,7 @@ class FileSocketsManager {
|
||||
final _serverWaitingRequests = <String, HttpRequest>{};
|
||||
|
||||
NearbyServiceFilesListener? _filesListener;
|
||||
NearbyDeviceInfo? _sender;
|
||||
|
||||
void setListener(NearbyServiceFilesListener? listener) {
|
||||
_filesListener = listener;
|
||||
@@ -26,22 +27,30 @@ class FileSocketsManager {
|
||||
|
||||
Future<void> handleFileMessageContent(
|
||||
NearbyMessageFilesContent content, {
|
||||
required NearbyDeviceInfo? sender,
|
||||
required NearbyAndroidCommunicationChannelData androidData,
|
||||
required bool isReceived,
|
||||
}) async {
|
||||
if (sender != null) {
|
||||
_sender = sender;
|
||||
Logger.debug('Sender was set to $_sender');
|
||||
}
|
||||
|
||||
final shouldStartSocket = content.byType(
|
||||
onFilesResponse: (response) => response.response,
|
||||
onFilesRequest: (_) => true,
|
||||
) ??
|
||||
false;
|
||||
|
||||
if (shouldStartSocket) {
|
||||
final alreadyExists = _filesSockets[content.id] != null;
|
||||
|
||||
if (shouldStartSocket && !alreadyExists) {
|
||||
final info = await _service.getConnectionInfo();
|
||||
if (info != null && info.groupFormed) {
|
||||
if (info.isGroupOwner) {
|
||||
await _startFilesServer(content);
|
||||
if (content is NearbyMessageFilesResponse && isReceived) {
|
||||
await _tryTransferData(content);
|
||||
if (isReceived && content is NearbyMessageFilesResponse) {
|
||||
await _startDataTransfer(content);
|
||||
}
|
||||
} else {
|
||||
await _connectToFilesSocket(
|
||||
@@ -49,13 +58,11 @@ class FileSocketsManager {
|
||||
connectionData: androidData,
|
||||
ownerIpAddress: info.ownerIpAddress,
|
||||
);
|
||||
if (content is NearbyMessageFilesRequest && !isReceived) {
|
||||
await _tryTransferData(content);
|
||||
if (!isReceived && content is NearbyMessageFilesRequest) {
|
||||
await _startDataTransfer(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_filesSockets.remove(content.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,9 +114,7 @@ class FileSocketsManager {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _startFilesServer(
|
||||
NearbyMessageFilesContent content,
|
||||
) async {
|
||||
Future<void> _startFilesServer(NearbyMessageFilesContent content) async {
|
||||
final request = _serverWaitingRequests[content.id];
|
||||
|
||||
if (request != null) {
|
||||
@@ -130,8 +135,9 @@ class FileSocketsManager {
|
||||
required Future<WebSocket?> Function() onCreateSocket,
|
||||
}) async {
|
||||
final socket = await onCreateSocket();
|
||||
if (socket != null) {
|
||||
if (socket != null && _sender != null) {
|
||||
_filesSockets[content.id] = FilesSocket.startListening(
|
||||
sender: _sender!,
|
||||
content: content,
|
||||
socket: socket,
|
||||
listener: _filesListener,
|
||||
@@ -143,7 +149,7 @@ class FileSocketsManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> _tryTransferData(NearbyMessageFilesContent content) async {
|
||||
Future<void> _startDataTransfer(NearbyMessageFilesContent content) async {
|
||||
final filesSocket = _filesSockets[content.id];
|
||||
if (filesSocket != null) {
|
||||
Logger.debug('Start transferring the files pack ${content.id}');
|
||||
|
||||
@@ -96,13 +96,7 @@ class NearbySocketService {
|
||||
},
|
||||
),
|
||||
);
|
||||
if (message.content is NearbyMessageFilesContent) {
|
||||
_fileSocketsManager.handleFileMessageContent(
|
||||
message.content as NearbyMessageFilesContent,
|
||||
androidData: _androidData,
|
||||
isReceived: false,
|
||||
);
|
||||
}
|
||||
_handleMessage(message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -211,13 +205,7 @@ class NearbySocketService {
|
||||
.listen(
|
||||
(message) async {
|
||||
try {
|
||||
if (message.content is NearbyMessageFilesContent) {
|
||||
_fileSocketsManager.handleFileMessageContent(
|
||||
message.content as NearbyMessageFilesContent,
|
||||
androidData: _androidData,
|
||||
isReceived: true,
|
||||
);
|
||||
}
|
||||
_handleMessage(message);
|
||||
socketListener.onData(message);
|
||||
} catch (e) {
|
||||
Logger.error(e);
|
||||
@@ -244,4 +232,15 @@ class NearbySocketService {
|
||||
state.value = CommunicationChannelState.notConnected;
|
||||
}
|
||||
}
|
||||
|
||||
void _handleMessage(NearbyMessageBase message) {
|
||||
if (message.content is NearbyMessageFilesContent) {
|
||||
_fileSocketsManager.handleFileMessageContent(
|
||||
message.content as NearbyMessageFilesContent,
|
||||
isReceived: message is ReceivedNearbyMessage,
|
||||
sender: message is ReceivedNearbyMessage ? message.sender : null,
|
||||
androidData: _androidData,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,8 @@ class NearbyIOSService extends NearbyService {
|
||||
/// Note! Requires [NearbyIOSDevice] to be passed.
|
||||
///
|
||||
@override
|
||||
Future<bool> disconnect(NearbyDeviceBase device) async {
|
||||
Future<bool> disconnect([NearbyDeviceBase? device]) async {
|
||||
if (device == null) return false;
|
||||
_requireIOSDevice(device);
|
||||
final result = await NearbyServiceIOSPlatform.instance.disconnect(
|
||||
device.info.id,
|
||||
@@ -185,9 +186,9 @@ class NearbyIOSService extends NearbyService {
|
||||
cancelOnError: eventListener.cancelOnError,
|
||||
);
|
||||
_resourcesSubscription = NearbyServiceIOSPlatform.instance.resourcesStream
|
||||
.map(ResourcesStreamMapper.toFiles)
|
||||
.map(ResourcesStreamMapper.toFilesPack)
|
||||
.where((event) => event != null)
|
||||
.cast<List<NearbyFile>>()
|
||||
.cast<ReceivedNearbyFilesPack>()
|
||||
.listen(
|
||||
(e) => filesListener?.onData.call(e),
|
||||
onDone: filesListener?.onDone,
|
||||
|
||||
@@ -46,7 +46,7 @@ class NearbyServiceMessagesListener
|
||||
/// Stream Subscription Listener.
|
||||
///
|
||||
class NearbyServiceFilesListener
|
||||
extends NearbyServiceSocketListener<List<NearbyFile>> {
|
||||
extends NearbyServiceSocketListener<ReceivedNearbyFilesPack> {
|
||||
///
|
||||
/// It is required to pass the [onData] parameter to process the
|
||||
/// data that came through the stream.
|
||||
|
||||
@@ -31,7 +31,8 @@ class NearbyServiceException implements Exception {
|
||||
);
|
||||
}
|
||||
|
||||
factory NearbyServiceException.invalidMessage(NearbyMessageContentBase content) {
|
||||
factory NearbyServiceException.invalidMessage(
|
||||
NearbyMessageContentBase content) {
|
||||
return NearbyServiceException(
|
||||
'The message="$content" is not valid',
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class FilesSocket {
|
||||
FilesSocket.startListening({
|
||||
required this.sender,
|
||||
required this.content,
|
||||
required this.listener,
|
||||
required this.onDestroy,
|
||||
@@ -31,9 +32,10 @@ class FilesSocket {
|
||||
final NearbyMessageFilesContent content;
|
||||
final void Function(String) onDestroy;
|
||||
final NearbyServiceFilesListener? listener;
|
||||
final NearbyDeviceInfo sender;
|
||||
final WebSocket _socket;
|
||||
|
||||
final _files = <NearbyFile>[];
|
||||
final _files = <NearbyFileInfo>[];
|
||||
final _bytesTable = <String, List<int>>{'0': []};
|
||||
final _futures = <Future>[];
|
||||
|
||||
@@ -65,7 +67,13 @@ class FilesSocket {
|
||||
} else if (event == finishCommand) {
|
||||
await Future.wait(_futures);
|
||||
Logger.info('Files pack ${content.id} was created');
|
||||
listener?.onData.call(_files);
|
||||
|
||||
listener?.onData.call(
|
||||
ReceivedNearbyFilesPack(
|
||||
sender: sender,
|
||||
files: _files,
|
||||
),
|
||||
);
|
||||
onDestroy(content.id);
|
||||
}
|
||||
}
|
||||
@@ -76,13 +84,12 @@ class FilesSocket {
|
||||
final fileInfo = content.files[index];
|
||||
final directory = await getTemporaryDirectory();
|
||||
final file = File('${directory.path}/${fileInfo.name}');
|
||||
|
||||
await file.writeAsBytes(bytes);
|
||||
final updatedFileInfo = NearbyFileInfo(path: file.path);
|
||||
|
||||
final nearbyFile = NearbyFile(file: file, info: fileInfo);
|
||||
_files.add(nearbyFile);
|
||||
_files.add(updatedFileInfo);
|
||||
|
||||
Logger.info('File ${nearbyFile.info.name} was created');
|
||||
Logger.info('File ${updatedFileInfo.name} was created');
|
||||
} catch (e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:nearby_service/nearby_service.dart';
|
||||
import 'package:nearby_service/src/utils/json_decoder.dart';
|
||||
|
||||
@@ -20,6 +18,8 @@ abstract class MessagesStreamMapper {
|
||||
static ReceivedNearbyMessage? toMessage(dynamic event) {
|
||||
try {
|
||||
final decoded = JSONDecoder.decodeMap(event);
|
||||
if (decoded == null) return null;
|
||||
|
||||
return ReceivedNearbyMessage.fromJson(decoded);
|
||||
} catch (e) {
|
||||
throw NearbyServiceException(
|
||||
@@ -30,17 +30,12 @@ abstract class MessagesStreamMapper {
|
||||
}
|
||||
|
||||
abstract class ResourcesStreamMapper {
|
||||
static List<NearbyFile>? toFiles(dynamic event) {
|
||||
static ReceivedNearbyFilesPack? toFilesPack(dynamic event) {
|
||||
try {
|
||||
final decoded = JSONDecoder.decodeList(event);
|
||||
final infoList = [
|
||||
...?decoded?.map(
|
||||
(e) => NearbyFileInfo.fromJson(e as Map<String, dynamic>),
|
||||
)
|
||||
];
|
||||
return [
|
||||
...infoList.map((e) => NearbyFile(info: e, file: File(e.path))),
|
||||
];
|
||||
final decoded = JSONDecoder.decodeMap(event);
|
||||
if (decoded == null) return null;
|
||||
|
||||
return ReceivedNearbyFilesPack.fromJson(decoded);
|
||||
} catch (e) {
|
||||
throw NearbyServiceException(
|
||||
'Can\'t convert $event to ReceivedNearbyMessage',
|
||||
|
||||
Reference in New Issue
Block a user