Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
Sailassist
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
54
Merge Requests
54
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gr-ssv
Sailassist
Commits
5e4e2e3c
Commit
5e4e2e3c
authored
Apr 21, 2024
by
shigemi miura
Browse files
Options
Browse Files
Download
Plain Diff
Merge trial-chat2 into develop
parents
0b014901
9aeb57c1
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
537 additions
and
188 deletions
+537
-188
project.pbxproj
Seilassist/Sailassist.xcodeproj/project.pbxproj
+0
-0
ChatView.swift
Seilassist/Sailassist/Chat/ChatView.swift
+31
-4
GetMessage.swift
Seilassist/Sailassist/Chat/GetMessage.swift
+12
-7
Imagepicker.swift
Seilassist/Sailassist/Chat/Imagepicker.swift
+50
-0
CameraView.swift
Seilassist/Sailassist/Chat/View/CameraView.swift
+27
-0
ChatInputView.swift
Seilassist/Sailassist/Chat/View/ChatInputView.swift
+97
-1
ChatMemberView.swift
Seilassist/Sailassist/Chat/View/ChatMemberView.swift
+4
-3
ChatTitleView.swift
Seilassist/Sailassist/Chat/View/ChatTitleView.swift
+9
-5
MyChatContentView.swift
Seilassist/Sailassist/Chat/View/MyChatContentView.swift
+48
-1
OtherChatContentView.swift
Seilassist/Sailassist/Chat/View/OtherChatContentView.swift
+55
-0
ReqUploadImage.swift
Seilassist/Sailassist/Json/ReqUploadImage.swift
+18
-0
ResAckMessage.swift
Seilassist/Sailassist/Json/ResAckMessage.swift
+16
-0
ResChatMessage.swift
Seilassist/Sailassist/Json/ResChatMessage.swift
+20
-0
ResChatMode.swift
Seilassist/Sailassist/Json/ResChatMode.swift
+16
-0
ResGetMessages.swift
Seilassist/Sailassist/Json/ResGetMessages.swift
+10
-2
MapRepresentable.swift
Seilassist/Sailassist/Map/MapRepresentable.swift
+4
-0
GetManualUrl.swift
Seilassist/Sailassist/Menu/GetManualUrl.swift
+0
-1
MenuView.swift
Seilassist/Sailassist/Menu/MenuView.swift
+3
-1
SailassistApp.swift
Seilassist/Sailassist/SailassistApp.swift
+0
-0
ServerSession.swift
Seilassist/Sailassist/ServerSession/ServerSession.swift
+84
-0
SessionUploadImage.swift
Seilassist/Sailassist/ServerSession/SessionUploadImage.swift
+15
-14
SharingData.swift
Seilassist/Sailassist/SharingData/SharingData.swift
+6
-1
SignalRService.swift
Seilassist/Sailassist/SignalR/SignalRService.swift
+0
-142
MainTabView.swift
Seilassist/Sailassist/Tab/MainTabView.swift
+12
-6
No files found.
Seilassist/Sailassist.xcodeproj/project.pbxproj
View file @
5e4e2e3c
This diff is collapsed.
Click to expand it.
Seilassist/Sailassist/Chat/ChatView.swift
View file @
5e4e2e3c
...
...
@@ -11,9 +11,10 @@ struct ChatView: View {
@EnvironmentObject
private
var
selectedTabModel
:
SelectedTabModel
@ObservedObject
var
message
=
SharingData
.
message
@State
var
isShowMember
:
Bool
=
false
var
body
:
some
View
{
ZStack
{
if
message
.
mode
==
1
{
if
message
.
mode
==
true
{
LinearGradient
(
gradient
:
Gradient
(
colors
:
[
.
chatEmargencyColor1
,
.
chatEmargencyColor2
]),
startPoint
:
.
top
,
endPoint
:
.
bottom
)
.
ignoresSafeArea
()
}
...
...
@@ -21,12 +22,14 @@ struct ChatView: View {
ChatTitleView
(
isShowMember
:
$
isShowMember
)
ZStack
{
ScrollViewReader
{
proxy
in
ScrollView
(
.
vertical
)
{
VStack
{
Spacer
()
.
frame
(
height
:
20
)
ForEach
(
message
.
messages
,
id
:
\
.
messageId
)
{
msg
in
if
msg
.
fromId
!=
String
(
SharingData
.
my
.
id
)
{
if
msg
.
from
==
Preferences
.
UserName
{
//自分のメッセージ
MyChatContentView
(
message
:
msg
)
.
padding
(
.
bottom
,
24
)
...
...
@@ -37,6 +40,31 @@ struct ChatView: View {
}
}
}
.
onAppear
{
if
let
id
=
message
.
messages
.
last
?
.
messageId
{
print
(
debug
:
"ChatView:onAppear"
)
proxy
.
scrollTo
(
id
,
anchor
:
.
center
)
}
}
.
onChange
(
of
:
message
.
messages
.
count
)
{
newValue
in
if
let
id
=
message
.
messages
.
last
?
.
messageId
{
withAnimation
{
print
(
debug
:
"ChatView:onChange"
)
proxy
.
scrollTo
(
id
,
anchor
:
.
center
)
}
}
}
.
onReceive
(
message
.
$
messages
)
{
(
value
)
in
withAnimation
{
guard
!
value
.
isEmpty
else
{
return
}
if
let
id
=
message
.
messages
.
last
?
.
messageId
{
print
(
debug
:
"ChatView:onReceive"
)
proxy
.
scrollTo
(
id
,
anchor
:
.
center
)
}
}
}
}
}
HStack
{
Spacer
()
VStack
{
...
...
@@ -56,10 +84,9 @@ struct ChatView: View {
ChatMemberView
()
}
}
}
ChatInputView
()
}
}
.
background
(
ColorSet
.
BackgroundPrimary
.
color
)
}
}
...
...
Seilassist/Sailassist/Chat/GetMessage.swift
View file @
5e4e2e3c
...
...
@@ -12,26 +12,31 @@ class GetMessage {
func
start
()
{
print
(
debug
:
"called"
)
sessionGetMessage
.
RequestGetMessage
(
responseGetMessage
)
}
private
func
responseGetMessage
(
result
:
Result
<
Data
,
APIError
>
)
{
print
(
debug
:
"called"
)
switch
result
{
sessionGetMessage
.
RequestGetMessage
{
response
in
switch
response
{
case
.
success
(
let
resultData
):
let
serverSession
=
ServerSession
()
let
resjson
=
serverSession
.
fromJSON
(
resultData
:
resultData
,
resltType
:
ResGetMessages
.
self
)
if
let
res
=
resjson
{
SharingData
.
message
.
mode
=
res
.
mode
if
res
.
mode
==
1
{
SharingData
.
message
.
mode
=
true
}
else
{
SharingData
.
message
.
mode
=
false
}
SharingData
.
message
.
messages
=
[]
if
let
msg
=
res
.
messages
{
SharingData
.
message
.
messages
=
msg
}
SharingData
.
message
.
users
=
[]
if
let
users
=
res
.
users
{
SharingData
.
message
.
users
=
users
}
}
case
.
failure
(
let
errorCode
):
print
(
debug
:
errorCode
)
break
}
}
}
}
Seilassist/Sailassist/Chat/Imagepicker.swift
0 → 100644
View file @
5e4e2e3c
//
// Imagepicker.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/01/19.
//
import
SwiftUI
struct
Imagepicker
:
UIViewControllerRepresentable
{
@Binding
var
show
:
Bool
@Binding
var
image
:
Data
var
sourceType
:
UIImagePickerController
.
SourceType
func
makeCoordinator
()
->
Imagepicker
.
Coodinator
{
return
Imagepicker
.
Coordinator
(
parent
:
self
)
}
func
makeUIViewController
(
context
:
UIViewControllerRepresentableContext
<
Imagepicker
>
)
->
UIImagePickerController
{
let
controller
=
UIImagePickerController
()
controller
.
sourceType
=
sourceType
controller
.
delegate
=
context
.
coordinator
return
controller
}
func
updateUIViewController
(
_
uiViewController
:
UIImagePickerController
,
context
:
UIViewControllerRepresentableContext
<
Imagepicker
>
)
{
}
class
Coodinator
:
NSObject
,
UIImagePickerControllerDelegate
,
UINavigationControllerDelegate
{
var
parent
:
Imagepicker
init
(
parent
:
Imagepicker
){
self
.
parent
=
parent
}
//Cancel
func
imagePickerControllerDidCancel
(
_
picker
:
UIImagePickerController
)
{
self
.
parent
.
show
.
toggle
()
}
//Use Photo
func
imagePickerController
(
_
picker
:
UIImagePickerController
,
didFinishPickingMediaWithInfo
info
:
[
UIImagePickerController
.
InfoKey
:
Any
])
{
let
image
=
info
[
.
originalImage
]
as!
UIImage
let
data
=
image
.
pngData
()
self
.
parent
.
image
=
data
!
self
.
parent
.
show
.
toggle
()
}
}
}
Seilassist/Sailassist/Chat/View/CameraView.swift
0 → 100644
View file @
5e4e2e3c
//
// CameraView.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/01/19.
//
import
SwiftUI
struct
CameraView
:
View
{
@Binding
var
imageData
:
Data
@Binding
var
source
:
UIImagePickerController
.
SourceType
@Binding
var
isActionSheet
:
Bool
@Binding
var
isImagePicker
:
Bool
var
body
:
some
View
{
NavigationStack
{
List
{
}
.
navigationDestination
(
isPresented
:
$
isImagePicker
)
{
Imagepicker
(
show
:
$
isImagePicker
,
image
:
$
imageData
,
sourceType
:
source
)
}
}
.
ignoresSafeArea
(
.
all
,
edges
:
.
top
)
.
background
(
Color
.
primary
.
opacity
(
0.06
)
.
ignoresSafeArea
(
.
all
,
edges
:
.
all
))
}
}
Seilassist/Sailassist/Chat/View/ChatInputView.swift
View file @
5e4e2e3c
...
...
@@ -9,14 +9,69 @@ import SwiftUI
struct
ChatInputView
:
View
{
@EnvironmentObject
private
var
sceneDelegate
:
SceneDelegate
@ObservedObject
var
sessionUploadImage
:
SessionUploadImage
=
SessionUploadImage
()
@State
var
inputText
=
""
@State
private
var
selectionValue
=
3
@State
var
isCamera
:
Bool
=
false
@State
var
isPhoto
:
Bool
=
false
@State
var
isImportFile
:
Bool
=
false
@State
var
imageData
:
Data
=
.
init
(
capacity
:
0
)
@State
var
source
:
UIImagePickerController
.
SourceType
=
.
photoLibrary
@State
var
isActionSheet
=
false
@State
var
isImagePicker
=
false
@FocusState
var
isKeyboard
:
Bool
var
body
:
some
View
{
VStack
(
spacing
:
0
){
Spacer
()
Divider
()
HStack
(
spacing
:
10
){
Button
{
sceneDelegate
.
tabWindow
?
.
isHidden
=
true
isCamera
=
true
source
=
.
camera
isImagePicker
.
toggle
()
}
label
:
{
Image
(
systemName
:
"camera"
)
.
resizable
()
.
frame
(
width
:
24
,
height
:
24
)
.
padding
(
10
)
}
Menu
{
Button
(
action
:
{
print
(
"Photo Library"
)
sceneDelegate
.
tabWindow
?
.
isHidden
=
true
isCamera
=
true
source
=
.
photoLibrary
isImagePicker
.
toggle
()
})
{
Label
(
"Photo Library"
,
systemImage
:
"photo.on.rectangle"
)
}
Button
(
action
:
{
print
(
"Take Photo"
)
sceneDelegate
.
tabWindow
?
.
isHidden
=
true
isImportFile
=
true
})
{
Label
(
"Take Phot"
,
systemImage
:
"camera"
)
}
Button
(
action
:
{
print
(
"Choose File"
)
sceneDelegate
.
tabWindow
?
.
isHidden
=
true
isCamera
=
true
source
=
.
photoLibrary
isImagePicker
.
toggle
()
})
{
Label
(
"Choose File"
,
systemImage
:
"folder"
)
}
}
label
:
{
Image
(
systemName
:
"photo"
)
.
resizable
()
.
frame
(
width
:
24
,
height
:
24
)
.
padding
(
10
)
}
TextField
(
""
,
text
:
$
inputText
,
onEditingChanged
:
{
isEdit
in
sceneDelegate
.
tabWindow
?
.
isHidden
=
isEdit
})
...
...
@@ -31,7 +86,9 @@ struct ChatInputView: View {
Button
{
isKeyboard
=
false
let
signalRService
=
SignalR
()
signalRService
.
chatMessage
(
message
:
inputText
)
inputText
=
""
}
label
:
{
Image
(
"send"
)
.
resizable
()
...
...
@@ -42,8 +99,47 @@ struct ChatInputView: View {
.
padding
(
.
trailing
,
11
)
}
.
background
(
ColorSet
.
BackgroundSecondary
.
color
)
.
fullScreenCover
(
isPresented
:
.
constant
(
isImagePicker
),
onDismiss
:
{
//シートを閉じる時に実行する処理
sceneDelegate
.
tabWindow
?
.
isHidden
=
false
if
imageData
.
count
!=
0
{
let
jpegData
=
UIImage
(
data
:
imageData
)
!.
jpegData
(
compressionQuality
:
1.0
)
let
uploadImage
=
ReqUploadImage
(
shipId
:
Preferences
.
shipId
,
messageId
:
UUID
()
.
uuidString
,
location
:
2
,
from
:
Preferences
.
UserName
,
fromId
:
String
(
SharingData
.
my
.
id
),
files
:
jpegData
!
)
sessionUploadImage
.
RequestUploadImage
(
uploadImage
,
completion
:
responseUploadImage
)
}
},
content
:
{
CameraView
(
imageData
:
$
imageData
,
source
:
$
source
,
isActionSheet
:
$
isActionSheet
,
isImagePicker
:
$
isImagePicker
)
})
.
fileImporter
(
isPresented
:
$
isImportFile
,
allowedContentTypes
:
[
.
png
,
.
jpeg
,
.
pdf
])
{
result
in
switch
result
{
case
.
success
(
let
url
):
guard
let
imageData
=
try
?
Data
(
contentsOf
:
url
)
else
{
return
}
if
imageData
.
count
!=
0
{
let
jpegData
=
UIImage
(
data
:
imageData
)
!.
jpegData
(
compressionQuality
:
1.0
)
let
uploadImage
=
ReqUploadImage
(
shipId
:
Preferences
.
shipId
,
messageId
:
UUID
()
.
uuidString
,
location
:
2
,
from
:
Preferences
.
UserName
,
fromId
:
String
(
SharingData
.
my
.
id
),
files
:
jpegData
!
)
sessionUploadImage
.
RequestUploadImage
(
uploadImage
,
completion
:
responseUploadImage
)
}
case
.
failure
:
print
(
"failure"
)
}
}
}
.
frame
(
maxHeight
:
55
)
}
func
responseUploadImage
(
result
:
Result
<
Data
,
APIError
>
)
{
print
(
debug
:
"calld"
)
switch
result
{
case
.
success
(
let
resultData
):
let
serverSession
=
ServerSession
()
let
resjson
=
serverSession
.
fromJSON
(
resultData
:
resultData
,
resltType
:
ResLogin
.
self
)
case
.
failure
(
let
errorCode
):
print
(
debug
:
errorCode
)
break
}
}
}
...
...
Seilassist/Sailassist/Chat/View/ChatMemberView.swift
View file @
5e4e2e3c
...
...
@@ -8,12 +8,13 @@
import
SwiftUI
struct
ChatMemberView
:
View
{
var
members
=
[
"Yokoyama"
,
"Nogami"
,
"Arahira"
,
"Enokido"
]
@ObservedObject
var
message
=
SharingData
.
message
// var members = ["Yokoyama", "Nogami", "Arahira", "Enokido"]
var
body
:
some
View
{
VStack
{
List
{
ForEach
(
me
mbers
,
id
:
\
.
self
)
{
memb
er
in
Text
(
member
)
ForEach
(
me
ssage
.
users
,
id
:
\
.
id
)
{
us
er
in
Text
(
user
.
name
)
.
foregroundColor
(
ColorSet
.
BodyChat
.
color
)
.
font
(
FontStyle
.
SupplementText
.
font
)
}
...
...
Seilassist/Sailassist/Chat/View/ChatTitleView.swift
View file @
5e4e2e3c
...
...
@@ -9,10 +9,10 @@ import SwiftUI
struct
ChatTitleView
:
View
{
@Binding
var
isShowMember
:
Bool
var
body
:
some
View
{
@ObservedObject
var
message
=
SharingData
.
message
var
body
:
some
View
{
VStack
{
HStack
{
Button
{
...
...
@@ -25,11 +25,15 @@ struct ChatTitleView: View {
Spacer
()
HStack
(
spacing
:
8
)
{
VStack
{
Text
(
"JMB-Demo(0518)"
)
Text
(
SharingData
.
my
.
shipName
)
.
font
(
FontStyle
.
TitleL
.
font
)
Text
(
"Yokoyama,Nogami,Arahira,Enokida"
)
.
font
(
FontStyle
.
TitleSBold
.
font
)
HStack
{
ForEach
(
message
.
users
,
id
:
\
.
id
)
{
user
in
Text
(
user
.
name
+
","
)
.
font
(
FontStyle
.
TitleS
.
font
)
}
}
}
.
foregroundColor
(
ColorSet
.
Body
.
color
)
.
frame
(
width
:
162
,
height
:
44
)
...
...
Seilassist/Sailassist/Chat/View/MyChatContentView.swift
View file @
5e4e2e3c
...
...
@@ -13,12 +13,59 @@ struct MyChatContentView: View {
HStack
{
Spacer
()
VStack
(
alignment
:
.
trailing
,
spacing
:
6
)
{
Group
{
if
message
.
message
.
contains
(
"https://"
)
{
//TODO: stampIdが0
AsyncImage
(
url
:
URL
(
string
:
message
.
message
))
{
image
in
image
.
resizable
()
.
frame
(
width
:
200
,
height
:
200
)
.
contextMenu
{
Button
(
action
:
{
print
(
"fight"
)
})
{
Text
(
"Share..."
)
Image
(
systemName
:
"square.and.arrow.up"
)
}
Button
(
action
:
{
print
(
"bag"
)
})
{
Text
(
"Save to Photos"
)
Image
(
systemName
:
"square.and.arrow.down"
)
}
Button
(
action
:
{
print
(
"pokemon"
)
})
{
Text
(
"Copy"
)
Image
(
systemName
:
"doc.on.doc"
)
}
Button
(
action
:
{
print
(
"run"
)
})
{
Text
(
"Copy Subject"
)
Image
(
systemName
:
"circle.dashed.rectangle"
)
}
Button
(
action
:
{
print
(
"run"
)
})
{
Text
(
"Show Text"
)
Image
(
systemName
:
"text.viewfinder"
)
}
}
}
placeholder
:
{
ProgressView
()
}
}
else
{
Text
(
message
.
message
)
.
font
(
FontStyle
.
DefaultText
.
font
)
.
foregroundColor
(
ColorSet
.
BodyChat
.
color
)
.
padding
(
15
)
.
background
(
ColorSet
.
ChatBaloon
.
color
)
.
cornerRadius
(
10
,
corners
:
[
.
tl
,
.
tr
,
.
bl
])
.
cornerRadius
(
10
,
corners
:
[
.
tl
,
.
tr
,
.
br
])
}
}
HStack
(
spacing
:
0
){
Text
(
DateTextLib
.
ISO86012FormatText
(
message
.
time
,
format
:
"yyyy/MM/dd hh:mm"
,
errFormat
:
""
))
...
...
Seilassist/Sailassist/Chat/View/OtherChatContentView.swift
View file @
5e4e2e3c
...
...
@@ -16,12 +16,59 @@ struct OtherChatContentView: View {
.
font
(
FontStyle
.
EmphasisText
.
font
)
.
foregroundColor
(
ColorSet
.
Body
.
color
)
VStack
(
alignment
:
.
leading
,
spacing
:
10
)
{
Group
{
if
message
.
message
.
contains
(
"https://"
)
{
//TODO: stampIdが0
AsyncImage
(
url
:
URL
(
string
:
message
.
message
))
{
image
in
image
.
resizable
()
.
frame
(
width
:
200
,
height
:
200
)
.
contextMenu
{
Button
(
action
:
{
print
(
"fight"
)
})
{
Text
(
"Share..."
)
Image
(
systemName
:
"square.and.arrow.up"
)
}
Button
(
action
:
{
print
(
"bag"
)
})
{
Text
(
"Save to Photos"
)
Image
(
systemName
:
"square.and.arrow.down"
)
}
Button
(
action
:
{
print
(
"pokemon"
)
})
{
Text
(
"Copy"
)
Image
(
systemName
:
"doc.on.doc"
)
}
Button
(
action
:
{
print
(
"run"
)
})
{
Text
(
"Copy Subject"
)
Image
(
systemName
:
"circle.dashed.rectangle"
)
}
Button
(
action
:
{
print
(
"run"
)
})
{
Text
(
"Show Text"
)
Image
(
systemName
:
"text.viewfinder"
)
}
}
}
placeholder
:
{
ProgressView
()
}
}
else
{
Text
(
message
.
message
)
.
font
(
FontStyle
.
DefaultText
.
font
)
.
foregroundColor
(
ColorSet
.
BodyChat
.
color
)
.
padding
(
15
)
.
background
(
ColorSet
.
ChatBaloon
.
color
)
.
cornerRadius
(
10
,
corners
:
[
.
tl
,
.
tr
,
.
br
])
}
}
HStack
(
alignment
:
.
top
){
Text
(
DateTextLib
.
ISO86012FormatText
(
message
.
time
,
format
:
"yyyy/MM/dd hh:mm"
,
errFormat
:
""
))
...
...
@@ -30,6 +77,14 @@ struct OtherChatContentView: View {
}
}
}
.
onAppear
{
//既読確認
let
result
=
message
.
viewer
.
first
(
where
:
{
$0
.
id
==
String
(
SharingData
.
my
.
id
)})
if
result
==
nil
{
let
signalRService
=
SignalR
()
signalRService
.
ackMessage
(
messageId
:
message
.
messageId
)
}
}
.
padding
(
.
leading
,
20
)
Spacer
()
}
...
...
Seilassist/Sailassist/Json/ReqUploadImage.swift
0 → 100644
View file @
5e4e2e3c
//
// ReqUploadImage.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/01/29.
//
import
Foundation
struct
ReqUploadImage
:
Codable
{
var
shipId
:
Int
var
messageId
:
String
//UUID
var
location
:
Int
//1:Shore、2:Ship
var
from
:
String
//投稿者名
var
fromId
:
String
//ユーザーID
var
files
:
Data
}
Seilassist/Sailassist/Json/ResAckMessage.swift
0 → 100644
View file @
5e4e2e3c
//
// ResAckMessage.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/01/05.
//
import
Foundation
struct
ResAckMessage
:
Codable
{
var
shipId
:
Int
var
messageId
:
String
//UUID
var
time
:
String
//投稿日時
var
location
:
Int
//1:Shore、2:Ship
var
fromId
:
String
//ユーザーID
}
Seilassist/Sailassist/Json/ResChatMessage.swift
0 → 100644
View file @
5e4e2e3c
//
// ResChatMessage.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/01/05.
//
import
Foundation
struct
ResChatMessage
:
Codable
{
var
shipId
:
Int
var
messageId
:
String
//UUID
var
type
:
Int
//0:テキスト、1:スタンプ
var
time
:
String
//投稿日時
var
location
:
Int
//1:Shore、2:Ship
var
from
:
String
//投稿者名
var
fromId
:
String
//ユーザーID
var
message
:
String
//テキスト
var
stampId
:
Int
//スタンプ番号
}
Seilassist/Sailassist/Json/ResChatMode.swift
0 → 100644
View file @
5e4e2e3c
//
// ResChatMode.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/01/05.
//
import
Foundation
struct
ResChatMode
:
Codable
{
var
shipId
:
Int
var
time
:
String
//投稿日時
var
location
:
Int
//1:Shore、2:Ship
var
fromId
:
String
//ユーザーID
var
mode
:
Int
//0:通常、1:Warning中
}
Seilassist/Sailassist/Json/ResGetMessages.swift
View file @
5e4e2e3c
...
...
@@ -10,16 +10,17 @@ import Foundation
struct
ResGetMessages
:
Codable
{
var
mode
:
Int
// 0:通常 , 1:Warning中
var
messages
:
[
ChatMessage
]?
var
users
:
[
ChatUser
]?
}
struct
ChatMessage
:
Codable
{
var
shipId
:
U
Int
var
shipId
:
Int
var
messageId
:
String
//各メッセージ固有ID
var
type
:
Int
//0:テキスト , 1:スタンプ , 2:画像
var
time
:
String
//投稿日時
var
location
:
Int
//1:Shore , 2:Ship
var
from
:
String
//投稿者名
var
fromId
:
String
//ユーザーID
var
fromId
:
String
?
//ユーザーID
var
message
:
String
//テキスト時:テキスト , 画像時:サムネイルのUri
var
stampId
:
Int
//スタンプ番号 0:Fire~
var
viewer
:
[
Viewer
]
//閲覧者情報
...
...
@@ -30,3 +31,10 @@ struct Viewer: Codable {
var
location
:
Int
//1:Shore , 2:Ship
var
id
:
String
//ユーザーID
}
struct
ChatUser
:
Codable
{
var
time
:
String
//最終アクセス日時
var
location
:
Int
//1:Shore , 2:Ship
var
id
:
String
//ログイン時のデバイスID
var
name
:
String
//ユーザー名
}
Seilassist/Sailassist/Map/MapRepresentable.swift
View file @
5e4e2e3c
...
...
@@ -17,10 +17,12 @@ struct MapRepresentable: UIViewControllerRepresentable{
@ObservedObject
var
pushHistory
=
SharingData
.
pushHistory
@State
var
mapVC
=
MapViewController
()
//作成したいViewControllerを返すメソッド
func
makeUIViewController
(
context
:
Context
)
->
some
UIViewController
{
mapVC
}
//Viewが更新された場合に必要な処理を実装
func
updateUIViewController
(
_
uiViewController
:
UIViewControllerType
,
context
:
Context
)
{
let
ecaArea
=
ecaData
.
ecaArea
.
map
{
$0
.
1
}
.
filter
{
$0
.
isRunning
}
.
first
if
let
ecaArea
=
ecaArea
{
...
...
@@ -29,6 +31,7 @@ struct MapRepresentable: UIViewControllerRepresentable{
mapVC
.
removeEcaLine
()
}
//ECA領域を画面中央に表示
if
let
focusEcaAreaId
=
ecaData
.
focusEca
,
let
focusEca
=
ecaData
.
ecaArea
[
focusEcaAreaId
]{
mapVC
.
updateCamera
(
location
:
focusEca
.
centerPosition
,
zoomlevel
:
focusEca
.
zoomLevel
)
mapVC
.
updateOneTimeEca
(
eca
:
focusEca
.
points
)
...
...
@@ -38,6 +41,7 @@ struct MapRepresentable: UIViewControllerRepresentable{
}
}
//通知場所を画面中央に表示
if
let
focusPushHistoryId
=
pushHistory
.
focusPushHistory
,
let
focusPushHistory
=
pushHistory
.
pushHistoryData
[
focusPushHistoryId
]{
if
let
position
=
focusPushHistory
.
position
{
if
let
latitude
=
position
.
lat
,
let
longitude
=
position
.
lon
{
...
...
Seilassist/Sailassist/Menu/GetManualUrl.swift
View file @
5e4e2e3c
...
...
@@ -13,7 +13,6 @@ class GetManualUrl {
func
start
()
{
print
(
debug
:
"called"
)
sessionGetManualUrl
.
getManualUrl
{
response
in
print
(
debug
:
"called"
)
switch
response
{
case
.
success
(
let
resultData
):
print
(
debug
:
String
(
data
:
resultData
,
encoding
:
.
utf8
)
as
Any
)
...
...
Seilassist/Sailassist/Menu/MenuView.swift
View file @
5e4e2e3c
...
...
@@ -221,7 +221,7 @@ struct MenuView: View {
loginViewModel
.
isLogin
=
false
sceneDelegate
.
tabWindow
?
.
isHidden
=
true
SharingData
.
message
.
mode
=
0
SharingData
.
message
.
mode
=
false
SharingData
.
message
.
messages
=
[]
SharingData
.
pushHistory
.
focusPushHistory
=
nil
...
...
@@ -231,6 +231,8 @@ struct MenuView: View {
SharingData
.
map
.
legLine
=
[]
SharingData
.
map
.
portLine
=
[]
SharingData
.
map
.
starboardLine
=
[]
connection
!.
stop
()
}
Button
(
"No"
)
{}
}
message
:
{
Text
(
"Are you sure?"
)
}
...
...
Seilassist/Sailassist/SailassistApp.swift
View file @
5e4e2e3c
This diff is collapsed.
Click to expand it.
Seilassist/Sailassist/ServerSession/ServerSession.swift
View file @
5e4e2e3c
...
...
@@ -79,6 +79,50 @@ class ServerSession{
})
.
resume
()
}
func
postForm
(
boundary
:
String
,
_
req_url
:
URL
,
_
postdata
:
Data
,
completion
:
@escaping
(
SessionResponse
)
->
Void
){
var
req
=
URLRequest
(
url
:
req_url
)
req
.
httpMethod
=
"POST"
req
.
setValue
(
"multipart/form-data; boundary=
\(
boundary
)
"
,
forHTTPHeaderField
:
"Content-Type"
)
req
.
setValue
(
"
\(
postdata
.
count
)
"
,
forHTTPHeaderField
:
"Content-Length"
)
req
.
httpBody
=
postdata
req
.
timeoutInterval
=
20
// タイムアウト3秒 → Amedasでタイムアウトエラー20秒に変更
// サーバー送信
let
session
=
URLSession
(
configuration
:
.
default
,
delegate
:
nil
,
delegateQueue
:
OperationQueue
.
main
)
session
.
dataTask
(
with
:
req
,
completionHandler
:
{(
data
,
response
,
error
)
in
session
.
finishTasksAndInvalidate
()
do
{
if
error
!=
nil
{
throw
APIError
.
clientError
}
guard
let
indata
=
data
,
let
inresponse
=
response
as?
HTTPURLResponse
else
{
throw
APIError
.
responseError
}
if
inresponse
.
statusCode
!=
200
{
throw
APIError
.
serverError
}
//Cookieを保存
if
let
fields
=
inresponse
.
allHeaderFields
as?
[
String
:
String
],
let
url
=
inresponse
.
url
{
for
cookie
in
HTTPCookie
.
cookies
(
withResponseHeaderFields
:
fields
,
for
:
url
)
{
HTTPCookieStorage
.
shared
.
setCookie
(
cookie
)
}
}
DispatchQueue
.
main
.
async
{
completion
(
.
success
(
indata
))
}
}
catch
{
if
error
as?
APIError
!=
nil
{
completion
(
.
failure
(
error
as!
APIError
))
}
else
{
completion
(
.
failure
(
.
unknown
))
}
}
})
.
resume
()
}
func
getJson
(
_
req_url
:
URL
,
completion
:
@escaping
(
SessionResponse
)
->
Void
){
var
req
=
URLRequest
(
url
:
req_url
)
...
...
@@ -164,4 +208,44 @@ class ServerSession{
}
return
false
}
func
httpBody
(
boundary
:
String
,
_
uploadImage
:
ReqUploadImage
)
->
Data
!
{
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
+=
"
\(
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=\"\(uploadImage.files)\"\r\n"
httpBody1
+=
"Content-Type: image/jpeg
\r\n
"
httpBody1
+=
"
\r\n
"
// var tmp = httpBody1.data(using: .utf8)!
var
httpBody
=
Data
()
httpBody
.
append
(
httpBody1
.
data
(
using
:
.
utf8
)
!
)
httpBody
.
append
(
uploadImage
.
files
)
var
httpBody2
=
"
\r\n
"
httpBody2
+=
"--
\(
boundary
)
--
\r\n
"
httpBody
.
append
(
httpBody2
.
data
(
using
:
.
utf8
)
!
)
return
httpBody
}
}
Seilassist/Sailassist/ServerSession/SessionUploadImage.swift
View file @
5e4e2e3c
...
...
@@ -19,7 +19,7 @@ class SessionUploadImage : ObservableObject {
/**
* メッセージ
*/
func
Request
GetUploadImage
(
_
completion
:
@escaping
((
Result
<
Data
,
APIError
>
))
->
Void
)
{
func
Request
UploadImage
(
_
uploadImage
:
ReqUploadImage
,
completion
:
@escaping
((
Result
<
Data
,
APIError
>
))
->
Void
)
{
print
(
debug
:
"calld"
)
if
Calling
{
return
...
...
@@ -27,19 +27,20 @@ class SessionUploadImage : ObservableObject {
Calling
=
true
// リクエストURLの組み立て
// リクエストURLの組み立て
// let url_string : String = HttpRequestType.UploadImage.rawValue
// guard let req_url = URL(string : url_string) else {
// Calling = false
// return
// }
let
url_string
:
String
=
HttpRequestType
.
UploadImage
.
rawValue
guard
let
req_url
=
URL
(
string
:
url_string
)
else
{
Calling
=
false
return
}
// if let postdata = serverSession.toJSON(login) {
// serverSession.postJson(req_url, postdata, completion: completion)
// }
// else {
// Calling = false
// return
// }
// let boundary = "----------" + UUID().uuidString
let
boundary
=
"----WebKitFormBoundaryZLdHZy8HNaBmUX0d"
if
let
postdata
=
serverSession
.
httpBody
(
boundary
:
boundary
,
uploadImage
)
{
serverSession
.
postForm
(
boundary
:
boundary
,
req_url
,
postdata
,
completion
:
completion
)
}
else
{
Calling
=
false
return
}
}
}
Seilassist/Sailassist/SharingData/SharingData.swift
View file @
5e4e2e3c
...
...
@@ -116,8 +116,13 @@ class SharingData{
static
var
message
=
Message
()
class
Message
:
ObservableObject
{
@Published
var
mode
:
Int
=
0
// 0:通常 , 1
:Warning中
@Published
var
mode
:
Bool
=
false
// false:通常 , true
:Warning中
@Published
var
messages
:
[
ChatMessage
]
=
[]
@Published
var
users
:
[
ChatUser
]
=
[]
func
changeMode
(){
self
.
mode
.
toggle
()
}
}
static
var
information
=
Information
()
...
...
Seilassist/Sailassist/SignalR/SignalRService.swift
deleted
100644 → 0
View file @
0b014901
//
// SignalRService.swift
// Sailassist
//
// Created by 三浦薫巳 on 2023/11/17.
//
import
Foundation
import
SwiftSignalRClient
public
class
SignalRService
{
private
var
connection
:
HubConnection
private
var
hubConnectionDelegate
:
HubConnectionDelegate
?
public
init
()
{
// hubConnectionDelegate = ChatHubConnectionDelegate(app: self)
hubConnectionDelegate
=
ChatHubConnectionDelegate
()
connection
=
HubConnectionBuilder
(
url
:
URL
(
string
:
HttpRequestType
.
SignalR
.
rawValue
)
!
)
.
withHubConnectionDelegate
(
delegate
:
hubConnectionDelegate
!
)
.
withAutoReconnect
()
.
withLogging
(
minLogLevel
:
.
error
)
.
build
()
connection
.
on
(
method
:
"chatMessage"
,
callback
:
{
(
shipId
:
Int
,
messageId
:
Int
,
type
:
Int
,
time
:
String
,
location
:
Int
,
from
:
String
,
fromeId
:
Int
,
message
:
String
)
in
self
.
handleChatMessage
(
message
,
from
:
from
)
})
connection
.
on
(
method
:
"ackMessage"
,
callback
:
{
(
shipId
:
Int
,
time
:
String
,
location
:
Int
,
fromId
:
Int
,
mode
:
Int
)
in
self
.
handleAckMessage
(
time
)
})
connection
.
on
(
method
:
"chatMode"
,
callback
:
{
(
shipId
:
Int
,
time
:
String
,
location
:
Int
,
fromId
:
String
,
mode
:
Int
)
in
self
.
handleChatMessage
(
fromId
)
})
connection
.
start
()
}
private
func
handleChatMessage
(
_
message
:
String
,
from
user
:
String
)
{
print
(
debug
:
"called"
)
}
private
func
handleAckMessage
(
_
time
:
String
)
{
print
(
debug
:
"called"
)
}
private
func
handleChatMessage
(
_
fromId
:
String
)
{
print
(
debug
:
"called"
)
}
func
applicationWillTerminate
(
_
aNotification
:
Notification
)
{
connection
.
stop
()
}
//呼び出す
func
chatMessage
(
_
message
:
String
)
{
var
request
=
ReqMessage
(
shipId
:
Preferences
.
shipId
,
messageId
:
"aaaa"
)
request
.
type
=
0
//0:テキスト, 1:スタンプ
// request.time = DateTextLib.Date2ISO8601Text(date: Date())
request
.
location
=
2
//1:Shore , 2:Ship
request
.
from
=
Preferences
.
UserName
//投稿者名
// request.fromeId = SharingData.my.shipName //ユーザーID
request
.
message
=
message
//テキスト
// request.stampId = //スタンプ番号 0:Fire~
if
message
!=
""
{
connection
.
invoke
(
method
:
"ChatMessage"
,
message
)
{
error
in
if
let
e
=
error
{
print
(
debug
:
"Error:
\(
e
)
"
)
}
}
}
}
func
ackMessage
(
_
message
:
String
)
{
var
request
=
ReqAckMessage
(
shipId
:
Preferences
.
shipId
,
messageId
:
"aaaa"
)
//request.time = DateTextLib.Date2ISO8601Text(date: Date())
request
.
location
=
2
//1:Shore , 2:Ship
// request.fromeId = SharingData.my.shipName //ユーザーID
if
message
!=
""
{
connection
.
invoke
(
method
:
"AckMessage"
,
request
)
{
error
in
if
let
e
=
error
{
print
(
debug
:
"Error:
\(
e
)
"
)
}
}
}
}
func
chatMode
(
_
message
:
String
)
{
var
request
=
ReqChatModeMessage
(
shipId
:
Preferences
.
shipId
)
// request.time = DateTextLib.Date2ISO8601Text(date: Date())
request
.
location
=
2
//1:Shore , 2:Ship
// request.fromeId = SharingData.my.shipName //ユーザーID
request
.
mode
=
0
//0:通常 / 1:Warning中
if
message
!=
""
{
connection
.
invoke
(
method
:
"ChatMode"
,
message
)
{
error
in
if
let
e
=
error
{
print
(
debug
:
"Error:
\(
e
)
"
)
}
}
}
}
// func chatMode2(_ message: String) {
// connection.send(method: "Broadcast", "Playground user", "Testing send") { error in
// if let error = error {
// print("Send failed: \(error)")
// }
// }
// }
}
class
ChatHubConnectionDelegate
:
HubConnectionDelegate
{
// weak var app: AppDelegate?
//
// init(app: AppDelegate) {
// self.app = app
// }
func
connectionDidOpen
(
hubConnection
:
HubConnection
)
{
print
(
"connectionDidOpen"
)
// After connection established call registerUserInServer method
DispatchQueue
.
main
.
async
{
// self.registerUserInServer()
}
}
func
connectionDidFailToOpen
(
error
:
Error
)
{
print
(
"connectionDidFailToOpen"
)
}
func
connectionDidClose
(
error
:
Error
?)
{
print
(
"connectionDidClose"
)
}
func
connectionWillReconnect
(
error
:
Error
)
{
print
(
"connectionWillReconnect"
)
}
func
connectionDidReconnect
()
{
print
(
"connectionDidReconnect"
)
}
}
Seilassist/Sailassist/Tab/MainTabView.swift
View file @
5e4e2e3c
...
...
@@ -122,12 +122,20 @@ struct CustomTabBar: View {
}
},
label
:
{
VStack
{
ZStack
(
alignment
:
.
bottomTrailing
)
{
Image
(
selectedTabModel
.
activeTab
==
tab
?
tab
.
rawValue
+
"_selected"
:
tab
.
rawValue
)
.
font
(
.
title2
)
// if tab == Tab.chat {
// Rectangle()
// .foregroundColor(.red)
// .frame(width: 12, height: 12)
// .cornerRadius(60)
// }
}
Text
(
tab
.
title
)
.
font
(
.
caption
)
}
.
frame
(
maxWidth
:
.
infinity
,
maxHeight
:
.
infinity
)
.
contentShape
(
.
rect
)
...
...
@@ -140,11 +148,9 @@ struct CustomTabBar: View {
.
background
(
ColorSet
.
BottomNav
.
color
)
.
alert
(
""
,
isPresented
:
$
selectedTabModel
.
isShowChangeEmrMode
)
{
Button
(
"Yes"
){
if
SharingData
.
message
.
mode
==
0
{
SharingData
.
message
.
mode
=
1
}
else
{
SharingData
.
message
.
mode
=
0
}
SharingData
.
message
.
changeMode
()
let
signalRService
=
SignalR
()
signalRService
.
chatMode
(
mode
:
SharingData
.
message
.
mode
)
}
Button
(
"No"
){
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment