feat(android, ios): remove files field from files response
This commit is contained in:
@@ -479,15 +479,15 @@ class AppService extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sendFilesResponse(
|
void sendFilesResponse(
|
||||||
NearbyMessageFilesRequest request, {
|
String requestId, {
|
||||||
required bool response,
|
required bool response,
|
||||||
}) {
|
}) {
|
||||||
if (connectedDevice == null) return;
|
if (connectedDevice == null) return;
|
||||||
_nearbyService.send(
|
_nearbyService.send(
|
||||||
OutgoingNearbyMessage(
|
OutgoingNearbyMessage(
|
||||||
receiver: connectedDevice!.info,
|
receiver: connectedDevice!.info,
|
||||||
content: NearbyMessageFilesResponse.fromRequest(
|
content: NearbyMessageFilesResponse(
|
||||||
request,
|
id: requestId,
|
||||||
response: response,
|
response: response,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -869,7 +869,7 @@ class _ConnectedBody extends StatelessWidget {
|
|||||||
).then((value) {
|
).then((value) {
|
||||||
if (value is bool) {
|
if (value is bool) {
|
||||||
context.read<AppService>().sendFilesResponse(
|
context.read<AppService>().sendFilesResponse(
|
||||||
content,
|
content.id,
|
||||||
response: value,
|
response: value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,57 +58,64 @@ class NearbyMessageTextContent : NearbyMessageContent {
|
|||||||
|
|
||||||
class NearbyMessageFilesContent : NearbyMessageContent {
|
class NearbyMessageFilesContent : NearbyMessageContent {
|
||||||
|
|
||||||
init(files: Array<String>, id: String, type: MessageContentType) {
|
init(id: String, type: MessageContentType) {
|
||||||
self.files = files
|
|
||||||
self.id = id
|
self.id = id
|
||||||
super.init(type: type)
|
super.init(type: type)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func fromJsonRaw(type: MessageContentType, json: [String: Any]) -> NearbyMessageFilesContent? {
|
static func fromJsonRaw(type: MessageContentType, json: [String: Any]) -> NearbyMessageFilesContent? {
|
||||||
if let filesObjects: Array = json["files"] as? Array<Dictionary<String, AnyObject>> {
|
if let id: String = json["id"] as? String{
|
||||||
let files : [String]? = filesObjects.map({ $0["path"] as? String }).compactMap({$0})
|
return NearbyMessageFilesContent(id: id, type: type)
|
||||||
if let id: String = json["id"] as? String{
|
|
||||||
if let requireFiles = files {
|
|
||||||
return NearbyMessageFilesContent(files: requireFiles, id: id, type: type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
override func toJson() -> [String : Any] {
|
override func toJson() -> [String : Any] {
|
||||||
return [
|
return [
|
||||||
"files": files.map{["path": $0]},
|
|
||||||
"id": id,
|
"id": id,
|
||||||
].merging( super.toJson()) { (current, _) in current}
|
].merging( super.toJson()) { (current, _) in current}
|
||||||
}
|
}
|
||||||
|
|
||||||
let files: Array<String>
|
|
||||||
let id: String
|
let id: String
|
||||||
}
|
}
|
||||||
|
|
||||||
class NearbyMessageFilesRequest : NearbyMessageFilesContent {
|
class NearbyMessageFilesRequest : NearbyMessageFilesContent {
|
||||||
init(files: Array<String>, id: String) {
|
init(files: Array<String>, id: String) {
|
||||||
super.init(files: files, id: id, type: MessageContentType.filesRequest)
|
self.files = files
|
||||||
|
super.init(id: id, type: MessageContentType.filesRequest)
|
||||||
}
|
}
|
||||||
static func fromJson( json: [String: Any]) -> NearbyMessageFilesRequest? {
|
static func fromJson(json: [String: Any]) -> NearbyMessageFilesRequest? {
|
||||||
let message = NearbyMessageFilesContent.fromJsonRaw(type: MessageContentType.filesRequest, json: json)
|
let message = NearbyMessageFilesContent.fromJsonRaw(type: MessageContentType.filesRequest, json: json)
|
||||||
if let requireMessage = message {
|
if let filesObjects: Array = json["files"] as? Array<Dictionary<String, AnyObject>> {
|
||||||
return NearbyMessageFilesRequest(files: requireMessage.files, id: requireMessage.id)
|
let files : [String]? = filesObjects.map({ $0["path"] as? String }).compactMap({$0})
|
||||||
|
if let requireMessage = message {
|
||||||
|
if let requireFiles = files {
|
||||||
|
return NearbyMessageFilesRequest(files: requireFiles, id: requireMessage.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil;
|
||||||
|
}
|
||||||
|
let files: Array<String>
|
||||||
|
|
||||||
|
override func toJson() -> [String : Any] {
|
||||||
|
return [
|
||||||
|
"files": files.map{["path": $0]},
|
||||||
|
].merging( super.toJson()) { (current, _) in current}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NearbyMessageFilesResponse : NearbyMessageFilesContent {
|
class NearbyMessageFilesResponse : NearbyMessageFilesContent {
|
||||||
init(files: Array<String>, id: String, response: Bool) {
|
init(id: String, response: Bool) {
|
||||||
self.response = response
|
self.response = response
|
||||||
super.init(files: files, id: id, type: MessageContentType.filesResponse)
|
super.init(id: id, type: MessageContentType.filesResponse)
|
||||||
}
|
}
|
||||||
static func fromJson( json: [String: Any]) -> NearbyMessageFilesResponse? {
|
static func fromJson( json: [String: Any]) -> NearbyMessageFilesResponse? {
|
||||||
let message = NearbyMessageFilesContent.fromJsonRaw(type: MessageContentType.filesResponse, json: json)
|
let message = NearbyMessageFilesContent.fromJsonRaw(type: MessageContentType.filesResponse, json: json)
|
||||||
if let requireMessage = message,
|
if let requireMessage = message,
|
||||||
let response = json["response"] as? Bool {
|
let response = json["response"] as? Bool {
|
||||||
return NearbyMessageFilesResponse(files: requireMessage.files, id: requireMessage.id, response: response)
|
return NearbyMessageFilesResponse(id: requireMessage.id, response: response)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ class NearbyManager: NSObject {
|
|||||||
do {
|
do {
|
||||||
if let requireDevice = device {
|
if let requireDevice = device {
|
||||||
let message = NearbyMessage(content: content, senderName: self.device.name, senderPeerID: self.device.peerID)
|
let message = NearbyMessage(content: content, senderName: self.device.name, senderPeerID: self.device.peerID)
|
||||||
|
|
||||||
|
if (content is NearbyMessageFilesRequest) {
|
||||||
|
NearbyRequestsStore.instance.add(request: message.content as! NearbyMessageFilesRequest)
|
||||||
|
}
|
||||||
try requireDevice.session?.session?.send(
|
try requireDevice.session?.session?.send(
|
||||||
try JSONSerialization.data(withJSONObject: message.toDictionary()),
|
try JSONSerialization.data(withJSONObject: message.toDictionary()),
|
||||||
toPeers: [requireDevice.peerID],
|
toPeers: [requireDevice.peerID],
|
||||||
|
|||||||
@@ -9,18 +9,21 @@ import Foundation
|
|||||||
import Flutter
|
import Flutter
|
||||||
|
|
||||||
extension NearbyServicePlugin {
|
extension NearbyServicePlugin {
|
||||||
|
|
||||||
@objc func onMessageReceived(notification: Notification) {
|
@objc func onMessageReceived(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 message = NearbyMessage.fromUserInfo(userInfo: userInfo) {
|
if let message = NearbyMessage.fromUserInfo(userInfo: userInfo) {
|
||||||
if message.content is NearbyMessageFilesResponse {
|
if message.content is NearbyMessageFilesResponse {
|
||||||
let response = message.content as! NearbyMessageFilesResponse
|
let response = message.content as! NearbyMessageFilesResponse
|
||||||
if (response.response) {
|
let cachedRequest = NearbyRequestsStore.instance.find(for: response.id)
|
||||||
|
if (response.response && cachedRequest != nil) {
|
||||||
self.manager.sendFiles(
|
self.manager.sendFiles(
|
||||||
id: response.id,
|
id: cachedRequest!.id,
|
||||||
paths: response.files,
|
paths: cachedRequest!.files,
|
||||||
with: message.senderPeerID.displayName
|
with: message.senderPeerID.displayName
|
||||||
)
|
)
|
||||||
|
NearbyRequestsStore.instance.remove(for: cachedRequest!.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.channel.invokeMethod(DART_COMMAND_MESSAGE_RECEIVED, arguments: message.toDartFormat())
|
self.channel.invokeMethod(DART_COMMAND_MESSAGE_RECEIVED, arguments: message.toDartFormat())
|
||||||
@@ -33,7 +36,6 @@ 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) {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// NearbyRequestsStore.swift
|
||||||
|
// nearby_service
|
||||||
|
//
|
||||||
|
// Created by Kseniia Nikitina on 5/2/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class NearbyRequestsStore {
|
||||||
|
static let instance = NearbyRequestsStore()
|
||||||
|
|
||||||
|
private var requests : [NearbyMessageFilesRequest] = []
|
||||||
|
|
||||||
|
|
||||||
|
func add(request: NearbyMessageFilesRequest) {
|
||||||
|
requests.append(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func find(for id: String) -> NearbyMessageFilesRequest? {
|
||||||
|
return requests.first { request in
|
||||||
|
return request.id == id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func remove(for id: String) {
|
||||||
|
self.requests = requests.filter{$0.id != id}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,15 +64,7 @@ sealed class NearbyMessageFilesContent extends NearbyMessageContentBase {
|
|||||||
/// Also [NearbyMessageFilesContent] contains [id] of the files pack and
|
/// Also [NearbyMessageFilesContent] contains [id] of the files pack and
|
||||||
/// list of [NearbyFileInfo] to determine the files.
|
/// list of [NearbyFileInfo] to determine the files.
|
||||||
///
|
///
|
||||||
const NearbyMessageFilesContent({
|
const NearbyMessageFilesContent({required this.id});
|
||||||
required this.id,
|
|
||||||
required this.files,
|
|
||||||
});
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Info about the files to be sent or received.
|
|
||||||
///
|
|
||||||
final List<NearbyFileInfo> files;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// ID of this files pack
|
/// ID of this files pack
|
||||||
@@ -83,51 +75,43 @@ sealed class NearbyMessageFilesContent extends NearbyMessageContentBase {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'id': id,
|
'id': id,
|
||||||
'files': [
|
|
||||||
...files.map((e) => e.toJson()),
|
|
||||||
],
|
|
||||||
...super.toJson(),
|
...super.toJson(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
bool get isValid =>
|
|
||||||
files.isNotEmpty &&
|
|
||||||
files.every(
|
|
||||||
(element) => element.path.isNotEmpty,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is NearbyMessageFilesContent &&
|
other is NearbyMessageFilesContent &&
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
files == other.files &&
|
|
||||||
id == other.id;
|
id == other.id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => files.hashCode ^ id.hashCode;
|
int get hashCode => id.hashCode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'NearbyMessageFilesContent{files: $files, id: $id}';
|
return 'NearbyMessageFilesContent{id: $id}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isValid => id.isNotEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Nearby message File Request. Used for file sending requests.
|
/// Nearby message File Request. Used for files sending requests.
|
||||||
/// Does not contain files' bytes!
|
/// Contains info about the [files].
|
||||||
///
|
///
|
||||||
final class NearbyMessageFilesRequest extends NearbyMessageFilesContent {
|
final class NearbyMessageFilesRequest extends NearbyMessageFilesContent {
|
||||||
const NearbyMessageFilesRequest._({
|
const NearbyMessageFilesRequest._({
|
||||||
required super.id,
|
required super.id,
|
||||||
required super.files,
|
required this.files,
|
||||||
});
|
});
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Basic constructor with [files] to be sent or received.
|
/// Basic constructor with [files] to be sent or received.
|
||||||
///
|
///
|
||||||
NearbyMessageFilesRequest({required super.files})
|
NearbyMessageFilesRequest({required this.files})
|
||||||
: super(
|
: super(
|
||||||
id: RandomUtils.instance.nextInt(1000000, 9999999).toString(),
|
id: RandomUtils.instance.nextInt(1000000, 9999999).toString(),
|
||||||
);
|
);
|
||||||
@@ -146,6 +130,11 @@ final class NearbyMessageFilesRequest extends NearbyMessageFilesContent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Info about the files to be sent or received.
|
||||||
|
///
|
||||||
|
final List<NearbyFileInfo> files;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
NearbyMessageContentType get type => NearbyMessageContentType.filesRequest;
|
NearbyMessageContentType get type => NearbyMessageContentType.filesRequest;
|
||||||
|
|
||||||
@@ -153,6 +142,35 @@ final class NearbyMessageFilesRequest extends NearbyMessageFilesContent {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return 'NearbyMessageFileRequest{id: $id, files: $files}';
|
return 'NearbyMessageFileRequest{id: $id, files: $files}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'files': [
|
||||||
|
...files.map((e) => e.toJson()),
|
||||||
|
],
|
||||||
|
...super.toJson(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isValid =>
|
||||||
|
super.isValid &&
|
||||||
|
files.isNotEmpty &&
|
||||||
|
files.every(
|
||||||
|
(element) => element.path.isNotEmpty,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
super == other &&
|
||||||
|
other is NearbyMessageFilesRequest &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
files == other.files;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => super.hashCode ^ files.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -162,41 +180,19 @@ final class NearbyMessageFilesRequest extends NearbyMessageFilesContent {
|
|||||||
final class NearbyMessageFilesResponse extends NearbyMessageFilesContent {
|
final class NearbyMessageFilesResponse extends NearbyMessageFilesContent {
|
||||||
///
|
///
|
||||||
/// Used to send a response to a previously received request.
|
/// Used to send a response to a previously received request.
|
||||||
/// Provide [id] and [files] from [NearbyMessageFilesRequest] or
|
/// Provide [id] from [NearbyMessageFilesRequest] or
|
||||||
/// Use the [NearbyMessageFilesResponse.fromRequest] factory to generate a
|
|
||||||
/// response.
|
|
||||||
///
|
///
|
||||||
NearbyMessageFilesResponse({
|
NearbyMessageFilesResponse({
|
||||||
required super.id,
|
required super.id,
|
||||||
required super.files,
|
|
||||||
required this.response,
|
required this.response,
|
||||||
});
|
});
|
||||||
|
|
||||||
///
|
|
||||||
/// Factory to quickly create a response to [NearbyMessageFilesRequest].
|
|
||||||
///
|
|
||||||
factory NearbyMessageFilesResponse.fromRequest(
|
|
||||||
NearbyMessageFilesRequest request, {
|
|
||||||
required bool response,
|
|
||||||
}) {
|
|
||||||
return NearbyMessageFilesResponse(
|
|
||||||
id: request.id,
|
|
||||||
files: request.files,
|
|
||||||
response: response,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Gets [NearbyMessageFilesResponse] from [Map]
|
/// Gets [NearbyMessageFilesResponse] from [Map]
|
||||||
///
|
///
|
||||||
factory NearbyMessageFilesResponse.fromJson(Map<String, dynamic>? json) {
|
factory NearbyMessageFilesResponse.fromJson(Map<String, dynamic>? json) {
|
||||||
return NearbyMessageFilesResponse(
|
return NearbyMessageFilesResponse(
|
||||||
id: json?['id'] ?? '',
|
id: json?['id'] ?? '',
|
||||||
files: [
|
|
||||||
...?(json?['files'] as List?)?.map(
|
|
||||||
(e) => NearbyFileInfo.fromJson(e),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
response: json?['response'] ?? false,
|
response: json?['response'] ?? false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -219,6 +215,6 @@ final class NearbyMessageFilesResponse extends NearbyMessageFilesContent {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'NearbyMessageFileResponse{response: $response, id: $id, files: $files}';
|
return 'NearbyMessageFileResponse{response: $response, id: $id}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,15 +12,23 @@ class FileSocketsManager {
|
|||||||
|
|
||||||
NearbyServiceFilesListener? _filesListener;
|
NearbyServiceFilesListener? _filesListener;
|
||||||
NearbyDeviceInfo? _sender;
|
NearbyDeviceInfo? _sender;
|
||||||
|
NearbyMessageFilesRequest? _cachedFilesRequest;
|
||||||
|
Future? _socketCreationFuture;
|
||||||
|
var _connectionData = const NearbyAndroidCommunicationChannelData();
|
||||||
|
|
||||||
void setListener(NearbyServiceFilesListener? listener) {
|
void setListener(NearbyServiceFilesListener? listener) {
|
||||||
_filesListener = listener;
|
_filesListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setConnectionData(NearbyAndroidCommunicationChannelData? data) {
|
||||||
|
_connectionData = data ?? _connectionData;
|
||||||
|
}
|
||||||
|
|
||||||
void onWsRequest(HttpRequest request) {
|
void onWsRequest(HttpRequest request) {
|
||||||
final type = NearbySocketType.fromRequest(request);
|
final type = NearbySocketType.fromRequest(request);
|
||||||
final filesPackId = NearbyFilesPackId.fromRequest(request);
|
final filesPackId = NearbyFilesPackId.fromRequest(request);
|
||||||
if (type == NearbySocketType.file && filesPackId != null) {
|
if (type == NearbySocketType.file && filesPackId != null) {
|
||||||
|
Logger.debug('Save a connection request $filesPackId from client');
|
||||||
_serverWaitingRequests[filesPackId] = request;
|
_serverWaitingRequests[filesPackId] = request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,42 +36,62 @@ class FileSocketsManager {
|
|||||||
Future<void> handleFileMessageContent(
|
Future<void> handleFileMessageContent(
|
||||||
NearbyMessageFilesContent content, {
|
NearbyMessageFilesContent content, {
|
||||||
required NearbyDeviceInfo? sender,
|
required NearbyDeviceInfo? sender,
|
||||||
required NearbyAndroidCommunicationChannelData androidData,
|
|
||||||
required bool isReceived,
|
required bool isReceived,
|
||||||
}) async {
|
}) async {
|
||||||
if (sender != null) {
|
if (sender != null) {
|
||||||
_sender = sender;
|
_sender = sender;
|
||||||
Logger.debug('Sender was set to $_sender');
|
Logger.debug('Sender was set to $_sender');
|
||||||
}
|
}
|
||||||
|
final socketExists = _filesSockets[content.id] != null;
|
||||||
|
|
||||||
final shouldStartSocket = content.byType(
|
final isRequest = content is NearbyMessageFilesRequest;
|
||||||
onFilesResponse: (response) => response.response,
|
|
||||||
onFilesRequest: (_) => true,
|
|
||||||
) ??
|
|
||||||
false;
|
|
||||||
|
|
||||||
final alreadyExists = _filesSockets[content.id] != null;
|
final isPositiveResponse =
|
||||||
|
content is NearbyMessageFilesResponse && content.response;
|
||||||
|
|
||||||
if (shouldStartSocket && !alreadyExists) {
|
if (isRequest) {
|
||||||
|
_cachedFilesRequest = content;
|
||||||
|
Logger.debug('Files pack request ${content.id} was cached');
|
||||||
|
}
|
||||||
|
if (!socketExists) {
|
||||||
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);
|
if (isPositiveResponse && _cachedFilesRequest != null) {
|
||||||
if (isReceived && content is NearbyMessageFilesResponse) {
|
_socketCreationFuture = _startFilesServerSocket(
|
||||||
await _startDataTransfer(content);
|
_cachedFilesRequest!,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await _connectToFilesSocket(
|
NearbyMessageFilesRequest? request;
|
||||||
content,
|
|
||||||
connectionData: androidData,
|
if (!isReceived &&
|
||||||
ownerIpAddress: info.ownerIpAddress,
|
isPositiveResponse &&
|
||||||
);
|
_cachedFilesRequest != null) {
|
||||||
if (!isReceived && content is NearbyMessageFilesRequest) {
|
request = _cachedFilesRequest!;
|
||||||
await _startDataTransfer(content);
|
} else if (isRequest) {
|
||||||
|
request = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request != null) {
|
||||||
|
_socketCreationFuture = _connectToFilesSocket(
|
||||||
|
request,
|
||||||
|
ownerIpAddress: info.ownerIpAddress,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isReceived && isPositiveResponse && _cachedFilesRequest != null) {
|
||||||
|
await _socketCreationFuture?.whenComplete(
|
||||||
|
() async {
|
||||||
|
await _startDataTransfer(_cachedFilesRequest!);
|
||||||
|
_socketCreationFuture = null;
|
||||||
|
_cachedFilesRequest = null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> closeAll() async {
|
Future<void> closeAll() async {
|
||||||
@@ -72,39 +100,39 @@ class FileSocketsManager {
|
|||||||
}
|
}
|
||||||
_filesSockets.clear();
|
_filesSockets.clear();
|
||||||
_filesListener = null;
|
_filesListener = null;
|
||||||
|
_cachedFilesRequest = null;
|
||||||
|
_socketCreationFuture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _connectToFilesSocket(
|
Future<void> _connectToFilesSocket(
|
||||||
NearbyMessageFilesContent content, {
|
NearbyMessageFilesRequest filesRequest, {
|
||||||
required NearbyAndroidCommunicationChannelData connectionData,
|
|
||||||
required String ownerIpAddress,
|
required String ownerIpAddress,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _network.pingServer(
|
final response = await _network.pingServer(
|
||||||
address: ownerIpAddress,
|
address: ownerIpAddress,
|
||||||
port: connectionData.port,
|
port: _connectionData.port,
|
||||||
);
|
);
|
||||||
if (await _pingManager.checkPong(response)) {
|
if (await _pingManager.checkPong(response)) {
|
||||||
await _tryStartFileSocket(
|
await _startFilesSocket(
|
||||||
content,
|
filesRequest,
|
||||||
onCreateSocket: () => _network.connectToSocket(
|
onCreateSocket: () => _network.connectToSocket(
|
||||||
ownerIpAddress: ownerIpAddress,
|
ownerIpAddress: ownerIpAddress,
|
||||||
port: connectionData.port,
|
port: _connectionData.port,
|
||||||
socketType: NearbySocketType.file,
|
socketType: NearbySocketType.file,
|
||||||
headers: {
|
headers: {
|
||||||
NearbyFilesPackId.key: content.id,
|
NearbyFilesPackId.key: filesRequest.id,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Logger.debug(
|
Logger.debug(
|
||||||
'Files server is unavailable, reconnect in ${connectionData.clientReconnectInterval}s',
|
'Files server is unavailable, reconnect in ${_connectionData.clientReconnectInterval}s',
|
||||||
);
|
);
|
||||||
await Future.delayed(
|
await Future.delayed(
|
||||||
connectionData.clientReconnectInterval,
|
_connectionData.clientReconnectInterval,
|
||||||
() => _connectToFilesSocket(
|
() => _connectToFilesSocket(
|
||||||
content,
|
filesRequest,
|
||||||
connectionData: connectionData,
|
|
||||||
ownerIpAddress: ownerIpAddress,
|
ownerIpAddress: ownerIpAddress,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -114,50 +142,52 @@ class FileSocketsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _startFilesServer(NearbyMessageFilesContent content) async {
|
Future<void> _startFilesServerSocket(
|
||||||
final request = _serverWaitingRequests[content.id];
|
NearbyMessageFilesRequest filesRequest,
|
||||||
|
) async {
|
||||||
|
final connectionRequest = _serverWaitingRequests[filesRequest.id];
|
||||||
|
|
||||||
if (request != null) {
|
if (connectionRequest != null) {
|
||||||
Logger.debug('Found cached server file request ${content.id}');
|
Logger.debug('Found cached server files request ${filesRequest.id}');
|
||||||
|
|
||||||
final result = await _tryStartFileSocket(
|
final result = await _startFilesSocket(
|
||||||
content,
|
filesRequest,
|
||||||
onCreateSocket: () => WebSocketTransformer.upgrade(request),
|
onCreateSocket: () => WebSocketTransformer.upgrade(connectionRequest),
|
||||||
);
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
_serverWaitingRequests.remove(content.id);
|
_serverWaitingRequests.remove(filesRequest.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _tryStartFileSocket(
|
Future<bool> _startFilesSocket(
|
||||||
NearbyMessageFilesContent content, {
|
NearbyMessageFilesRequest filesRequest, {
|
||||||
required Future<WebSocket?> Function() onCreateSocket,
|
required Future<WebSocket?> Function() onCreateSocket,
|
||||||
}) async {
|
}) async {
|
||||||
final socket = await onCreateSocket();
|
final socket = await onCreateSocket();
|
||||||
if (socket != null && _sender != null) {
|
if (socket != null && _sender != null) {
|
||||||
_filesSockets[content.id] = FilesSocket.startListening(
|
_filesSockets[filesRequest.id] = FilesSocket.startListening(
|
||||||
sender: _sender!,
|
sender: _sender!,
|
||||||
content: content,
|
filesRequest: filesRequest,
|
||||||
socket: socket,
|
socket: socket,
|
||||||
listener: _filesListener,
|
listener: _filesListener,
|
||||||
onDestroy: _filesSockets.remove,
|
onDestroy: _filesSockets.remove,
|
||||||
);
|
);
|
||||||
Logger.info('Created a socket for the files pack ${content.id}');
|
Logger.info('Created a socket for the files pack ${filesRequest.id}');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _startDataTransfer(NearbyMessageFilesContent content) async {
|
Future<void> _startDataTransfer(NearbyMessageFilesRequest request) async {
|
||||||
final filesSocket = _filesSockets[content.id];
|
final filesSocket = _filesSockets[request.id];
|
||||||
if (filesSocket != null) {
|
if (filesSocket != null) {
|
||||||
Logger.debug('Start transferring the files pack ${content.id}');
|
Logger.debug('Start transferring the files pack ${request.id}');
|
||||||
for (var i = 0; i < content.files.length; i++) {
|
for (var i = 0; i < request.files.length; i++) {
|
||||||
try {
|
try {
|
||||||
final fileInfo = content.files[i];
|
final fileInfo = request.files[i];
|
||||||
await _streamFile(
|
await _streamFile(
|
||||||
content.id,
|
request.id,
|
||||||
filesSocket: filesSocket,
|
filesSocket: filesSocket,
|
||||||
file: File(fileInfo.path),
|
file: File(fileInfo.path),
|
||||||
)?.asFuture();
|
)?.asFuture();
|
||||||
@@ -170,7 +200,7 @@ class FileSocketsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
filesSocket.sendData(FilesSocket.finishCommand);
|
filesSocket.sendData(FilesSocket.finishCommand);
|
||||||
Logger.debug('Sent finish command for the pack ${content.id}');
|
Logger.debug('Sent finish command for the pack ${request.id}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ class NearbySocketService {
|
|||||||
_androidData = data.androidData;
|
_androidData = data.androidData;
|
||||||
_connectedDeviceId = data.connectedDeviceId;
|
_connectedDeviceId = data.connectedDeviceId;
|
||||||
|
|
||||||
_fileSocketsManager.setListener(data.filesListener);
|
_fileSocketsManager
|
||||||
|
..setListener(data.filesListener)
|
||||||
|
..setConnectionData(data.androidData);
|
||||||
|
|
||||||
final info = await _service.getConnectionInfo();
|
final info = await _service.getConnectionInfo();
|
||||||
|
|
||||||
@@ -239,7 +241,6 @@ class NearbySocketService {
|
|||||||
message.content as NearbyMessageFilesContent,
|
message.content as NearbyMessageFilesContent,
|
||||||
isReceived: message is ReceivedNearbyMessage,
|
isReceived: message is ReceivedNearbyMessage,
|
||||||
sender: message is ReceivedNearbyMessage ? message.sender : null,
|
sender: message is ReceivedNearbyMessage ? message.sender : null,
|
||||||
androidData: _androidData,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import 'package:path_provider/path_provider.dart';
|
|||||||
class FilesSocket {
|
class FilesSocket {
|
||||||
FilesSocket.startListening({
|
FilesSocket.startListening({
|
||||||
required this.sender,
|
required this.sender,
|
||||||
required this.content,
|
required this.filesRequest,
|
||||||
required this.listener,
|
required this.listener,
|
||||||
required this.onDestroy,
|
required this.onDestroy,
|
||||||
required WebSocket socket,
|
required WebSocket socket,
|
||||||
@@ -29,7 +29,7 @@ class FilesSocket {
|
|||||||
|
|
||||||
static String separateCommandOf(int index) => '$separateCommand$index';
|
static String separateCommandOf(int index) => '$separateCommand$index';
|
||||||
|
|
||||||
final NearbyMessageFilesContent content;
|
final NearbyMessageFilesRequest filesRequest;
|
||||||
final void Function(String) onDestroy;
|
final void Function(String) onDestroy;
|
||||||
final NearbyServiceFilesListener? listener;
|
final NearbyServiceFilesListener? listener;
|
||||||
final NearbyDeviceInfo sender;
|
final NearbyDeviceInfo sender;
|
||||||
@@ -52,7 +52,7 @@ class FilesSocket {
|
|||||||
final logStep = min(pow(10, _chunksCount.toString().length - 1), 100);
|
final logStep = min(pow(10, _chunksCount.toString().length - 1), 100);
|
||||||
if (_chunksCount % logStep == 0) {
|
if (_chunksCount % logStep == 0) {
|
||||||
Logger.debug(
|
Logger.debug(
|
||||||
'Got $_chunksCount chunks for the file ${content.files[_currentFileIndex].name}',
|
'Got $_chunksCount chunks for the file ${filesRequest.files[_currentFileIndex].name}',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ class FilesSocket {
|
|||||||
_bytesTable['$_currentFileIndex'] = [];
|
_bytesTable['$_currentFileIndex'] = [];
|
||||||
} 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 ${filesRequest.id} was created');
|
||||||
|
|
||||||
listener?.onData.call(
|
listener?.onData.call(
|
||||||
ReceivedNearbyFilesPack(
|
ReceivedNearbyFilesPack(
|
||||||
@@ -74,14 +74,14 @@ class FilesSocket {
|
|||||||
files: _files,
|
files: _files,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
onDestroy(content.id);
|
onDestroy(filesRequest.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _createFile(int index) async {
|
Future<void> _createFile(int index) async {
|
||||||
try {
|
try {
|
||||||
final bytes = _bytesTable['$index']!;
|
final bytes = _bytesTable['$index']!;
|
||||||
final fileInfo = content.files[index];
|
final fileInfo = filesRequest.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);
|
||||||
|
|||||||
Reference in New Issue
Block a user