Commit 7f096f00 authored by shigemi miura's avatar shigemi miura

チャット機能

parent fbbb1ea7
......@@ -47,8 +47,8 @@ struct ChatView: View {
}
}
.onChange(of: message.messages.count) { newValue in
if let id = message.messages.last?.messageId {
withAnimation {
if let id = message.messages.last?.messageId {
print(debug: "ChatView:onChange")
proxy.scrollTo(id, anchor: .center)
}
......@@ -94,3 +94,4 @@ struct ChatView: View {
#Preview {
ChatView()
}
......@@ -27,23 +27,7 @@ class GetMessage {
if let msg = res.messages {
//既読マーク確認
SharingData.message.messages = msg
var msgCnt = 0 //受信メッセージ数
var viewCnt = 0 //既読メッセージ数
for message in SharingData.message.messages {
// print(debug: "message \(message)")
if message.fromId != Preferences.UserName {
msgCnt = msgCnt + 1
}
//SSV Mobileで既読
for view in message.viewer {
if view.location == 1 {
viewCnt = viewCnt + 1
}
}
}
// if msgCnt != viewCnt {
// SharingData.message.viewCnt = msgCnt - viewCnt
// }
self.checkUnreadMessages()
}
SharingData.message.users = []
if let users = res.users {
......@@ -56,5 +40,49 @@ class GetMessage {
}
}
}
/**
* 未読数の確認
*/
func checkUnreadMessages() {
var msgCnt = 0 //SSV Mobileからの受信メッセージ数
var viewCnt = 0 //Sail Assistでの既読メッセージ数
for message in SharingData.message.messages {
//SSV Mobileからの受信メッセージ
if message.location == 1 {
msgCnt = msgCnt + 1
if ((message.viewer.first(where: {$0.location == 2})) != nil){
viewCnt = viewCnt + 1
}
}
}
SharingData.message.viewCnt = msgCnt - viewCnt //未読数
}
/**
* 既読通知
*/
func readNotification() {
for message in SharingData.message.messages {
//Sail Assist側で既読が無い場合(既読確認)
var unRead = true
if ((message.viewer.first(where: {$0.location == 2})) != nil){
unRead = false //既読状態
}
if unRead {
let signalRService = SignalR()
signalRService.ackMessage(messageId: message.messageId)
let msgIndex = SharingData.message.messages.firstIndex(where: {$0.messageId == message.messageId})
if let index = msgIndex {
let viewer = Viewer(time: DateTextLib.Date2ISO8601Text(Date()), location: 2, id: "")
SharingData.message.messages[index].viewer.append(viewer)
}
}
}
}
}
......@@ -15,48 +15,22 @@ struct MyChatContentView: View {
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: {
AsyncImage(url: URL(string: message.message)) { phase in
if let image = phase.image {
image
.resizable(resizingMode: .stretch)
.aspectRatio(contentMode: .fit)
.frame(width: 250)
} else if phase.error != nil {
Color.gray.opacity(0.2)
.overlay(Image(systemName: "rectangle.slash"))
} else {
Color.gray.opacity(0.2)
ProgressView()
}
}
.cornerRadius(16)
.frame(height: 250)
} else {
Text(message.message)
.font(FontStyle.DefaultText.font)
......
......@@ -18,48 +18,22 @@ struct OtherChatContentView: View {
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: {
AsyncImage(url: URL(string: message.message)) { phase in
if let image = phase.image {
image
.resizable(resizingMode: .stretch)
.aspectRatio(contentMode: .fit)
.frame(width: 250)
} else if phase.error != nil {
Color.gray.opacity(0.2)
.overlay(Image(systemName: "rectangle.slash"))
} else {
Color.gray.opacity(0.2)
ProgressView()
}
}
.cornerRadius(16)
.frame(height: 250)
} else {
Text(message.message)
.font(FontStyle.DefaultText.font)
......@@ -70,21 +44,13 @@ struct OtherChatContentView: View {
}
}
HStack(alignment: .top){
HStack(alignment: .top) {
Text(DateTextLib.ISO86012FormatText(message.time, format: "yyyy/MM/dd hh:mm", errFormat: ""))
.font(FontStyle.DateText.font)
.foregroundColor(ColorSet.ChatDate.color)
}
}
}
.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()
}
......
......@@ -23,7 +23,7 @@ struct ChatMessage: Codable {
var fromId: String? //ユーザーID
var message: String //テキスト時:テキスト , 画像時:サムネイルのUri
var stampId: Int //スタンプ番号 0:Fire~
var viewer: [Viewer] //閲覧者情報
var viewer: [Viewer] = [] //閲覧者情報
}
struct Viewer: Codable {
......
......@@ -207,14 +207,14 @@ struct LoginView: View {
Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
isLogin = true
let message = GetMessage()
message.start()
timer = Timer.scheduledTimer(withTimeInterval: TimerInterval, repeats: true) { _ in
print(debug: "called timer")
let eca = EcaTask()
eca.start()
let message = GetMessage()
message.start()
let route = MonitoringRoute()
route.start()
......
......@@ -113,14 +113,14 @@ struct InputUserNameView: View {
Preferences.Password = param.password
Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
let message = GetMessage()
message.start()
timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { _ in
print(debug: "called timer")
let eca = EcaTask()
eca.start()
let message = GetMessage()
message.start()
let route = MonitoringRoute()
route.start()
......
......@@ -77,6 +77,7 @@ class NotificationTags: NSObject {
var connection: HubConnection?
class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, MSInstallationLifecycleDelegate {
@ObservedObject var msg = SharingData.message
private var hubConnectionDelegate: HubConnectionDelegate?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
......@@ -117,16 +118,16 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
if let r_connection = connection {
r_connection.stop()
r_connection.on(method: "chatMessage", callback: { (message: ResChatMessage) in
r_connection.on(method: "ChatMessage", callback: { (message: ResChatMessage) in
self.handleChatMessage(message: message)
})
r_connection.on(method: "ackMessage", callback: { (message: ResAckMessage) in
r_connection.on(method: "AckMessage", callback: { (message: ResAckMessage) in
self.handleAckMessage(message: message)
})
r_connection.on(method: "chatMode", callback: { (message: ResChatMode) in
self.handleChatMessage(message: message)
r_connection.on(method: "ChatMode", callback: { (message: ResChatMode) in
self.handleChatMode(message: message)
})
r_connection.start()
......@@ -168,27 +169,42 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
// APNs 登録成功時に呼ばれる
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
print("デバイストークン : \(token)")
print(debug: "デバイストークン : \(token)")
}
// APNs 登録失敗時に呼ばれる
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("APNs 登録に失敗しました : \(error.localizedDescription)")
print(debug: "APNs 登録に失敗しました : \(error.localizedDescription)")
}
private func handleChatMessage(message: ResChatMessage) {
print(debug: "called")
// print(debug: "called \(ResMessage)")
print(debug: "test:called")
let ownMsg = ChatMessage(shipId: message.shipId, messageId: message.messageId, type: message.type, time: message.time, location: message.location, from: message.from, message: message.message, stampId: message.stampId, viewer: [])
self.msg.messages.append(ownMsg)
let message = GetMessage()
message.checkUnreadMessages()
}
private func handleAckMessage(message: ResAckMessage) {
print(debug: "called")
// print(debug: "called \(ResAckMessage)")
print(debug: "test:called")
let msgIndex = self.msg.messages.firstIndex(where: {$0.messageId == message.messageId})
if let index = msgIndex {
let viewer = Viewer(time: message.time, location: message.location, id: message.fromId)
self.msg.messages[index].viewer.append(viewer)
}
private func handleChatMessage(message: ResChatMode) {
print(debug: "called")
// print(debug: "called \(ResChatMode)")
let message = GetMessage()
message.checkUnreadMessages()
}
private func handleChatMode(message: ResChatMode) {
print(debug: "test:called")
if message.mode == 1 {
self.msg.mode = true
} else {
self.msg.mode = false
}
}
//アプリ終了時
......@@ -203,7 +219,8 @@ class SignalR: NSObject {
@ObservedObject var msg = SharingData.message
func chatMessage(message: String) {
var request = ReqMessage(shipId: Preferences.shipId, messageId: UUID().uuidString)
print(debug: "test:called")
var request = ReqMessage(shipId: Preferences.shipId, messageId: UUID().uuidString.lowercased())
request.type = 0 //0:テキスト, 1:スタンプ
request.time = DateTextLib.Date2ISO8601Text(Date())
request.location = 2 //1:Shore , 2:Ship
......@@ -217,14 +234,14 @@ 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])
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: [])
self.msg.messages.append(ownMsg)
}
}
}
func ackMessage(messageId: String) {
print(debug: "test:called")
var request = ReqAckMessage(shipId: Preferences.shipId, messageId: messageId)
request.time = DateTextLib.Date2ISO8601Text(Date())
request.location = 2 //1:Shore , 2:Ship
......@@ -308,13 +325,16 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
completionHandler([[.banner, .badge, .sound]])
return
}
let subtitle = arrAlert["subtitle"] as? String ?? "" //送信内容
let subtitle = arrAlert["subtitle"] as? String ?? "" //送信先名称
let strTitle = arrAlert["title"] as? String ?? "" //船名
let strBody = arrAlert["body"] as? String ?? "" //送信先名称
let strBody = arrAlert["body"] as? String ?? "" //送信内容
print(debug: "called \(subtitle) \(strTitle) \(strBody)")
let message = GetMessage()
message.start()
//送信先名称が同一の場合は通知を出さない
if subtitle == Preferences.UserName {
return
}
case "sailassist":
print(debug: "sailassist")
let getPushHistory = GetPushHistory()
......@@ -362,8 +382,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
let strBody = arrAlert["body"] as? String ?? "" //送信先名称
print(debug: "called \(subtitle) \(strTitle) \(strBody)")
let message = GetMessage()
message.start()
// let message = GetMessage()
// message.start()
case "sailassist":
print(debug: "sailassist")
let getPushHistory = GetPushHistory()
......
......@@ -8,9 +8,7 @@
import SwiftUI
enum Tab: String, CaseIterable{
#if CANARY
case chat = "tab_chat"
#endif
case task = "tab_task"
case alert = "tab_notification"
case menu = "tab_menu"
......@@ -40,10 +38,9 @@ struct MainTabView: View {
@State var isTaskSel: Bool = selectedTabModel.activeTab == .task
TabView(selection: $selectedTabModel.activeTab){
#if CANARY
ChatView()
.tag(Tab.chat)
#endif
MapRepresentable()
.ignoresSafeArea()
.tag(Tab.task)
......@@ -117,6 +114,12 @@ struct CustomTabBar: View {
if tab == .task {
selectedTabModel.isPoppver.toggle()
location.focusOwnShip = true
} else if tab == .chat {
let message = GetMessage()
message.readNotification()
message.checkUnreadMessages()
selectedTabModel.isPoppver = false
} 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