Commit 9aeb57c1 authored by shigemi miura's avatar shigemi miura

チャット機能

parent 40fa98bc
......@@ -11,7 +11,7 @@ struct ChatView: View {
@EnvironmentObject private var selectedTabModel: SelectedTabModel
@ObservedObject var message = SharingData.message
@State var isShowMember: Bool = false
@StateObject var scrollBottom = ScrollBottom()
var body: some View {
ZStack {
if message.mode == true{
......@@ -29,7 +29,6 @@ struct ChatView: View {
.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)
......@@ -42,20 +41,28 @@ struct ChatView: View {
}
}
.onAppear {
self.scrollBottom.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}
proxy.scrollTo(value.last?.messageId, anchor: .center)
if let lastId = value.last?.messageId {
print(debug: "\(String(describing: lastId))")
if let id = message.messages.last?.messageId {
print(debug: "ChatView:onReceive")
proxy.scrollTo(id, anchor: .center)
}
}
}
.onChange(of: scrollBottom.scrollID) { id in
proxy.scrollTo(id, anchor: .center)
}
}
HStack {
......@@ -84,18 +91,6 @@ struct ChatView: View {
}
}
class ScrollBottom: ObservableObject {
@Published var scrollID: String = ""
func onAppear() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
if let id = SharingData.message.messages.last?.messageId {
self.scrollID = id
}
}
}
}
#Preview {
ChatView()
}
......@@ -77,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()
}
......
......@@ -9,8 +9,8 @@ import Foundation
struct ResAckMessage: Codable {
var shipId: Int
var messageId: Int //UUID
var messageId: String //UUID
var time: String //投稿日時
var location: Int //1:Shore、2:Ship
var fromId: Int //ユーザーID
var fromId: String //ユーザーID
}
......@@ -9,12 +9,12 @@ import Foundation
struct ResChatMessage: Codable {
var shipId: Int
var messageId: Int //UUID
var messageId: String //UUID
var type: Int //0:テキスト、1:スタンプ
var time: String //投稿日時
var location: Int //1:Shore、2:Ship
var from: String //投稿者名
var fromId: Int //ユーザーID
var fromId: String //ユーザーID
var message: String //テキスト
var stampId: Int //スタンプ番号
}
......@@ -11,6 +11,6 @@ struct ResChatMode: Codable {
var shipId: Int
var time: String //投稿日時
var location: Int //1:Shore、2:Ship
var fromId: Int //ユーザーID
var fromId: String //ユーザーID
var mode: Int //0:通常、1:Warning中
}
......@@ -187,9 +187,11 @@ struct LoginView: View {
let resjson = serverSession.fromJSON(resultData: resultData, resltType: ResLogin.self)
if let res = resjson {
SharingData.my.id = res.id
SharingData.my.shipId = res.shipId
SharingData.my.shipName = res.shipName
SharingData.my.imo = res.imo
SharingData.my.mmsi = res.mmsi
SharingData.my.isFuelSwitchTask = res.enableFuelSwitchTask
Preferences.shipId = res.shipId
......@@ -247,6 +249,7 @@ struct LoginView: View {
let resjson = serverSession.fromJSON(resultData: resultData, resltType: ResLogin.self)
if let res = resjson {
SharingData.my.id = res.id
SharingData.my.shipId = res.shipId
SharingData.my.shipName = res.shipName
SharingData.my.imo = res.imo
SharingData.my.mmsi = res.mmsi
......
......@@ -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 {
......@@ -46,6 +50,11 @@ struct MapRepresentable: UIViewControllerRepresentable{
}
}
//自船を画面中央に表示
if location.focusOwnShip {
mapVC.updateCamera(location: location.location, zoomlevel: nil)
}
if let mylocation = location.location {
mapVC.updateOwnShip(location: mylocation, bearing: location.heading)
......@@ -84,7 +93,6 @@ class MapViewController : UIViewController{
mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in
self.addLayers()
}
}
......@@ -284,6 +292,9 @@ class MapViewController : UIViewController{
if SharingData.pushHistory.focusPushHistory != nil {
SharingData.pushHistory.focusPushHistory = nil
}
if SharingData.location.focusOwnShip {
SharingData.location.focusOwnShip = false
}
}
///Ecaの線3本
......
......@@ -213,7 +213,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
......@@ -223,6 +223,8 @@ struct MenuView: View {
SharingData.map.legLine = []
SharingData.map.portLine = []
SharingData.map.starboardLine = []
connection!.stop()
}
Button("No") {}
} message: { Text("Are you sure?") }
......
......@@ -17,7 +17,6 @@ struct SailassistApp: App {
@State private var isPrivAgree = Preferences.privacyPolicyAgreeDate != nil
let locationViewModel = LocationViewModel()
let signalRService = SignalRService()
var body: some Scene {
WindowGroup {
......@@ -76,7 +75,7 @@ class NotificationTags: NSObject {
}
}
private var connection: HubConnection?
var connection: HubConnection?
class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, MSInstallationLifecycleDelegate {
private var hubConnectionDelegate: HubConnectionDelegate?
......@@ -110,23 +109,28 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
connection = HubConnectionBuilder(url: URL(string : HttpRequestType.SignalR.rawValue)!)
.withHubConnectionDelegate(delegate: hubConnectionDelegate!)
.withAutoReconnect()
.withLogging(minLogLevel: .error)
.withHubConnectionOptions(configureHubConnectionOptions: {options in options.keepAliveInterval = 20 })
// .withLogging(minLogLevel: .error)
.withLogging(minLogLevel: .debug)
// .withHubConnectionOptions(configureHubConnectionOptions: {options in options.keepAliveInterval = 20 })
.build()
connection!.on(method: "chatMessage", callback: { (message: ResChatMessage) in
if let r_connection = connection {
r_connection.stop()
r_connection.on(method: "chatMessage", callback: { (message: ResChatMessage) in
self.handleChatMessage(message: message)
})
connection!.on(method: "ackMessage", callback: { (message: ResAckMessage) in
r_connection.on(method: "ackMessage", callback: { (message: ResAckMessage) in
self.handleAckMessage(message: message)
})
connection!.on(method: "chatMode", callback: { (message: ResChatMode) in
r_connection.on(method: "chatMode", callback: { (message: ResChatMode) in
self.handleChatMessage(message: message)
})
connection!.start()
r_connection.start()
}
return true
}
......@@ -174,14 +178,17 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
private func handleChatMessage(message: ResChatMessage) {
print(debug: "called")
// print(debug: "called \(ResMessage)")
}
private func handleAckMessage(message: ResAckMessage) {
print(debug: "called")
// print(debug: "called \(ResAckMessage)")
}
private func handleChatMessage(message: ResChatMode) {
print(debug: "called")
// print(debug: "called \(ResChatMode)")
}
// func applicationWillTerminate(_ aNotification: Notification) {
......@@ -190,6 +197,8 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
}
class SignalR: NSObject {
@ObservedObject var msg = SharingData.message
func chatMessage(message: String) {
var request = ReqMessage(shipId: Preferences.shipId, messageId: UUID().uuidString)
request.type = 0 //0:テキスト, 1:スタンプ
......@@ -205,6 +214,9 @@ class SignalR: NSObject {
if let e = error {
print(debug: "Error:\(e)")
}
let viewer = Viewer(time: "", location: 0, id: "")
let ownMsg = ChatMessage(shipId: request.shipId, messageId: request.messageId, type: request.type, time: request.time, location: request.location, from: request.from, message: request.message, stampId: request.stampId, viewer: [viewer])
self.msg.messages.append(ownMsg)
}
}
}
......@@ -249,22 +261,27 @@ class ChatHubConnectionDelegate: HubConnectionDelegate {
}
func connectionDidOpen(hubConnection: HubConnection) {
print(debug: "connectionDidOpen")
// app?.connectionDidStart()
}
func connectionDidFailToOpen(error: Error) {
print(debug: "connectionDidFailToOpen")
// app?.connectionDidFailToOpen(error: error)
}
func connectionDidClose(error: Error?) {
print(debug: "connectionDidClose")
// app?.connectionDidClose(error: error)
}
func connectionWillReconnect(error: Error) {
print(debug: "connectionWillReconnect")
// app?.connectionWillReconnect(error: error)
}
func connectionDidReconnect() {
print(debug: "connectionDidReconnect")
// app?.connectionDidReconnect()
}
}
......@@ -289,8 +306,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
return
}
let subtitle = arrAlert["subtitle"] as? String ?? "" //送信先名称
let strTitle = arrAlert["title"] as? String ?? "" //送信内容
let strBody = arrAlert["body"] as? String ?? "" //船名
let strTitle = arrAlert["title"] as? String ?? "" //船名
let strBody = arrAlert["body"] as? String ?? "" //送信内容
let message = GetMessage()
message.start()
......@@ -336,8 +353,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
return
}
let subtitle = arrAlert["subtitle"] as? String ?? "" //送信先名称
let strTitle = arrAlert["title"] as? String ?? "" //送信内容
let strBody = arrAlert["body"] as? String ?? "" //船名
let strTitle = arrAlert["title"] as? String ?? "" //船名
let strBody = arrAlert["body"] as? String ?? "" //送信内容
let message = GetMessage()
message.start()
......
......@@ -235,7 +235,7 @@ class ServerSession{
httpBody1 += "Content-Type: image/jpeg\r\n"
httpBody1 += "\r\n"
var tmp = httpBody1.data(using: .utf8)!
// var tmp = httpBody1.data(using: .utf8)!
var httpBody = Data()
httpBody.append(httpBody1.data(using: .utf8)!)
......
......@@ -12,6 +12,7 @@ class SharingData{
static var my = My()
class My: ObservableObject {
@Published var id: Int = 0
@Published var shipId: Int = 0
@Published var shipName: String = ""
@Published var imo: Int = 0
@Published var mmsi: Int = 0
......@@ -36,6 +37,8 @@ class SharingData{
@Published var heading: Double = 0.0
@Published var dataTime: String = "" //2023-11-02T05:25:49.4362123Z
@Published var focusOwnShip: Bool = false
func setLocation(){
if Preferences.LocationType == 0 {
self.location = self.gps
......@@ -113,7 +116,7 @@ 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] = []
......
......@@ -30,6 +30,7 @@ struct MainTabView: View {
appearance.backgroundColor = .clear
UITabBar.appearance().scrollEdgeAppearance = appearance
UITabBar.appearance().standardAppearance = appearance
SharingData.location.focusOwnShip = true
// EcaCoordinatesTable().setEcaData()
}
......@@ -103,6 +104,7 @@ struct CustomTabBar: View {
@State var isLocationAlert = false
@Environment(\.openURL) var openURL
@ObservedObject var my = SharingData.my
@ObservedObject var location = SharingData.location
var body: some View {
VStack(spacing: 0){
......@@ -114,6 +116,7 @@ struct CustomTabBar: View {
selectedTabModel.activeTab = tab
if tab == .task {
selectedTabModel.isPoppver.toggle()
location.focusOwnShip = true
} else {
selectedTabModel.isPoppver = false
}
......
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