feat(ios): files sending

This commit is contained in:
ksenia312
2024-02-04 16:23:48 +01:00
parent 32a9f2a923
commit 66a79eb4ba
29 changed files with 682 additions and 236 deletions
+35
View File
@@ -0,0 +1,35 @@
//
// NearbyCommand.swift
// nearby_service
//
// Created by Kseniia Nikitina on 4/2/24.
//
import Foundation
class NearbyStartCommand {
init( id: String, filesCount: Int) {
self.id = id
self.filesCount = filesCount
}
static func fromUserInfo(userInfo: NearbyUserInfo)-> NearbyStartCommand? {
if let id = userInfo.dictionary["id"] as? String ,
let filesCount = userInfo.dictionary["filesCount"] as? Int
{
return NearbyStartCommand(
id: id, filesCount: filesCount
)
}
return nil
}
func toDictionary() -> [String: Any] {
return ["id": id, "filesCount": filesCount]
}
let id: String
let filesCount: Int
}
+86
View File
@@ -0,0 +1,86 @@
import Foundation
import MultipeerConnectivity
class NearbyDevice : NSObject {
var name: String
var peerID: MCPeerID
var deviceType: String?
var os: String?
var osVersion: String?
var session: NearbySession?
init(
peerID: MCPeerID,
name:String,
deviceType:String? = nil,
os: String? = nil,
osVersion: String? = nil
) {
self.name=name
self.peerID = peerID
self.deviceType=deviceType
self.os=os
self.osVersion=osVersion
}
func createSession(for peerID: MCPeerID) -> NearbySession {
self.session = NearbySession.create(peerID: peerID)
return session!
}
func deleteSession() {
self.session = nil
}
}
extension NearbyDevice {
static func fromDictionary(for dictionary: [String: String]?, with peerID: MCPeerID) -> NearbyDevice {
let device = NearbyDevice(
peerID: peerID,
name:(dictionary?["displayName"] as String?) ?? peerID.displayName,
deviceType: dictionary?["deviceType"] as String?,
os: dictionary?["os"] as String?,
osVersion: dictionary?["osVersion"] as String?
)
return device
}
func toDictionary() -> [String: String] {
var deviceDict: [String: String] = [
"displayName": self.name,
"id": self.peerID.displayName,
]
if let os = self.os {
deviceDict["os"] = os
}
if let deviceType = self.deviceType {
deviceDict["deviceType"] = deviceType
}
if let osVersion = self.osVersion {
deviceDict["osVersion"] = osVersion
}
if let session = self.session {
deviceDict["state"] = String(session.state.rawValue)
} else {
deviceDict["state"] = String(0)
}
return deviceDict
}
func toDartFormat() -> String? {
var result: String?
do {
let jsonData = try JSONSerialization.data(withJSONObject: toDictionary())
if let jsonString = String(data: jsonData, encoding: .utf8) {
result = jsonString
}
} catch let error {
Logger.error(message: error.localizedDescription)
}
return result
}
}
+60
View File
@@ -0,0 +1,60 @@
//
// NearbyMessage.swift
// nearby_service
//
// Created by Kseniia Nikitina on 4/2/24.
//
import Foundation
import MultipeerConnectivity
class NearbyMessage {
init(content: NearbyMessageContent, senderName: String, senderPeerID: MCPeerID) {
self.content = content
self.senderName = senderName
self.senderPeerID = senderPeerID
}
let content: NearbyMessageContent
let senderPeerID: MCPeerID
let senderName: String
static func fromUserInfo(userInfo: NearbyUserInfo)-> NearbyMessage? {
if let jsonContent = userInfo.dictionary["content"] as? [String : Any],
let content = NearbyMessageContent.typedFromJson(json: jsonContent),
let name = userInfo.dictionary["name"] as? String {
return NearbyMessage(
content: content,
senderName: name,
senderPeerID: userInfo.peerID
)
}
return nil
}
func toDictionary() -> [String: Any] {
return [
"name": senderName,
"content": content.toJson()
]
}
func toDartFormat() -> String? {
do {
let object = [
"sender": ["id": senderPeerID.displayName, "displayName": senderName],
"content": content.toJson()
]
let jsonData = try JSONSerialization.data(withJSONObject: object)
if let jsonString = String(data: jsonData, encoding: .utf8) {
return jsonString
}
} catch let error {
Logger.error(message: error.localizedDescription)
}
return nil
}
}
@@ -0,0 +1,149 @@
//
// NearbyMessage.swift
// nearby_service
//
// Created by Kseniia Nikitina on 4/2/24.
//
import Foundation
import MultipeerConnectivity
class NearbyMessageContent {
init(type: MessageContentType) {
self.type = type
}
let type: MessageContentType
static func typedFromJson(json: [String: Any]) -> NearbyMessageContent? {
if let typeString: String = json["type"] as? String {
let type = MessageContentType.fromString(value: typeString)
if (type == MessageContentType.text) {
return NearbyMessageTextContent.fromJson(json: json)
} else if (type == MessageContentType.filesRequest) {
return NearbyMessageFilesRequest.fromJson(json: json)
} else if (type == MessageContentType.filesResponse) {
return NearbyMessageFilesResponse.fromJson(json: json)
}
}
return nil;
}
func toJson() -> [String : Any] {
return ["type": type.name]
}
}
class NearbyMessageTextContent : NearbyMessageContent {
init(value: String) {
self.value = value
super.init(type: MessageContentType.text)
}
static func fromJson(json:[String: Any]) -> NearbyMessageTextContent? {
if let message: String = json["value"] as? String {
return NearbyMessageTextContent(value: message)
}
return nil;
}
override func toJson() -> [String : Any] {
return ["value": value].merging( super.toJson()) { (current, _) in current}
}
let value: String
}
class NearbyMessageFilesContent : NearbyMessageContent {
init(files: Array<String>, id: String, type: MessageContentType) {
self.files = files
self.id = id
super.init(type: type)
}
static func fromJsonRaw(type: MessageContentType, json: [String: Any]) -> NearbyMessageFilesContent? {
if let filesObjects: Array = json["files"] as? Array<Dictionary<String, AnyObject>> {
let files : [String]? = filesObjects.map({ $0["path"] as? String }).compactMap({$0})
if let id: String = json["id"] as? String{
if let requireFiles = files {
return NearbyMessageFilesContent(files: requireFiles, id: id, type: type)
}
}
}
return nil;
}
override func toJson() -> [String : Any] {
return [
"files": files.map{["path": $0]},
"id": id,
].merging( super.toJson()) { (current, _) in current}
}
let files: Array<String>
let id: String
}
class NearbyMessageFilesRequest : NearbyMessageFilesContent {
init(files: Array<String>, id: String) {
super.init(files: files, id: id, type: MessageContentType.filesRequest)
}
static func fromJson( json: [String: Any]) -> NearbyMessageFilesRequest? {
let message = NearbyMessageFilesContent.fromJsonRaw(type: MessageContentType.filesRequest, json: json)
if let requireMessage = message {
return NearbyMessageFilesRequest(files: requireMessage.files, id: requireMessage.id)
}
return nil
}
}
class NearbyMessageFilesResponse : NearbyMessageFilesContent {
init(files: Array<String>, id: String, response: Bool) {
self.response = response
super.init(files: files, id: id, type: MessageContentType.filesResponse)
}
static func fromJson( json: [String: Any]) -> NearbyMessageFilesResponse? {
let message = NearbyMessageFilesContent.fromJsonRaw(type: MessageContentType.filesResponse, json: json)
if let requireMessage = message,
let response = json["response"] as? Bool {
return NearbyMessageFilesResponse(files: requireMessage.files, id: requireMessage.id, response: response)
}
return nil
}
override func toJson() -> [String : Any] {
return [
"response": response
].merging( super.toJson()) { (current, _) in current}
}
let response: Bool
}
enum MessageContentType {
case text
case filesRequest
case filesResponse
static func fromString(value: String) -> MessageContentType {
if (value == text.name) {
return text
} else if (value == filesRequest.name) {
return filesRequest
} else if (value == filesResponse.name) {
return filesResponse
} else {
return text
}
}
var name : String {
switch self {
case .text: return "text"
case .filesRequest: return "filesRequest"
case .filesResponse: return "filesResponse"
}
}
}
+65
View File
@@ -0,0 +1,65 @@
//
// NearbySession.swift
// nearby_service
//
// Created by Kseniia Nikitina on 16/1/24.
//
import Foundation
import MultipeerConnectivity
class NearbySession: NSObject {
var session: MCSession!
var state: MCSessionState = MCSessionState.notConnected
private init(peerID: MCPeerID) {
self.session = MCSession(peer: peerID)
}
static func create(peerID: MCPeerID) -> NearbySession {
let instance = NearbySession(peerID: peerID)
instance.session.delegate = instance
return instance
}
}
extension NearbySession: MCSessionDelegate {
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
self.state = state
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
NotificationCenter.default.post(
name: ON_MESSAGE_RECEIVED,
object: nil,
userInfo: NearbyUserInfo.message(peerID: peerID, data: data)?.toDictionary()
)
}
func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {}
func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
}
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
guard let localURL = localURL else { return }
let destinationURL = localURL.deletingLastPathComponent().appendingPathComponent("\(resourceName)")
do {
try FileManager.default.moveItem(at: localURL, to: destinationURL)
} catch {
Logger.error(message: "Error moving file: \(error)")
}
NotificationCenter.default.post(
name: ON_RESOURCE_RECEIVED,
object: nil,
userInfo: NearbyUserInfo.resource(peerID: peerID, url: destinationURL)?.toDictionary()
)
}
}
+58
View File
@@ -0,0 +1,58 @@
//
// NearbyUserInfo.swift
// nearby_service
//
// Created by Kseniia Nikitina on 4/2/24.
//
import Foundation
import MultipeerConnectivity
class NearbyUserInfo {
init(peerID: MCPeerID, dictionary: [String: Any]) {
self.peerID = peerID
self.dictionary = dictionary
}
static func resource(peerID: MCPeerID, url: URL?) -> NearbyUserInfo? {
var dictionary: [String: Any] = [:]
if let requireUrl = url {
dictionary["url"] = requireUrl
}
return NearbyUserInfo(
peerID: peerID,
dictionary: dictionary
)
}
static func message(peerID: MCPeerID, data: Data) -> NearbyUserInfo? {
do {
if let dict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
return NearbyUserInfo(
peerID: peerID,
dictionary: dict
)
}
} catch let error {
Logger.error(message: error.localizedDescription)
}
return nil
}
static func fromDictionary(userInfo: [AnyHashable : Any]?) -> NearbyUserInfo? {
if let dictionary = userInfo?["dictionary"] as? [String: Any],
let peerID = userInfo?["peerID"] as? MCPeerID {
return NearbyUserInfo(peerID: peerID, dictionary:dictionary)
}
return nil
}
func toDictionary() -> [AnyHashable : Any]? {
return ["peerID": peerID, "dictionary": dictionary]
}
let peerID: MCPeerID
let dictionary: [String: Any]
}