feat(*): add sender to files pack result

This commit is contained in:
ksenia312
2024-02-04 22:25:57 +01:00
parent a1ac4488ca
commit d6840a4313
25 changed files with 199 additions and 152 deletions
+19 -14
View File
@@ -270,6 +270,7 @@ class AppService extends ChangeNotifier {
final result = await _nearbyService.android?.checkWifiService(); final result = await _nearbyService.android?.checkWifiService();
if (result ?? false) { if (result ?? false) {
updateState(AppState.readyToDiscover); updateState(AppState.readyToDiscover);
startListeningConnectionInfo();
return true; return true;
} }
return false; return false;
@@ -289,7 +290,6 @@ class AppService extends ChangeNotifier {
final result = await _nearbyService.discover(); final result = await _nearbyService.discover();
if (result) { if (result) {
updateState(AppState.discoveringPeers); updateState(AppState.discoveringPeers);
startListeningConnectionInfo();
} }
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
@@ -333,11 +333,6 @@ class AppService extends ChangeNotifier {
updateState(AppState.discoveringPeers); updateState(AppState.discoveringPeers);
} }
Future<void> stopListeningConnectionInfo() async {
await connectionInfoSubscription?.cancel();
connectionInfoSubscription = null;
}
Future<void> connect(NearbyDeviceBase device) async { Future<void> connect(NearbyDeviceBase device) async {
try { try {
await _nearbyService.connect(device); await _nearbyService.connect(device);
@@ -366,6 +361,11 @@ class AppService extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> stopListeningConnectionInfo() async {
await connectionInfoSubscription?.cancel();
connectionInfoSubscription = null;
}
Future<void> startListeningConnectedDevice(NearbyDeviceBase device) async { Future<void> startListeningConnectedDevice(NearbyDeviceBase device) async {
updateState(AppState.loadingConnection); updateState(AppState.loadingConnection);
try { try {
@@ -404,7 +404,7 @@ class AppService extends ChangeNotifier {
Future<void> startCommunicationChannel({ Future<void> startCommunicationChannel({
ValueChanged<ReceivedNearbyMessage>? listener, ValueChanged<ReceivedNearbyMessage>? listener,
ValueChanged<List<NearbyFileInfo>>? onFilesSaved, ValueChanged<ReceivedNearbyFilesPack>? onFilesSaved,
}) async { }) async {
final messagesListener = NearbyServiceMessagesListener( final messagesListener = NearbyServiceMessagesListener(
onCreated: () { onCreated: () {
@@ -424,16 +424,18 @@ class AppService extends ChangeNotifier {
? Directory('storage/emulated/0/Download') ? Directory('storage/emulated/0/Download')
: await getApplicationDocumentsDirectory(); : await getApplicationDocumentsDirectory();
for (final nearbyFile in event) { for (final nearbyFile in event.files) {
final newFile = await nearbyFile.file.copy( final newFile = await File(nearbyFile.path).copy(
'${directory.path}/${DateTime.now().microsecondsSinceEpoch}.${nearbyFile.info.extension}', '${directory.path}/${DateTime.now().microsecondsSinceEpoch}.${nearbyFile.extension}',
); );
if (!await newFile.exists()) { if (!await newFile.exists()) {
await newFile.create(); await newFile.create();
} }
files.add(NearbyFileInfo(path: newFile.path)); files.add(NearbyFileInfo(path: newFile.path));
} }
onFilesSaved?.call(files); onFilesSaved?.call(
ReceivedNearbyFilesPack(sender: event.sender, files: files),
);
}, },
); );
@@ -492,7 +494,7 @@ class AppService extends ChangeNotifier {
); );
} }
Future<void> disconnect(NearbyDeviceBase device) async { Future<void> disconnect([NearbyDeviceBase? device]) async {
try { try {
await _nearbyService.disconnect(device); await _nearbyService.disconnect(device);
} catch (e) { } catch (e) {
@@ -883,10 +885,13 @@ class _ConnectedBody extends StatelessWidget {
); );
} }
void _onFileSaved(BuildContext context, List<NearbyFileInfo> files) { void _onFileSaved(BuildContext context, ReceivedNearbyFilesPack pack) {
final senderSubtitle = 'From ${pack.sender.displayName} '
'(ID: ${pack.sender.id})';
AppShackBar.show( AppShackBar.show(
Scaffold.of(context).context, Scaffold.of(context).context,
'${files.length} files saved! \n${files.map((e) => e.name).join('\n')}', '${pack.files.length} files saved! \n${pack.files.map((e) => e.name).join('\n')}',
subtitle: senderSubtitle,
); );
} }
} }
+7 -8
View File
@@ -6,30 +6,29 @@
// //
import Foundation import Foundation
import MultipeerConnectivity
class NearbyStartCommand { class NearbyStartCommand {
init( id: String, filesCount: Int) { init(senderName: String, filesCount: Int) {
self.id = id self.senderName = senderName
self.filesCount = filesCount self.filesCount = filesCount
} }
static func fromUserInfo(userInfo: NearbyUserInfo)-> NearbyStartCommand? { static func fromUserInfo(userInfo: NearbyUserInfo)-> NearbyStartCommand? {
if let id = userInfo.dictionary["id"] as? String , if let name = userInfo.dictionary["name"] as? String,
let filesCount = userInfo.dictionary["filesCount"] as? Int let filesCount = userInfo.dictionary["filesCount"] as? Int
{ {
return NearbyStartCommand( return NearbyStartCommand(senderName: name, filesCount: filesCount)
id: id, filesCount: filesCount
)
} }
return nil return nil
} }
func toDictionary() -> [String: Any] { func toDictionary() -> [String: Any] {
return ["id": id, "filesCount": filesCount] return ["name": senderName, "filesCount": filesCount]
} }
let id: String let senderName: String
let filesCount: Int let filesCount: Int
} }
+4 -2
View File
@@ -47,15 +47,17 @@ extension NearbySession: MCSessionDelegate {
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) { func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
guard let localURL = localURL else { return } guard let localURL = localURL else { return }
let destinationURL = localURL.deletingLastPathComponent().appendingPathComponent("\(resourceName)") var destinationURL = localURL.deletingLastPathComponent().appendingPathComponent("\(resourceName)")
if FileManager.default.fileExists(atPath: destinationURL.path) {
destinationURL = localURL.deletingLastPathComponent().appendingPathComponent("New_\(resourceName)")
}
do { do {
try FileManager.default.moveItem(at: localURL, to: destinationURL) try FileManager.default.moveItem(at: localURL, to: destinationURL)
} catch { } catch {
Logger.error(message: "Error moving file: \(error)") Logger.error(message: "Error moving file: \(error)")
} }
NotificationCenter.default.post( NotificationCenter.default.post(
name: ON_RESOURCE_RECEIVED, name: ON_RESOURCE_RECEIVED,
object: nil, object: nil,
+7 -2
View File
@@ -124,8 +124,13 @@ class NearbyManager: NSObject {
do { do {
let device = NearbyDevicesStore.instance.find(for: receiverId) let device = NearbyDevicesStore.instance.find(for: receiverId)
if let requireDevice = device { if let requireDevice = device {
try requireDevice.session?.session?.send( let command = NearbyStartCommand(
try JSONSerialization.data(withJSONObject: NearbyStartCommand( id: id, filesCount: paths.count).toDictionary()), senderName: requireDevice.name,
filesCount: paths.count
).toDictionary()
try requireDevice.session?.session?.send(
try JSONSerialization.data(withJSONObject: command),
toPeers: [requireDevice.peerID], toPeers: [requireDevice.peerID],
with: MCSessionSendDataMode.reliable with: MCSessionSendDataMode.reliable
) )
+5 -1
View File
@@ -33,13 +33,17 @@ extension NearbyServicePlugin {
} }
@objc func onResourceReceived(notification: Notification) { @objc func onResourceReceived(notification: Notification) {
DispatchQueue.main.async { DispatchQueue.main.async {
if let userInfo = NearbyUserInfo.fromDictionary(userInfo: notification.userInfo) { if let userInfo = NearbyUserInfo.fromDictionary(userInfo: notification.userInfo) {
if let url = userInfo.dictionary["url"] as? URL { if let url = userInfo.dictionary["url"] as? URL {
NearbyFilesStore.instance.add(url: url) NearbyFilesStore.instance.add(url: url)
if (NearbyFilesStore.instance.checkIsFull()) { if (NearbyFilesStore.instance.checkIsFull()) {
self.channel.invokeMethod(DART_COMMAND_RESOURCES_RECEIVED, arguments: NearbyFilesStore.instance.toDartFormat())
self.channel.invokeMethod(DART_COMMAND_RESOURCES_RECEIVED, arguments: NearbyFilesStore.instance.toDartFormat(peerID: userInfo.peerID))
NearbyFilesStore.instance.clear()
} }
} }
} }
+25 -11
View File
@@ -6,18 +6,19 @@
// //
import Foundation import Foundation
import MultipeerConnectivity
class NearbyFilesStore { class NearbyFilesStore {
static let instance = NearbyFilesStore() static let instance = NearbyFilesStore()
private var paths : [String] = [] private var paths : [String] = []
private var id: String? = nil private var senderName: String? = nil
private var maxCount: Int = 0 private var maxCount: Int = 0
private var count: Int = 0 private var count: Int = 0
func startReceiving(command: NearbyStartCommand) { func startReceiving(command: NearbyStartCommand) {
self.paths.removeAll() self.paths.removeAll()
self.id = command.id self.senderName = command.senderName
self.maxCount = command.filesCount self.maxCount = command.filesCount
self.count = 0 self.count = 0
} }
@@ -31,16 +32,29 @@ class NearbyFilesStore {
return maxCount <= count return maxCount <= count
} }
func toDartFormat() -> String? { func clear() {
let pathsObject = paths.map { ["path": $0]} self.paths.removeAll()
do { self.senderName = nil
let jsonData = try JSONSerialization.data(withJSONObject: pathsObject) self.maxCount = 0
if let jsonString = String(data: jsonData, encoding: .utf8) { self.count = 0
return jsonString }
func toDartFormat(peerID: MCPeerID) -> String? {
if (senderName != nil) {
let object = [
"files": paths.map { ["path": $0]},
"sender": ["id": peerID.displayName, "displayName": senderName!]
] as [String : Any]
do {
let jsonData = try JSONSerialization.data(withJSONObject: object)
if let jsonString = String(data: jsonData, encoding: .utf8) {
return jsonString
}
} catch {
return nil
} }
} catch { return nil
return "[]"
} }
return "[]" return nil
} }
} }
+2 -1
View File
@@ -195,7 +195,8 @@ abstract class NearbyService {
/// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed. /// Note that if [Platform.isIOS] == true, [NearbyIOSDevice] should be passed.
/// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed. /// If [Platform.isAndroid] == true, [NearbyAndroidDevice] should be passed.
/// ///
Future<bool> disconnect(NearbyDeviceBase device); /// For IOS [device] is required!!!
Future<bool> disconnect([NearbyDeviceBase? device]);
/// ///
/// If the device is already connected, it does not mean that you can /// If the device is already connected, it does not mean that you can
+1 -1
View File
@@ -1,3 +1,3 @@
export 'nearby_device_base.dart'; export 'nearby_device_base.dart';
export 'nearby_message_base.dart'; export 'nearby_message_base.dart';
export 'nearby_message_content_base.dart'; export 'nearby_message_content_base.dart';
+1 -1
View File
@@ -1,3 +1,3 @@
export 'nearby_device_mapper.dart'; export 'nearby_device_mapper.dart';
export 'nearby_received_interface.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); NearbyDeviceBase? mapToDevice(dynamic value);
} }
+2 -1
View File
@@ -3,5 +3,6 @@ export 'nearby_device_status.dart';
export 'nearby_message.dart'; export 'nearby_message.dart';
export 'nearby_message_content.dart'; export 'nearby_message_content.dart';
export 'communication_channel_state.dart'; export 'communication_channel_state.dart';
export 'nearby_file.dart'; export 'nearby_file_info.dart';
export 'nearby_message_content_type.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'; 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 /// From the communication channel, you usually get
/// the [NearbyMessageFilesRequest] request first. /// the [NearbyMessageFilesRequest] request first.
/// After that, you can send positive [NearbyMessageFilesResponse] and /// After that, you can send positive [NearbyMessageFilesResponse] and
/// get the list of [NearbyFile]. /// get the list of [NearbyFileInfo].
///
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
/// ///
class NearbyFileInfo { class NearbyFileInfo {
/// ///
+54
View File
@@ -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; 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) /// Source [WifiP2pInfo documentation](https://developer.android.com/reference/android/net/wifi/p2p/WifiP2pInfo)
/// ///
final bool groupFormed; final bool groupFormed;
@@ -18,15 +18,15 @@ final class NearbyAndroidDevice extends NearbyDeviceBase {
/// ///
NearbyAndroidDevice({ NearbyAndroidDevice({
required String deviceName, required String deviceName,
required super.status,
required this.deviceAddress, required this.deviceAddress,
required this.isGroupOwner, this.isGroupOwner = false,
required this.isServiceDiscoveryCapable, this.isServiceDiscoveryCapable = false,
required this.primaryDeviceType, this.primaryDeviceType = kNearbyUnknown,
required this.wpsKeypadSupported, this.wpsKeypadSupported = false,
required this.wpsPbcSupported, this.wpsPbcSupported = false,
required this.wpsDisplaySupported, this.wpsDisplaySupported = false,
this.secondaryDeviceType, this.secondaryDeviceType,
super.status = NearbyDeviceStatus.unavailable,
}) : super( }) : super(
info: NearbyDeviceInfo( info: NearbyDeviceInfo(
displayName: deviceName, displayName: deviceName,
@@ -65,9 +65,8 @@ class NearbyAndroidService extends NearbyService {
/// Note! Requires [NearbyAndroidDevice] to be passed. /// Note! Requires [NearbyAndroidDevice] to be passed.
/// ///
@override @override
Future<bool> disconnect(NearbyDeviceBase device) { Future<bool> disconnect([NearbyDeviceBase? device]) {
_requireAndroidDevice(device); return NearbyServiceAndroidPlatform.instance.disconnect();
return NearbyServiceAndroidPlatform.instance.disconnect(device.info.id);
} }
/// ///
@@ -51,7 +51,7 @@ abstract class NearbyServiceAndroidPlatform extends PlatformInterface {
throw UnimplementedError('connect() has not been implemented.'); throw UnimplementedError('connect() has not been implemented.');
} }
Future<bool> disconnect(String deviceAddress) { Future<bool> disconnect() {
throw UnimplementedError('disconnect() has not been implemented.'); throw UnimplementedError('disconnect() has not been implemented.');
} }
@@ -57,12 +57,8 @@ class MethodChannelAndroidNearbyService extends NearbyServiceAndroidPlatform {
} }
@override @override
Future<bool> disconnect(String deviceAddress) async { Future<bool> disconnect() async {
return (await methodChannel.invokeMethod<bool?>( return (await methodChannel.invokeMethod<bool?>("disconnect")) ?? false;
"disconnect",
{"deviceAddress": deviceAddress},
)) ??
false;
} }
@override @override
@@ -11,6 +11,7 @@ class FileSocketsManager {
final _serverWaitingRequests = <String, HttpRequest>{}; final _serverWaitingRequests = <String, HttpRequest>{};
NearbyServiceFilesListener? _filesListener; NearbyServiceFilesListener? _filesListener;
NearbyDeviceInfo? _sender;
void setListener(NearbyServiceFilesListener? listener) { void setListener(NearbyServiceFilesListener? listener) {
_filesListener = listener; _filesListener = listener;
@@ -26,22 +27,30 @@ class FileSocketsManager {
Future<void> handleFileMessageContent( Future<void> handleFileMessageContent(
NearbyMessageFilesContent content, { NearbyMessageFilesContent content, {
required NearbyDeviceInfo? sender,
required NearbyAndroidCommunicationChannelData androidData, required NearbyAndroidCommunicationChannelData androidData,
required bool isReceived, required bool isReceived,
}) async { }) async {
if (sender != null) {
_sender = sender;
Logger.debug('Sender was set to $_sender');
}
final shouldStartSocket = content.byType( final shouldStartSocket = content.byType(
onFilesResponse: (response) => response.response, onFilesResponse: (response) => response.response,
onFilesRequest: (_) => true, onFilesRequest: (_) => true,
) ?? ) ??
false; false;
if (shouldStartSocket) { final alreadyExists = _filesSockets[content.id] != null;
if (shouldStartSocket && !alreadyExists) {
final info = await _service.getConnectionInfo(); final info = await _service.getConnectionInfo();
if (info != null && info.groupFormed) { if (info != null && info.groupFormed) {
if (info.isGroupOwner) { if (info.isGroupOwner) {
await _startFilesServer(content); await _startFilesServer(content);
if (content is NearbyMessageFilesResponse && isReceived) { if (isReceived && content is NearbyMessageFilesResponse) {
await _tryTransferData(content); await _startDataTransfer(content);
} }
} else { } else {
await _connectToFilesSocket( await _connectToFilesSocket(
@@ -49,13 +58,11 @@ class FileSocketsManager {
connectionData: androidData, connectionData: androidData,
ownerIpAddress: info.ownerIpAddress, ownerIpAddress: info.ownerIpAddress,
); );
if (content is NearbyMessageFilesRequest && !isReceived) { if (!isReceived && content is NearbyMessageFilesRequest) {
await _tryTransferData(content); await _startDataTransfer(content);
} }
} }
} }
} else {
_filesSockets.remove(content.id);
} }
} }
@@ -107,9 +114,7 @@ class FileSocketsManager {
} }
} }
Future<void> _startFilesServer( Future<void> _startFilesServer(NearbyMessageFilesContent content) async {
NearbyMessageFilesContent content,
) async {
final request = _serverWaitingRequests[content.id]; final request = _serverWaitingRequests[content.id];
if (request != null) { if (request != null) {
@@ -130,8 +135,9 @@ class FileSocketsManager {
required Future<WebSocket?> Function() onCreateSocket, required Future<WebSocket?> Function() onCreateSocket,
}) async { }) async {
final socket = await onCreateSocket(); final socket = await onCreateSocket();
if (socket != null) { if (socket != null && _sender != null) {
_filesSockets[content.id] = FilesSocket.startListening( _filesSockets[content.id] = FilesSocket.startListening(
sender: _sender!,
content: content, content: content,
socket: socket, socket: socket,
listener: _filesListener, listener: _filesListener,
@@ -143,7 +149,7 @@ class FileSocketsManager {
return false; return false;
} }
Future<void> _tryTransferData(NearbyMessageFilesContent content) async { Future<void> _startDataTransfer(NearbyMessageFilesContent content) async {
final filesSocket = _filesSockets[content.id]; final filesSocket = _filesSockets[content.id];
if (filesSocket != null) { if (filesSocket != null) {
Logger.debug('Start transferring the files pack ${content.id}'); Logger.debug('Start transferring the files pack ${content.id}');
@@ -96,13 +96,7 @@ class NearbySocketService {
}, },
), ),
); );
if (message.content is NearbyMessageFilesContent) { _handleMessage(message);
_fileSocketsManager.handleFileMessageContent(
message.content as NearbyMessageFilesContent,
androidData: _androidData,
isReceived: false,
);
}
} }
return true; return true;
} }
@@ -211,13 +205,7 @@ class NearbySocketService {
.listen( .listen(
(message) async { (message) async {
try { try {
if (message.content is NearbyMessageFilesContent) { _handleMessage(message);
_fileSocketsManager.handleFileMessageContent(
message.content as NearbyMessageFilesContent,
androidData: _androidData,
isReceived: true,
);
}
socketListener.onData(message); socketListener.onData(message);
} catch (e) { } catch (e) {
Logger.error(e); Logger.error(e);
@@ -244,4 +232,15 @@ class NearbySocketService {
state.value = CommunicationChannelState.notConnected; 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. /// Note! Requires [NearbyIOSDevice] to be passed.
/// ///
@override @override
Future<bool> disconnect(NearbyDeviceBase device) async { Future<bool> disconnect([NearbyDeviceBase? device]) async {
if (device == null) return false;
_requireIOSDevice(device); _requireIOSDevice(device);
final result = await NearbyServiceIOSPlatform.instance.disconnect( final result = await NearbyServiceIOSPlatform.instance.disconnect(
device.info.id, device.info.id,
@@ -185,9 +186,9 @@ class NearbyIOSService extends NearbyService {
cancelOnError: eventListener.cancelOnError, cancelOnError: eventListener.cancelOnError,
); );
_resourcesSubscription = NearbyServiceIOSPlatform.instance.resourcesStream _resourcesSubscription = NearbyServiceIOSPlatform.instance.resourcesStream
.map(ResourcesStreamMapper.toFiles) .map(ResourcesStreamMapper.toFilesPack)
.where((event) => event != null) .where((event) => event != null)
.cast<List<NearbyFile>>() .cast<ReceivedNearbyFilesPack>()
.listen( .listen(
(e) => filesListener?.onData.call(e), (e) => filesListener?.onData.call(e),
onDone: filesListener?.onDone, onDone: filesListener?.onDone,
@@ -46,7 +46,7 @@ class NearbyServiceMessagesListener
/// Stream Subscription Listener. /// Stream Subscription Listener.
/// ///
class NearbyServiceFilesListener class NearbyServiceFilesListener
extends NearbyServiceSocketListener<List<NearbyFile>> { extends NearbyServiceSocketListener<ReceivedNearbyFilesPack> {
/// ///
/// It is required to pass the [onData] parameter to process the /// It is required to pass the [onData] parameter to process the
/// data that came through the stream. /// data that came through the stream.
+2 -1
View File
@@ -31,7 +31,8 @@ class NearbyServiceException implements Exception {
); );
} }
factory NearbyServiceException.invalidMessage(NearbyMessageContentBase content) { factory NearbyServiceException.invalidMessage(
NearbyMessageContentBase content) {
return NearbyServiceException( return NearbyServiceException(
'The message="$content" is not valid', 'The message="$content" is not valid',
); );
+13 -6
View File
@@ -8,6 +8,7 @@ import 'package:path_provider/path_provider.dart';
class FilesSocket { class FilesSocket {
FilesSocket.startListening({ FilesSocket.startListening({
required this.sender,
required this.content, required this.content,
required this.listener, required this.listener,
required this.onDestroy, required this.onDestroy,
@@ -31,9 +32,10 @@ class FilesSocket {
final NearbyMessageFilesContent content; final NearbyMessageFilesContent content;
final void Function(String) onDestroy; final void Function(String) onDestroy;
final NearbyServiceFilesListener? listener; final NearbyServiceFilesListener? listener;
final NearbyDeviceInfo sender;
final WebSocket _socket; final WebSocket _socket;
final _files = <NearbyFile>[]; final _files = <NearbyFileInfo>[];
final _bytesTable = <String, List<int>>{'0': []}; final _bytesTable = <String, List<int>>{'0': []};
final _futures = <Future>[]; final _futures = <Future>[];
@@ -65,7 +67,13 @@ class FilesSocket {
} else if (event == finishCommand) { } else if (event == finishCommand) {
await Future.wait(_futures); await Future.wait(_futures);
Logger.info('Files pack ${content.id} was created'); Logger.info('Files pack ${content.id} was created');
listener?.onData.call(_files);
listener?.onData.call(
ReceivedNearbyFilesPack(
sender: sender,
files: _files,
),
);
onDestroy(content.id); onDestroy(content.id);
} }
} }
@@ -76,13 +84,12 @@ class FilesSocket {
final fileInfo = content.files[index]; final fileInfo = content.files[index];
final directory = await getTemporaryDirectory(); final directory = await getTemporaryDirectory();
final file = File('${directory.path}/${fileInfo.name}'); final file = File('${directory.path}/${fileInfo.name}');
await file.writeAsBytes(bytes); await file.writeAsBytes(bytes);
final updatedFileInfo = NearbyFileInfo(path: file.path);
final nearbyFile = NearbyFile(file: file, info: fileInfo); _files.add(updatedFileInfo);
_files.add(nearbyFile);
Logger.info('File ${nearbyFile.info.name} was created'); Logger.info('File ${updatedFileInfo.name} was created');
} catch (e) { } catch (e) {
Logger.error(e); Logger.error(e);
} }
+7 -12
View File
@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:nearby_service/nearby_service.dart'; import 'package:nearby_service/nearby_service.dart';
import 'package:nearby_service/src/utils/json_decoder.dart'; import 'package:nearby_service/src/utils/json_decoder.dart';
@@ -20,6 +18,8 @@ abstract class MessagesStreamMapper {
static ReceivedNearbyMessage? toMessage(dynamic event) { static ReceivedNearbyMessage? toMessage(dynamic event) {
try { try {
final decoded = JSONDecoder.decodeMap(event); final decoded = JSONDecoder.decodeMap(event);
if (decoded == null) return null;
return ReceivedNearbyMessage.fromJson(decoded); return ReceivedNearbyMessage.fromJson(decoded);
} catch (e) { } catch (e) {
throw NearbyServiceException( throw NearbyServiceException(
@@ -30,17 +30,12 @@ abstract class MessagesStreamMapper {
} }
abstract class ResourcesStreamMapper { abstract class ResourcesStreamMapper {
static List<NearbyFile>? toFiles(dynamic event) { static ReceivedNearbyFilesPack? toFilesPack(dynamic event) {
try { try {
final decoded = JSONDecoder.decodeList(event); final decoded = JSONDecoder.decodeMap(event);
final infoList = [ if (decoded == null) return null;
...?decoded?.map(
(e) => NearbyFileInfo.fromJson(e as Map<String, dynamic>), return ReceivedNearbyFilesPack.fromJson(decoded);
)
];
return [
...infoList.map((e) => NearbyFile(info: e, file: File(e.path))),
];
} catch (e) { } catch (e) {
throw NearbyServiceException( throw NearbyServiceException(
'Can\'t convert $event to ReceivedNearbyMessage', 'Can\'t convert $event to ReceivedNearbyMessage',