Commit dabd9d58 authored by shigemi miura's avatar shigemi miura

画像送信関連修正

parent 8af9e919
PODS:
- AzureNotificationHubs-iOS (3.1.5)
- SwiftSignalRClient (1.0.0)
- SwiftSignalRClient (1.1.0)
DEPENDENCIES:
- AzureNotificationHubs-iOS
......@@ -13,7 +13,7 @@ SPEC REPOS:
SPEC CHECKSUMS:
AzureNotificationHubs-iOS: e5de62f44d7915a5cc3c5194ddc57cf2ee78873e
SwiftSignalRClient: f9a23a0407d490a799cc1a3c8835b8611128d76c
SwiftSignalRClient: 2fa651ea18d47c5aaa135f0c8cf959239c845999
PODFILE CHECKSUM: bbdabe3b255c91674ba1766a3ec70d307854a5a9
......
PODS:
- AzureNotificationHubs-iOS (3.1.5)
- SwiftSignalRClient (1.0.0)
- SwiftSignalRClient (1.1.0)
DEPENDENCIES:
- AzureNotificationHubs-iOS
......@@ -13,7 +13,7 @@ SPEC REPOS:
SPEC CHECKSUMS:
AzureNotificationHubs-iOS: e5de62f44d7915a5cc3c5194ddc57cf2ee78873e
SwiftSignalRClient: f9a23a0407d490a799cc1a3c8835b8611128d76c
SwiftSignalRClient: 2fa651ea18d47c5aaa135f0c8cf959239c845999
PODFILE CHECKSUM: bbdabe3b255c91674ba1766a3ec70d307854a5a9
......
......@@ -116,10 +116,5 @@ There are several sample projects in the `Examples` folder. They include:
**"Failed to bind to address http://0.0.0.0:5000: address already in use."**. This is due to Apple now advertising an 'AirPlay Receiver' on that port.
This port can be freed by disabling the receiver: Navigate to _System Preferences > Sharing_ and uncheck _AirPlay Receiver_.
## Disclaimer
I am providing code in the repository to you under an open source license. Because this is my personal repository, the license you receive to my code is from me
and not my employer (Facebook)
## Hits
[![HitCount](http://hits.dwyl.com/moozzyk/Signalr-Client-Swift.svg)](http://hits.dwyl.com/moozzyk/Signalr-Client-Swift)
......@@ -47,7 +47,14 @@ public class HttpConnectionOptions {
The timeout value for individual requests, in seconds.
*/
public var requestTimeout: TimeInterval = 120
/**
The maximum number of bytes to buffer before the receive call fails with an error.
This value includes the sum of all bytes from continuation frames. Receive calls will fail once the task reaches this limit. (URLSessionWebSocketTask)
*/
public var maximumWebsocketMessageSize: Int?
public var authenticationChallengeHandler: ((_ session: URLSession, _ challenge: URLAuthenticationChallenge, _ completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)?
/**
......
......@@ -171,6 +171,7 @@ public class HubConnectionBuilder {
httpConnectionOptionsCopy.skipNegotiation = httpConnectionOptions.skipNegotiation
}
httpConnectionOptionsCopy.requestTimeout = httpConnectionOptions.requestTimeout
httpConnectionOptionsCopy.maximumWebsocketMessageSize = httpConnectionOptions.maximumWebsocketMessageSize
httpConnectionOptionsCopy.callbackQueue = httpConnectionOptions.callbackQueue
httpConnectionOptionsCopy.authenticationChallengeHandler = httpConnectionOptions.authenticationChallengeHandler
return HttpConnection(url: url, options: httpConnectionOptionsCopy, transportFactory: transportFactory, logger: logger)
......
......@@ -35,7 +35,10 @@ public class WebsocketsTransport: NSObject, Transport, URLSessionWebSocketDelega
setAccessToken(accessTokenProvider: options.accessTokenProvider, request: &request)
urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
webSocketTask = urlSession!.webSocketTask(with: request)
if let maximumWebsocketMessageSize = options.maximumWebsocketMessageSize {
webSocketTask?.maximumMessageSize = maximumWebsocketMessageSize
}
webSocketTask!.resume()
}
......
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<string>1.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -111,6 +111,8 @@
D59908C62B19EA70000E13DD /* ResPushHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59908C52B19EA70000E13DD /* ResPushHistory.swift */; };
D59908C82B1ABD43000E13DD /* SessionPushHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59908C72B1ABD43000E13DD /* SessionPushHistory.swift */; };
D59908CA2B1AC381000E13DD /* GetPushHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59908C92B1AC381000E13DD /* GetPushHistory.swift */; };
D5A4C2532E7AB48700642D7D /* SpeechRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A4C2522E7AB46B00642D7D /* SpeechRecognizer.swift */; };
D5AAB69D2E7A5E8F0027CD90 /* AlertModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AAB69C2E7A5E8F0027CD90 /* AlertModifiers.swift */; };
D5AE351A2AEBA66A00059889 /* ReqLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AE35182AEBA66A00059889 /* ReqLogin.swift */; };
D5AE351B2AEBA66A00059889 /* ResLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AE35192AEBA66A00059889 /* ResLogin.swift */; };
D5AE351D2AEBA6FC00059889 /* SessionLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AE351C2AEBA6FC00059889 /* SessionLogin.swift */; };
......@@ -284,6 +286,8 @@
D59908C52B19EA70000E13DD /* ResPushHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ResPushHistory.swift; path = Sailassist/Json/ResPushHistory.swift; sourceTree = SOURCE_ROOT; };
D59908C72B1ABD43000E13DD /* SessionPushHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SessionPushHistory.swift; path = Sailassist/ServerSession/SessionPushHistory.swift; sourceTree = SOURCE_ROOT; };
D59908C92B1AC381000E13DD /* GetPushHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GetPushHistory.swift; path = Sailassist/Alert/GetPushHistory.swift; sourceTree = SOURCE_ROOT; };
D5A4C2522E7AB46B00642D7D /* SpeechRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpeechRecognizer.swift; sourceTree = "<group>"; };
D5AAB69C2E7A5E8F0027CD90 /* AlertModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertModifiers.swift; sourceTree = "<group>"; };
D5AE35182AEBA66A00059889 /* ReqLogin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ReqLogin.swift; path = Sailassist/Json/ReqLogin.swift; sourceTree = SOURCE_ROOT; };
D5AE35192AEBA66A00059889 /* ResLogin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResLogin.swift; path = Sailassist/Json/ResLogin.swift; sourceTree = SOURCE_ROOT; };
D5AE351C2AEBA6FC00059889 /* SessionLogin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SessionLogin.swift; path = Sailassist/ServerSession/SessionLogin.swift; sourceTree = SOURCE_ROOT; };
......@@ -439,7 +443,7 @@
020B983E2AD8C3500029DE4C /* Tab */ = {
isa = PBXGroup;
children = (
02C3E5CF2AFCC15700AF7837 /* View */,
D5AAB69C2E7A5E8F0027CD90 /* AlertModifiers.swift */,
02CE4DC92ADF9D2E002E79BC /* ViewModel */,
020B98582AD92A4C0029DE4C /* MainTabView.swift */,
);
......@@ -617,6 +621,7 @@
02A1DE2D2AFB497B005BCF55 /* View */ = {
isa = PBXGroup;
children = (
D5A4C2522E7AB46B00642D7D /* SpeechRecognizer.swift */,
02C3E5D02AFCC16800AF7837 /* ChatTitleView.swift */,
02A1DE2E2AFB4AA0005BCF55 /* ChatInputView.swift */,
02A1DE302AFB61D8005BCF55 /* MyChatContentView.swift */,
......@@ -630,13 +635,6 @@
path = View;
sourceTree = "<group>";
};
02C3E5CF2AFCC15700AF7837 /* View */ = {
isa = PBXGroup;
children = (
);
path = View;
sourceTree = "<group>";
};
02CE4D7D2ADE4297002E79BC /* View */ = {
isa = PBXGroup;
children = (
......@@ -1103,7 +1101,9 @@
D5258CA32B036CC500365276 /* SessionGetMessage.swift in Sources */,
D52C2C082B9195A8003B286C /* MenuInformationView.swift in Sources */,
D5258C992B0334BF00365276 /* SessionShipStatus.swift in Sources */,
D5AAB69D2E7A5E8F0027CD90 /* AlertModifiers.swift in Sources */,
02CE4D872ADF62A7002E79BC /* EcaListView.swift in Sources */,
D5A4C2532E7AB48700642D7D /* SpeechRecognizer.swift in Sources */,
D5E008762B2ADD5900C4070A /* MenuManualRADARView.swift in Sources */,
D59908C62B19EA70000E13DD /* ResPushHistory.swift in Sources */,
D58EF2472B9044C800FB784C /* ResInformation.swift in Sources */,
......@@ -1281,7 +1281,7 @@
CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 62;
DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\"";
DEVELOPMENT_TEAM = D2DC7QNNJ8;
ENABLE_PREVIEWS = YES;
......@@ -1330,7 +1330,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 62;
DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\"";
DEVELOPMENT_TEAM = D2DC7QNNJ8;
ENABLE_PREVIEWS = YES;
......@@ -1516,7 +1516,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 58;
CURRENT_PROJECT_VERSION = 62;
DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\"";
DEVELOPMENT_TEAM = D2DC7QNNJ8;
ENABLE_PREVIEWS = YES;
......
......@@ -15,7 +15,7 @@ struct NotificationView: View {
TitleView()
ScrollView {
ForEach(pushHist.pushHistoryData.map{ $1 }.sorted{ $0.id ?? 0 > $1.id ?? 0 }, id: \.id){ data in
ForEach(pushHist.pushHistoryData.map{ $1 }.filter { $0.id != nil }.sorted{ ($0.id ?? 0) > ($1.id ?? 0) }, id: \.id){ data in
NotificationContentView(pushData: data)
.onTapGesture {
if let position = data.position {
......@@ -38,12 +38,10 @@ struct NotificationView: View {
.onAppear {
let pushCount = pushHist.viewCnt
print(debug: "\(pushCount)")
pushHist.viewCnt = 0
DispatchQueue.main.async {
pushHist.viewCnt = 0
}
}
// .onChange(of: pushHist.pushHistoryData.count) { newValue in
// let pushCount = pushHist.viewCnt
// print(debug: "\(pushCount)")
// }
}
struct TitleView: View {
......
......@@ -14,7 +14,7 @@ struct NotificationContentView: View {
var body: some View {
VStack(alignment: .leading, spacing: 4){
HStack(spacing: 10) {
Text(pushData.time ?? "2023-07-13T08::17:40Z")
Text(pushData.time ?? "2023-07-13T08:17:40Z")
.foregroundColor(ColorSet.BodyDescriptiion.color)
.font(FontStyle.SupplementText2.font)
......
......@@ -16,7 +16,7 @@ struct ChatView: View {
var body: some View {
ZStack {
if message.mode == true {
if message.mode {
LinearGradient(gradient: Gradient(colors: [.chatEmargencyColor1, .chatEmargencyColor2]), startPoint: .top, endPoint: .bottom)
.ignoresSafeArea()
}
......@@ -48,8 +48,10 @@ struct ChatView: View {
}
}
.onAppear {
if let id = message.messages.last?.messageId {
proxy.scrollTo(id, anchor: .bottom)
guard !message.messages.isEmpty,
let id = message.messages.last?.messageId else { return }
proxy.scrollTo(id, anchor: .bottom)
DispatchQueue.main.async {
message.viewCnt = 0
}
}
......@@ -118,7 +120,7 @@ struct AlertChatMessage: View {
var message : ChatMessage
var body: some View {
if message.mode == 1 {
if message.mode == ChatMode.warningProgress.rawValue {
HStack() {
Rectangle()
.fill(ColorSet.ChatDate.color)
......
......@@ -56,7 +56,7 @@ class GetMessage {
}
}
SharingData.message.viewCnt = msgCnt - viewCnt //未読数
// SharingData.message.viewCnt = msgCnt - viewCnt //未読数
}
/**
......
......@@ -69,15 +69,12 @@ struct MyChatContentView: View {
var shipViewer = 0
var companyViewr = 0
for viewer in message.viewer {
//船のIDは全て同じ
// if viewer.id != String(SharingData.my.id) {
if viewer.location == 1 {
companyViewr += 1
} else {
shipViewer += 1
}
if viewer.location == 1 {
companyViewr += 1
} else {
shipViewer += 1
}
// }
}
return (shipViewer, companyViewr)
}
}
......
import Foundation
import Speech
import AVFoundation
class SpeechRecognizer: ObservableObject {
private var audioEngine = AVAudioEngine()
private var request = SFSpeechAudioBufferRecognitionRequest()
private var recognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))
private var task: SFSpeechRecognitionTask?
@Published var transcribedText = ""
func startRecording() {
SFSpeechRecognizer.requestAuthorization { authStatus in
guard authStatus == .authorized else { return }
let node = self.audioEngine.inputNode
let recordingFormat = node.outputFormat(forBus: 0)
node.removeTap(onBus: 0)
node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
self.request.append(buffer)
}
self.audioEngine.prepare()
try? self.audioEngine.start()
self.task = self.recognizer?.recognitionTask(with: self.request) { result, error in
if let result = result {
DispatchQueue.main.async {
self.transcribedText = result.bestTranscription.formattedString
}
}
}
}
}
func stopRecording() {
audioEngine.stop()
request.endAudio()
task?.cancel()
audioEngine.inputNode.removeTap(onBus: 0)
}
}
......@@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSSpeechRecognitionUsageDescription</key>
<string>Uses voice recognition</string>
<key>NSMicrophoneUsageDescription</key>
<string>Use a microphone</string>
<key>MBXAccessToken</key>
<string>pk.eyJ1Ijoiam1hcmluZWNsb3VkIiwiYSI6ImNsbmxjbGYzZjA0dG8yaW82MDgwajQ5OTQifQ.pd8YC9qK1C4YmMUbMx6ywQ</string>
<key>UIBackgroundModes</key>
......
......@@ -7,6 +7,11 @@
import Foundation
enum ChatMode: Int {
case normal = 0
case warningProgress = 1
}
struct ResGetMessages: Codable {
var mode: Int // 0:通常 , 1:Warning中
var messages: [ChatMessage]?
......
......@@ -110,7 +110,7 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
Preferences.DeviceId = UUID().uuidString
}
//SignalR初期化
//MARK: - SignalR初期化
hubConnectionDelegate = ChatHubConnectionDelegate(app: self)
connection = HubConnectionBuilder(url: URL(string : HttpRequestType.SignalR.rawValue)!)
.withHubConnectionDelegate(delegate: hubConnectionDelegate!)
......@@ -121,10 +121,16 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
.build()
if let r_connection = connection {
//Chat
r_connection.on(method: "ChatMessage", callback: { (message: ResChatMessage) in
self.handleChatMessage(message: message)
})
//Photo / Image
r_connection.on(method: "chatMessage", callback: { (message: ResChatMessage) in
self.handleChatMessage(message: message)
})
r_connection.on(method: "AckMessage", callback: { (message: ResAckMessage) in
self.handleAckMessage(message: message)
})
......@@ -158,6 +164,7 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
// Push通知を受信した時(サイレントプッシュ)
func notificationHub(_ notificationHub: MSNotificationHub, didReceivePushNotification notification: MSNotificationHubMessage) {
print(debug: "called")
// let title = notification.title ?? ""
// let body = notification.body ?? ""
let userInfo = notification.userInfo
......@@ -181,11 +188,13 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
}
private func handleChatMessage(message: ResChatMessage) {
print(debug: "called")
let ownMsg = ChatMessage(shipId: message.shipId, messageId: message.messageId, type: message.type, time: message.time, location: message.location, from: message.from, fromId: message.fromId, mode: message.mode, message: message.message, stampId: message.stampId, viewer: [])
self.msg.messages.append(ownMsg)
}
private func handleAckMessage(message: ResAckMessage) {
print(debug: "called")
let msgIndex = self.msg.messages.firstIndex(where: {$0.messageId == message.messageId})
if let index = msgIndex {
if let fromId = message.fromId {
......@@ -199,6 +208,7 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
}
private func handleChatMode(message: ResChatMode) {
print(debug: "called")
if message.mode == 1 {
self.msg.mode = true
} else {
......@@ -352,27 +362,39 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
//送信先名称が同一の場合は通知を出さない
if subtitle == Preferences.UserName {
return
} else {
DispatchQueue.main.async {
SharingData.message.viewCnt += 1
}
}
case "sailassist":
print(debug: "sailassist")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
DispatchQueue.main.async {
print(debug: "sailassist")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
}
case "bam":
print(debug: "bam")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
DispatchQueue.main.async {
print(debug: "bam")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
}
case "route":
print(debug: "route")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
DispatchQueue.main.async {
print(debug: "route")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
}
case "emergency":
print(debug: "emergency")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
DispatchQueue.main.async {
print(debug: "emergency")
SharingData.pushHistory.viewCnt += 1
let getPushHistory = GetPushHistory()
getPushHistory.start()
}
default:
print(debug: "default")
}
......
......@@ -14,4 +14,6 @@ enum APIError: Error{
case decodeError
case encodeError
case unknown
case invalidURL
case busy
}
......@@ -51,7 +51,7 @@ class ServerSession{
do{
if error != nil{
// print(debug: "clientError: \(error)")
print(debug: "clientError: \(String(describing: error))")
throw APIError.clientError
}
guard let indata = data, let inresponse = response as? HTTPURLResponse else {
......
......@@ -9,76 +9,107 @@ import Foundation
import SwiftUI
class SessionUploadImage : ObservableObject {
@Published var status = false
// シングルトン宣言
static let OnlyOne = SessionUploadImage()
@Published var progress: Double = 0.0
@Published var isUploading: Bool = false
static let OnlyOne = SessionUploadImage() // シングルトン宣言
private var serverSession = ServerSession()
private var Calling : Bool = false // 通信中
private var uploadTask: URLSessionUploadTask?
func cancelUpload() {
uploadTask?.cancel()
isUploading = false
progress = 0.0
}
/**
* メッセージ
*/
func RequestUploadImage(_ uploadImage : ReqUploadImage ,completion: @escaping ((Result<Data, APIError>)) -> Void) {
func requestUploadImage(_ uploadImage: ReqUploadImage) async throws -> Data {
print(debug: "calld")
if Calling {
return
guard !Calling else {
throw APIError.busy
}
Calling = true
defer { Calling = false }
// リクエストURLの組み立て
let url_string : String = HttpRequestType.UploadImage.rawValue
guard let req_url = URL(string : url_string) else {
Calling = false
return
guard let req_url = URL(string: HttpRequestType.UploadImage.rawValue) else {
throw APIError.invalidURL
}
let imageFileName = "itemp.jpg"
let boundary = "----------\(UUID().uuidString)"
var httpBody1 = "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"ShipId\"\r\n"
httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.shipId)\r\n"
httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"MessageId\"\r\n"
httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.messageId)\r\n"
httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"Location\"\r\n"
httpBody1 += "\r\n"
httpBody1 += "\(String(uploadImage.location))\r\n"
httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"From\"\r\n"
httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.from)\r\n"
httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"FromId\"\r\n"
httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.fromId)\r\n"
httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"files\"; filename=\"\(imageFileName)\"\r\n"
httpBody1 += "Content-Type: image/jpeg\r\n"
httpBody1 += "\r\n"
var httpBody = Data()
httpBody.append(httpBody1.data(using: .utf8)!)
func appendFormField(name: String, value: String) {
httpBody.append("--\(boundary)\r\n".data(using: .utf8)!)
httpBody.append("Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n".data(using: .utf8)!)
httpBody.append("\(value)\r\n".data(using: .utf8)!)
}
appendFormField(name: "ShipId", value: String(uploadImage.shipId))
appendFormField(name: "MessageId", value: uploadImage.messageId)
appendFormField(name: "Location", value: String(uploadImage.location))
appendFormField(name: "From", value: uploadImage.from)
appendFormField(name: "FromId", value: uploadImage.fromId)
httpBody.append("--\(boundary)\r\n".data(using: .utf8)!)
httpBody.append("Content-Disposition: form-data; name=\"files\"; filename=\"\(imageFileName)\"\r\n".data(using: .utf8)!)
httpBody.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
httpBody.append(uploadImage.files)
httpBody.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
var request = URLRequest(url: req_url)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let session = URLSession(configuration: .default, delegate: UploadProgressDelegate(parent: self), delegateQueue: nil)
isUploading = true
uploadTask = session.uploadTask(with: request, from: httpBody)
uploadTask?.resume()
let (data, response) = try await session.upload(for: request, from: httpBody)
isUploading = false
progress = 0.0
var httpBody2 = "\r\n"
httpBody2 += "--\(boundary)--\r\n"
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
throw APIError.serverError
}
return data
}
httpBody.append(httpBody2.data(using: .utf8)!)
// let str: String = String(decoding: httpBody, as: UTF8.self)
serverSession.postForm(boundary: boundary, req_url, httpBody, completion: completion)
func postFormAsync(boundary: String, url: URL, body: Data) async throws -> Data {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpBody = body
let (data, response) = try await URLSession.shared.data(for: request)
// if let postdata = serverSession.httpBody(boundary: boundary, uploadImage) {
// serverSession.postForm(boundary: boundary, req_url, postdata, completion: completion)
// }
// else {
// Calling = false
// return
// }
guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
throw APIError.serverError
}
return data
}
class UploadProgressDelegate: NSObject, URLSessionTaskDelegate {
weak var parent: SessionUploadImage?
init(parent: SessionUploadImage) {
self.parent = parent
}
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64,
totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
DispatchQueue.main.async {
self.parent?.progress = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
}
}
}
}
import SwiftUI
// MARK: - ChangeModeAlertModifier
struct ChangeModeAlertModifier: ViewModifier {
@Binding var isPresented: Bool
let currentMode: Bool
let onConfirm: () -> Void
func body(content: Content) -> some View {
content.alert("", isPresented: $isPresented) {
Button("Yes") {
onConfirm()
}
Button("No") {}
} message: {
Text("Do you change an warning mode?")
}
}
}
// MARK: - LocationAlertModifier
struct LocationAlertModifier: ViewModifier {
@Binding var isPresented: Bool
func body(content: Content) -> some View {
content.alert("Location", isPresented: $isPresented) {
Button("Cancel") {}
Button("Setting") {
guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else {
return
}
UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
}
} message: {
Text("To use ECA, set the permission to use location information to ALWAYS.")
}
}
}
// MARK: - UpdateAlertModifier
struct UpdateAlertModifier: ViewModifier {
@Binding var isPresented: Bool
let appStoreURL: URL
func body(content: Content) -> some View {
content.alert("Update", isPresented: $isPresented) {
Button("Go to app page") {
UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil)
}
} message: {
Text("A new version of this app is available.")
}
}
}
// MARK: - WarningModeAlertModifier
struct WarningModeAlertModifier: ViewModifier {
@Binding var isPresented: Bool
@Binding var isSignalrRestert: Bool
let onConfirm: () -> Void
func body(content: Content) -> some View {
content.alert("Error", isPresented: $isPresented) {
Button("OK") {
onConfirm()
isSignalrRestert = false
}
} message: {
Text("The mode did not change.")
}
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment