Commit d63ac4ca authored by shigemi miura's avatar shigemi miura

通知表示

タスク表示順序
parent e3319fdc
...@@ -1166,11 +1166,14 @@ ...@@ -1166,11 +1166,14 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 0.9;
OTHER_SWIFT_FLAGS = "-D CANARY -D COCOAPODS"; OTHER_SWIFT_FLAGS = "-D CANARY -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.canary; PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.canary;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
...@@ -1206,10 +1209,13 @@ ...@@ -1206,10 +1209,13 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 0.9;
OTHER_SWIFT_FLAGS = "-D COCOAPODS"; OTHER_SWIFT_FLAGS = "-D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist; PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
...@@ -1389,10 +1395,13 @@ ...@@ -1389,10 +1395,13 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 0.9;
OTHER_SWIFT_FLAGS = "-D QC -D COCOAPODS"; OTHER_SWIFT_FLAGS = "-D QC -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.qc; PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.qc;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
buildConfiguration = "Canary"> buildConfiguration = "Canary">
</AnalyzeAction> </AnalyzeAction>
<ArchiveAction <ArchiveAction
buildConfiguration = "Release" buildConfiguration = "Canary"
revealArchiveInOrganizer = "YES"> revealArchiveInOrganizer = "YES">
</ArchiveAction> </ArchiveAction>
</Scheme> </Scheme>
...@@ -8,14 +8,23 @@ ...@@ -8,14 +8,23 @@
import SwiftUI import SwiftUI
struct NotificationView: View { struct NotificationView: View {
@EnvironmentObject var selectedTabModel: SelectedTabModel
@ObservedObject var pushHist = SharingData.pushHistory @ObservedObject var pushHist = SharingData.pushHistory
var body: some View { var body: some View {
VStack(spacing: 0){ VStack(spacing: 0){
TitleView() TitleView()
ScrollView { ScrollView {
ForEach(pushHist.pushHistoryData.map{ $1 }.sorted{ DateTextLib.ISO8601Text2UnixTime($0.time) > DateTextLib.ISO8601Text2UnixTime($1.time)}, id: \.id){ data in ForEach(pushHist.pushHistoryData.map{ $1 }.sorted{ $0.id ?? 0 > $1.id ?? 0 }, id: \.id){ data in
NotificationContentView(pushData: data) NotificationContentView(pushData: data)
.onTapGesture {
if let position = data.position {
if position.lat != nil && position.lon != nil {
selectedTabModel.activeTab = .task
pushHist.focusPushHistory = data.id
}
}
}
Divider() Divider()
.frame(height: 1) .frame(height: 1)
...@@ -33,6 +42,7 @@ struct NotificationView: View { ...@@ -33,6 +42,7 @@ struct NotificationView: View {
VStack { VStack {
HStack { HStack {
Button{ Button{
print(debug: "called")
}label: { }label: {
} }
.disabled(true) .disabled(true)
...@@ -48,6 +58,7 @@ struct NotificationView: View { ...@@ -48,6 +58,7 @@ struct NotificationView: View {
Spacer() Spacer()
Button{ Button{
print(debug: "called")
}label: { }label: {
} }
.disabled(true) .disabled(true)
......
...@@ -4,10 +4,12 @@ ...@@ -4,10 +4,12 @@
// //
// Created by Mamoru Sugita on 2023/11/27. // Created by Mamoru Sugita on 2023/11/27.
// //
import SwiftUI import SwiftUI
import CoreLocation
struct NotificationContentView: View { struct NotificationContentView: View {
@EnvironmentObject var selectedTabModel: SelectedTabModel
var pushData: ResPushHistory var pushData: ResPushHistory
var body: some View { var body: some View {
VStack(alignment: .leading, spacing: 4){ VStack(alignment: .leading, spacing: 4){
...@@ -24,11 +26,22 @@ struct NotificationContentView: View { ...@@ -24,11 +26,22 @@ struct NotificationContentView: View {
Spacer() Spacer()
} }
HStack(spacing: 10) {
Text(pushData.title ?? "JTest-Ship") Text(pushData.title ?? "JTest-Ship")
.foregroundColor(ColorSet.Body.color) .foregroundColor(ColorSet.Body.color)
.font(FontStyle.EmphasisText.font) .font(FontStyle.EmphasisText.font)
Spacer()
if let position = pushData.position {
if position.lat != nil && position.lon != nil {
Image("map_pin")
.resizable()
.frame(width: 20, height: 20)
}
}
}
Text(pushData.message ?? "Fire emergency notice from ship") Text(pushData.message ?? "Fire emergency notice from ship")
.foregroundColor(ColorSet.BodyDescriptiion.color) .foregroundColor(ColorSet.BodyDescriptiion.color)
.font(FontStyle.SupplementText2.font) .font(FontStyle.SupplementText2.font)
......
{ {
"images" : [ "images" : [
{ {
"filename" : "app_icon40.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "app_icon60.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "app_icon58.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "app_icon87.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "app_icon76.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "38x38"
},
{
"filename" : "app_icon114.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "38x38"
},
{
"filename" : "app_icon80.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "app_icon120 1.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "app_icon120.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "app_icon180.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "app_icon128.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "64x64"
},
{
"filename" : "app_icon192.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "64x64"
},
{
"filename" : "app_icon136.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "68x68"
},
{
"filename" : "app_icon152.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "app_icon167.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "app_icon1024.png",
"idiom" : "universal", "idiom" : "universal",
"platform" : "ios", "platform" : "ios",
"size" : "1024x1024" "size" : "1024x1024"
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "map_pin.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "map_pin_dark.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -19,11 +19,7 @@ class DeleteEcaArea { ...@@ -19,11 +19,7 @@ class DeleteEcaArea {
print(debug: "called") print(debug: "called")
switch result { switch result {
case .success(let resultData): case .success(let resultData):
let serverSession = ServerSession() print(debug: resultData)
let resjson = serverSession.fromJSON(resultData: resultData, resltType: ReqTaskList.self)
if let res = resjson {
//ECA保存
}
case .failure(let errorCode): case .failure(let errorCode):
print(debug: errorCode) print(debug: errorCode)
break break
......
...@@ -23,7 +23,7 @@ class EcaArea { ...@@ -23,7 +23,7 @@ class EcaArea {
let serverSession = ServerSession() let serverSession = ServerSession()
let resjson = serverSession.fromJSON(resultData: resultData, resltType: [ResEcaArea].self) let resjson = serverSession.fromJSON(resultData: resultData, resltType: [ResEcaArea].self)
if let res = resjson { if let res = resjson {
var area = res print(debug: res)
} }
case .failure(let errorCode): case .failure(let errorCode):
print(debug: errorCode) print(debug: errorCode)
......
...@@ -59,7 +59,7 @@ class EcaTask { ...@@ -59,7 +59,7 @@ class EcaTask {
let runningEca = eca.ecaArea.first(where: {(key, value) in value.isRunning == true}) let runningEca = eca.ecaArea.first(where: {(key, value) in value.isRunning == true})
if var eca = runningEca?.value { if var eca = runningEca?.value {
if let location = SharingData.my.location { if let location = SharingData.my.location {
if var distance = LocationCalculation.checkPolyline(objPos: eca.points, shipPos: location) { if let distance = LocationCalculation.checkPolyline(objPos: eca.points, shipPos: location) {
//起動時に状態を設定 //起動時に状態を設定
if SharingData.my.ecaStatus == nil { if SharingData.my.ecaStatus == nil {
...@@ -109,12 +109,12 @@ class EcaTask { ...@@ -109,12 +109,12 @@ class EcaTask {
} }
if eca.swStart >= Float(distance) && result == false{ if eca.swStart >= Float(distance) && result == false{
newData.status = EcaState.startPass newData.status = EcaState.noticePass
result = true result = true
} }
if eca.swNotice >= Float(distance) && result == false{ if eca.swNotice >= Float(distance) && result == false{
newData.status = EcaState.noticePass newData.status = EcaState.running
} }
return newData return newData
......
...@@ -42,46 +42,28 @@ enum HttpRequestType : String { ...@@ -42,46 +42,28 @@ enum HttpRequestType : String {
case SignalR = "https://ssv-qc-web.azurewebsites.net/signalr/shore" case SignalR = "https://ssv-qc-web.azurewebsites.net/signalr/shore"
case PushHistory = "https://ssv-qc-web.azurewebsites.net/api/sailassist/pushhistory/XXXXX" case PushHistory = "https://ssv-qc-web.azurewebsites.net/api/sailassist/pushhistory/XXXXX"
case UploadImage = "https://ssv-qc-web.azurewebsites.net/api/chatdata/uploadimage" case UploadImage = "https://ssv-qc-web.azurewebsites.net/api/chatdata/uploadimage"
case ConnectionString = "Endpoint=sb://tacmiqchub.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=mjGZyOensA5D/T6bMiDDwX6hwhoZNsDcK+GtBBBiUXk=" case ConnectionString = "Endpoint=sb://ssv-qc-notification.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=qjI5K38IyGfh2arFherVgp5tNUBE2U4eVClgTEQip54="
case HubName = "tacmiqchub" case HubName = "ssv-qc-sailassist-notification"
case storage = "https://tacmiquaritycheckstorage.z31.web.core.windows.net/" case storage = "https://tacmiquaritycheckstorage.z31.web.core.windows.net/"
} }
#else #else
//MARK: 運用サーバー用 //MARK: 運用サーバー用
enum HttpRequestType : String { enum HttpRequestType : String {
case Terms = "https://tacmistorage.blob.core.windows.net/$web/terms/terms.mobile.html?sv=2021-10-04&st=2023-11-22T06%3A26%3A32Z&se=2023-11-23T06%3A26%3A32Z&sr=b&sp=r&sig=wS6kbbT5SvNVTkRsnRk%2BiDceZAsQ3Y56vrqTUO1X50E%3D" case Terms = "https://tacmistorage.blob.core.windows.net/$web/terms/terms.mobile.html?sv=2021-10-04&st=2023-11-22T06%3A26%3A32Z&se=2023-11-23T06%3A26%3A32Z&sr=b&sp=r&sig=wS6kbbT5SvNVTkRsnRk%2BiDceZAsQ3Y56vrqTUO1X50E%3D"
case RegisterLogin = "https://ssv-canary-web.azurewebsites.net/sailassistlogin" case RegisterLogin = "https://ssv.jmarinecloud.com/sailassistlogin"
case SitePolicy = "https://ssv-canary-web.azurewebsites.net/sitepolicy" case SitePolicy = "https://ssv.jmarinecloud.com/sitepolicy"
case CookiePolicy = "https://ssv-canary-web.azurewebsites.net/cookiepolicy" case CookiePolicy = "https://ssv.jmarinecloud.com/cookiepolicy"
case PrivacyPolicy = "https://ssv-canary-web.azurewebsites.net/inapp?" //+バージョン番号 case PrivacyPolicy = "https://ssv.jmarinecloud.com/inapp?" //+バージョン番号
case TaskList = "https://ssv-canary-web.azurewebsites.net/api/sailassist/tasklist/XXXXX" case TaskList = "https://ssv.jmarinecloud.com/api/sailassist/tasklist/XXXXX"
case EcaArea = "https://ssv-canary-web.azurewebsites.net/api/sailassist/ecaarea/XXXXX" case EcaArea = "https://ssv.jmarinecloud.com/api/sailassist/ecaarea"
case ShipStatus = "https://ssv-canary-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX" case ShipStatus = "https://ssv.jmarinecloud.com/api/sailassist/shipstatus/XXXXX"
case ShipMonitoringRoute = "https://ssv-canary-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX" case ShipMonitoringRoute = "https://ssv.jmarinecloud.com/api/sailassist/shipmonitoringroute/XXXXX"
case GetMessage = "https://ssv-canary-web.azurewebsites.net/api/chatdata/getmessages?shipId=XXXXX" case GetMessage = "https://ssv.jmarinecloud.com/api/chatdata/getmessages?shipId=XXXXX"
case SignalR = "https://ssv-canary-web.azurewebsites.net/signalr/shore" case SignalR = "https://ssv.jmarinecloud.com/signalr/shore"
case PushHistory = "https://ssv-canary-web.azurewebsites.net/api/sailassist/pushhistory/XXXXX" case PushHistory = "https://ssv.jmarinecloud.com/api/sailassist/pushhistory/XXXXX"
case UploadImage = "https://ssv-canary-web.azurewebsites.net/api/chatdata/uploadimage" case UploadImage = "https://ssv.jmarinecloud.com/api/chatdata/uploadimage"
case ConnectionString = "Endpoint=sb://ssv-canary-notification.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=zHzVMA757FciMum5jVG4NMl82YpYVzclUgCiKOVRKf8=" case ConnectionString = "Endpoint=sb://ssv-notification.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=IzbO7Lo+PenhlIaHBw1MA7+NE9XaLikwieOFwCzZC50="
case HubName = "ssv-canary-sailassist-notification" case HubName = "ssv-sailassist-notification"
case storage = "https://ssvcanarystorage.z1.web.core.windows.net/" case storage = "https://tacmistorage.z31.web.core.windows.net/"
} }
//enum HttpRequestType : String {
// case Terms = "https://tacmistorage.blob.core.windows.net/$web/terms/terms.mobile.html?sv=2021-10-04&st=2023-11-22T06%3A26%3A32Z&se=2023-11-23T06%3A26%3A32Z&sr=b&sp=r&sig=wS6kbbT5SvNVTkRsnRk%2BiDceZAsQ3Y56vrqTUO1X50E%3D"
// case RegisterLogin = "https://ssv.jmarinecloud.com/sailassistlogin"
// case SitePolicy = "https://ssv.jmarinecloud.com/sitepolicy"
// case CookiePolicy = "https://ssv.jmarinecloud.com/cookiepolicy"
// case PrivacyPolicy = "https://ssv.jmarinecloud.com/inapp?" //+バージョン番号
// case TaskList = "https://ssv.jmarinecloud.com/api/sailassist/tasklist/XXXXX"
// case EcaArea = "https://ssv.jmarinecloud.com/api/sailassist/ecaarea"
// case ShipStatus = "https://ssv.jmarinecloud.com/api/sailassist/shipstatus/XXXXX"
// case ShipMonitoringRoute = "https://ssv.jmarinecloud.com/api/sailassist/shipmonitoringroute/XXXXX"
// case GetMessage = "https://ssv.jmarinecloud.com/api/chatdata/getmessages?shipId=XXXXX"
// case SignalR = "https://ssv.jmarinecloud.com/signalr/shore"
// case PushHistory = "https://ssv.jmarinecloud.com/api/sailassist/pushhistory/XXXXX"
// case UploadImage = "https://ssv.jmarinecloud.com/api/chatdata/uploadimage"
// case ConnectionString = "Endpoint=sb://tacmihub.servicebus.windows.net/;SharedAccessKeyName=DefaultListenSharedAccessSignature;SharedAccessKey=/IOJAYGLZmS2JvlsHT5aT+ETlPXqNt1+VGuMNDt4bzw="
// case HubName = "tacmihub"
// case storage = "https://tacmistorage.z31.web.core.windows.net/"
//}
#endif #endif
...@@ -19,6 +19,27 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { ...@@ -19,6 +19,27 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
authorizationStatus = locationManager.authorizationStatus authorizationStatus = locationManager.authorizationStatus
super.init() super.init()
}
func requestPermission() {
locationManager.requestAlwaysAuthorization()
let status = CLLocationManager().authorizationStatus
switch status {
case .authorizedAlways :
print(debug: "authorizationStatus : .authorizedAlways")
case .notDetermined:
print(debug: "authorizationStatus : .notDetermined")
case .restricted:
print(debug: "authorizationStatus : .restricted")
case .denied:
print(debug: "authorizationStatus : .denied")
case .authorizedWhenInUse:
print(debug: "authorizationStatus : .authorizedWhenInUse")
@unknown default:
print(debug: "authorizationStatus : Unknown")
}
if status == .authorizedAlways || status == .authorizedWhenInUse {
locationManager.delegate = self locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true // バックグラウンド実行中も座標取得する場合、trueにする locationManager.allowsBackgroundLocationUpdates = true // バックグラウンド実行中も座標取得する場合、trueにする
locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.desiredAccuracy = kCLLocationAccuracyBest
...@@ -28,10 +49,6 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { ...@@ -28,10 +49,6 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
locationManager.startUpdatingLocation() locationManager.startUpdatingLocation()
} }
func requestPermission() {
locationManager.requestWhenInUseAuthorization()
locationManager.requestAlwaysAuthorization() // バックグラウンド実行中も座標取得する場合はこちら
} }
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
......
...@@ -14,6 +14,7 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -14,6 +14,7 @@ struct MapRepresentable: UIViewControllerRepresentable{
@ObservedObject var ecaData = SharingData.eca @ObservedObject var ecaData = SharingData.eca
@ObservedObject var my = SharingData.my @ObservedObject var my = SharingData.my
@ObservedObject var map = SharingData.map @ObservedObject var map = SharingData.map
@ObservedObject var pushHistory = SharingData.pushHistory
@State var mapVC = MapViewController() @State var mapVC = MapViewController()
func makeUIViewController(context: Context) -> some UIViewController { func makeUIViewController(context: Context) -> some UIViewController {
...@@ -24,10 +25,20 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -24,10 +25,20 @@ struct MapRepresentable: UIViewControllerRepresentable{
let ecaArea = ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first let ecaArea = ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first
if let ecaArea = ecaArea{ if let ecaArea = ecaArea{
mapVC.updateEcaLine(line: ecaArea.points) mapVC.updateEcaLine(line: ecaArea.points)
} else {
mapVC.removeEcaLine()
} }
if let foucusEcaName = ecaData.foucusEca, let foucusEca = ecaData.ecaArea[foucusEcaName]{ if let focusEcaName = ecaData.focusEca, let focusEca = ecaData.ecaArea[focusEcaName]{
mapVC.updateCamera(location: foucusEca.points.first) mapVC.updateCamera(location: focusEca.points.first)
}
if let focusPushHistoryId = pushHistory.focusPushHistory, let focusPushHistory = pushHistory.pushHistoryData[focusPushHistoryId]{
if let position = focusPushHistory.position {
if let latitude = position.lat, let longitude = position.lon {
mapVC.updateCamera(location: CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
}
}
} }
if let mylocation = my.location { if let mylocation = my.location {
...@@ -35,6 +46,8 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -35,6 +46,8 @@ struct MapRepresentable: UIViewControllerRepresentable{
if let ecaArea = ecaArea{ if let ecaArea = ecaArea{
mapVC.updateEcaSwitchingLine(center: mylocation, notice: ecaArea.swNotice, start: ecaArea.swStart, finish: ecaArea.swFinish) mapVC.updateEcaSwitchingLine(center: mylocation, notice: ecaArea.swNotice, start: ecaArea.swStart, finish: ecaArea.swFinish)
} else {
mapVC.removeEcaSwitchingLine()
} }
} }
mapVC.updateWakeLines(legLine: map.legLine, portLine: map.portLine, starboardLine: map.starboardLine) mapVC.updateWakeLines(legLine: map.legLine, portLine: map.portLine, starboardLine: map.starboardLine)
...@@ -56,20 +69,17 @@ class MapViewController : UIViewController{ ...@@ -56,20 +69,17 @@ class MapViewController : UIViewController{
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
let centerCoordinate = CLLocationCoordinate2D(latitude: 37.8, longitude: -96) let centerCoordinate = CLLocationCoordinate2D(latitude: 37.8, longitude: -96)
let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2))
zoom: 2))
mapView = MapView(frame: view.bounds, mapInitOptions: options) mapView = MapView(frame: view.bounds, mapInitOptions: options)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight] mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(mapView) self.view.addSubview(mapView)
mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in
self.addLayers() self.addLayers()
} }
} }
func addImage(){ func addImage(){
...@@ -112,7 +122,7 @@ class MapViewController : UIViewController{ ...@@ -112,7 +122,7 @@ class MapViewController : UIViewController{
let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)]) let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)])
var ecaLinefeature = Feature(geometry: ecaLineString) let ecaLinefeature = Feature(geometry: ecaLineString)
ecaLine.source.data = .feature(ecaLinefeature) ecaLine.source.data = .feature(ecaLinefeature)
var ecaLineLayer = LineLayer(id: ecaLine.layerId) var ecaLineLayer = LineLayer(id: ecaLine.layerId)
ecaLineLayer.source = ecaLine.sourceId ecaLineLayer.source = ecaLine.sourceId
...@@ -190,8 +200,14 @@ class MapViewController : UIViewController{ ...@@ -190,8 +200,14 @@ class MapViewController : UIViewController{
///カメラ ///カメラ
func updateCamera(location: CLLocationCoordinate2D?){ func updateCamera(location: CLLocationCoordinate2D?){
self.mapView.camera.ease(to: CameraOptions(center: location), duration: 1) self.mapView.camera.ease(to: CameraOptions(center: location), duration: 1)
SharingData.eca.foucusEca = nil if let eca = SharingData.eca.focusEca {
SharingData.eca.focusEca = nil
}
if let push = SharingData.pushHistory.focusPushHistory {
SharingData.pushHistory.focusPushHistory = nil
} }
}
///Ecaの線3本 ///Ecaの線3本
func updateEcaSwitchingLine(center: CLLocationCoordinate2D, notice: Float, start: Float, finish: Float){ func updateEcaSwitchingLine(center: CLLocationCoordinate2D, notice: Float, start: Float, finish: Float){
do{ do{
...@@ -242,6 +258,18 @@ class MapViewController : UIViewController{ ...@@ -242,6 +258,18 @@ class MapViewController : UIViewController{
}catch{} }catch{}
} }
func removeEcaSwitchingLine(){
do{
let switchingLines : [Feature] = []
let switchingLabels : [Feature] = []
let lineGeoJson = FeatureCollection(features: switchingLines)
let labelGeoJson = FeatureCollection(features: switchingLabels)
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson))
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson))
}catch{}
}
///円の位置情報を返す ///円の位置情報を返す
private func getCirclePoints(center: CLLocationCoordinate2D, radiusKm: Double) -> [CLLocationCoordinate2D]{ private func getCirclePoints(center: CLLocationCoordinate2D, radiusKm: Double) -> [CLLocationCoordinate2D]{
var circlePoints : [CLLocationCoordinate2D] = [] var circlePoints : [CLLocationCoordinate2D] = []
...@@ -257,7 +285,6 @@ class MapViewController : UIViewController{ ...@@ -257,7 +285,6 @@ class MapViewController : UIViewController{
return circlePoints return circlePoints
} }
func updateEcaLine(line: [CLLocationCoordinate2D]){ func updateEcaLine(line: [CLLocationCoordinate2D]){
do{ do{
var geoJson = Feature(geometry: LineString(line)) var geoJson = Feature(geometry: LineString(line))
...@@ -267,6 +294,14 @@ class MapViewController : UIViewController{ ...@@ -267,6 +294,14 @@ class MapViewController : UIViewController{
}catch{} }catch{}
} }
func removeEcaLine(){
do{
let line: [CLLocationCoordinate2D] = []
let geoJson = Feature(geometry: LineString(line))
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson))
}catch{}
}
func updateWakeLines(legLine: [CLLocationCoordinate2D], portLine: [CLLocationCoordinate2D], starboardLine: [CLLocationCoordinate2D]){ func updateWakeLines(legLine: [CLLocationCoordinate2D], portLine: [CLLocationCoordinate2D], starboardLine: [CLLocationCoordinate2D]){
do{ do{
var legLineFeature = Feature(geometry: LineString(legLine)) var legLineFeature = Feature(geometry: LineString(legLine))
...@@ -314,8 +349,6 @@ class MapViewController : UIViewController{ ...@@ -314,8 +349,6 @@ class MapViewController : UIViewController{
}catch{} }catch{}
} }
enum PropertyKey : String { enum PropertyKey : String {
case IconImage case IconImage
case Bearing case Bearing
......
...@@ -11,13 +11,13 @@ struct EcaListView: View { ...@@ -11,13 +11,13 @@ struct EcaListView: View {
@ObservedObject var ecaData = SharingData.eca @ObservedObject var ecaData = SharingData.eca
var body: some View { var body: some View {
ForEach(ecaData.ecaArea.map{ $0.1 }, id: \.name){ eca in ForEach(ecaData.ecaArea.map{ $0.1 }.sorted{ $0.id ?? 0 < $1.id ?? 0 }, id: \.name){ eca in
HStack { HStack {
Text(eca.name) Text(eca.name)
.font(FontStyle.DefaultText.font) .font(FontStyle.DefaultText.font)
.foregroundColor(ColorSet.Body.color) .foregroundColor(ColorSet.Body.color)
.onTapGesture { .onTapGesture {
ecaData.foucusEca = eca.name ecaData.focusEca = eca.name
} }
Spacer() Spacer()
if !eca.isEnable{ if !eca.isEnable{
......
...@@ -54,7 +54,6 @@ struct MapTaskView: View { ...@@ -54,7 +54,6 @@ struct MapTaskView: View {
}) })
.frame(width: 48, height: 48) .frame(width: 48, height: 48)
Spacer() Spacer()
Text(viewMode.title) Text(viewMode.title)
...@@ -73,7 +72,6 @@ struct MapTaskView: View { ...@@ -73,7 +72,6 @@ struct MapTaskView: View {
} }
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17)) .padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider() Divider()
.background(ColorSet.LineColor03.color) .background(ColorSet.LineColor03.color)
...@@ -88,7 +86,6 @@ struct MapTaskView: View { ...@@ -88,7 +86,6 @@ struct MapTaskView: View {
case .EcaList: case .EcaList:
EcaListView() EcaListView()
} }
} }
Spacer() Spacer()
...@@ -99,7 +96,7 @@ struct MapTaskView: View { ...@@ -99,7 +96,7 @@ struct MapTaskView: View {
EcaCoordinatesTable().setEcaData() EcaCoordinatesTable().setEcaData()
} }
.alert("", isPresented: $eca.isShowEcaAlert) { .alert("", isPresented: $eca.isShowEcaAlert) {
if var ecaArea = eca.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first{ if let ecaArea = eca.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first{
if SharingData.my.ecaStatus == .finishPass{ if SharingData.my.ecaStatus == .finishPass{
Button("Yes"){ Button("Yes"){
var newData = ecaArea var newData = ecaArea
......
...@@ -23,9 +23,10 @@ struct TaskSwitchingMenuView: View { ...@@ -23,9 +23,10 @@ struct TaskSwitchingMenuView: View {
var body: some View { var body: some View {
VStack{ VStack{
ForEach(ecaData.ecaArea.map{ $0.1 }.filter{ $0.isEnable }, id: \.name){ eca in ForEach(ecaData.ecaArea.map{ $0.1 }.filter{ $0.isEnable }.sorted{ $0.id ?? 0 < $1.id ?? 0 }, id: \.name){ eca in
VStack { VStack {
HStack { HStack {
//ECA開始・終了ボタン
Button { Button {
for runningEca in ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }{ for runningEca in ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }{
edittingEcaArea = runningEca edittingEcaArea = runningEca
...@@ -52,7 +53,7 @@ struct TaskSwitchingMenuView: View { ...@@ -52,7 +53,7 @@ struct TaskSwitchingMenuView: View {
.font(FontStyle.DefaultText.font) .font(FontStyle.DefaultText.font)
.foregroundColor(ColorSet.Body.color) .foregroundColor(ColorSet.Body.color)
.onTapGesture { .onTapGesture {
ecaData.foucusEca = eca.name ecaData.focusEca = eca.name
} }
Spacer() Spacer()
......
...@@ -19,6 +19,7 @@ enum MenuPath: String, Hashable{ ...@@ -19,6 +19,7 @@ enum MenuPath: String, Hashable{
case Help case Help
case AboutApp case AboutApp
case ContactUs case ContactUs
case SignOut
var title: String{ var title: String{
switch self { switch self {
...@@ -42,12 +43,15 @@ enum MenuPath: String, Hashable{ ...@@ -42,12 +43,15 @@ enum MenuPath: String, Hashable{
"About this App" "About this App"
case .ContactUs: case .ContactUs:
"Contact Us" "Contact Us"
case .SignOut:
"Sign Out"
} }
} }
} }
struct MenuView: View { struct MenuView: View {
@State var path: [MenuPath] = [] @State var path: [MenuPath] = []
@Binding var isSignout: Bool
var body: some View { var body: some View {
NavigationStack(path: $path){ NavigationStack(path: $path){
...@@ -56,10 +60,10 @@ struct MenuView: View { ...@@ -56,10 +60,10 @@ struct MenuView: View {
HStack { HStack {
VStack(alignment: .leading, spacing: 10){ VStack(alignment: .leading, spacing: 10){
Text(SharingData.my.company) Text("Group")
.font(FontStyle.TitleL.font) .font(FontStyle.TitleL.font)
.foregroundColor(ColorSet.Body.color) .foregroundColor(ColorSet.Body.color)
Text("Company name general") Text(SharingData.my.company)
.font(FontStyle.EmphasisText.font) .font(FontStyle.EmphasisText.font)
.foregroundColor(ColorSet.BodyDescriptiion.color) .foregroundColor(ColorSet.BodyDescriptiion.color)
} }
...@@ -70,12 +74,10 @@ struct MenuView: View { ...@@ -70,12 +74,10 @@ struct MenuView: View {
Divider() Divider()
.background(ColorSet.LineColor04.color) .background(ColorSet.LineColor04.color)
Button{ Button{
path.append(.Manual) path.append(.Manual)
}label: { }label: {
MenuContentView(content: .Manual) MenuContentView(content: .Manual)
} }
Button{ Button{
...@@ -90,6 +92,12 @@ struct MenuView: View { ...@@ -90,6 +92,12 @@ struct MenuView: View {
MenuContentView(content: .Setting) MenuContentView(content: .Setting)
} }
Button{
isSignout = true
}label: {
MenuContentView(content: .SignOut)
}
Spacer() Spacer()
} }
.background(ColorSet.BackgroundPrimary.color) .background(ColorSet.BackgroundPrimary.color)
...@@ -120,10 +128,20 @@ struct MenuView: View { ...@@ -120,10 +128,20 @@ struct MenuView: View {
} }
} }
.alert(isPresented: $isSignout) {
return Alert(title: Text("Sign Out"),
message: Text("Are you sure?"),
primaryButton: .default(Text("Yes"), action: {
Preferences.Id = ""
Preferences.Password = ""
Preferences.UserName = ""
}), secondaryButton: .cancel(Text("No")))
}
} }
} }
} }
#Preview { #Preview {
MenuView() MenuView(isSignout: .constant(false))
} }
...@@ -72,12 +72,16 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M ...@@ -72,12 +72,16 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
MSNotificationHub.start(connectionString: HttpRequestType.ConnectionString.rawValue, hubName: HttpRequestType.HubName.rawValue) MSNotificationHub.start(connectionString: HttpRequestType.ConnectionString.rawValue, hubName: HttpRequestType.HubName.rawValue)
let notification = notificationTags() // let notification = notificationTags()
notification.addTags() // notification.addTags()
// addTags() self.addTags()
// let testTag = "aaa"
// MSNotificationHub.addTags([testTag])
} }
} }
DispatchQueue.main.async {
application.registerForRemoteNotifications() application.registerForRemoteNotifications()
}
return true return true
} }
...@@ -92,23 +96,34 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M ...@@ -92,23 +96,34 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
func addTags() { func addTags() {
if Preferences.shipId != 0 { if Preferences.shipId != 0 {
let shipId = String(Preferences.shipId) let shipId = String(Preferences.shipId)
let testTag = "aaa"
let routeTag = "route-" + shipId let routeTag = "route-" + shipId
let bamTag = "bam-" + shipId let bamTag = "bam-" + shipId
let taskAlertTag = "taskalert-" + shipId let taskAlertTag = "taskalert-" + shipId
let sailassistTag = "sailassist-" + shipId let sailassistTag = "sailassist-" + shipId
MSNotificationHub.addTags([testTag, routeTag, bamTag, taskAlertTag, sailassistTag]) // MSNotificationHub.addTags([routeTag, bamTag, taskAlertTag, sailassistTag])
MSNotificationHub.addTags([routeTag])
} }
} }
// Push通知を受信した時(サイレントプッシュ)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print(debug: "called") print(debug: "called")
// Forward to MSNotificationHub // Forward to MSNotificationHub
MSNotificationHub.didReceiveRemoteNotification(userInfo) MSNotificationHub.didReceiveRemoteNotification(userInfo)
// Complete handling the notification // Complete handling the notificationposition
completionHandler(.noData) completionHandler(.noData)
// guard let data = userInfo["data"] as? [String: Any],
// let newTitle = data["newTitle"] as? String,
// let newBody = data["newBody"] as? String else {
// completionHandler(.noData)
// return
// }
// // ローカル通知で表示するタイトルとメッセージを変更する
// showLocalNotification(identifier: "SilentPush", title: newTitle, body: newBody)
// completionHandler(.newData)
} }
func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) { func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) {
...@@ -122,8 +137,19 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M ...@@ -122,8 +137,19 @@ class AppDelegate: NSObject, UIApplicationDelegate ,MSNotificationHubDelegate, M
let alertController = UIAlertController(title: title, message: body, preferredStyle: .alert) let alertController = UIAlertController(title: title, message: body, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .cancel)) alertController.addAction(UIAlertAction(title: "OK", style: .cancel))
// self.present(alertController, animated: true) // self.present(alertController, animated: true)
}
}
// APNs 登録成功時に呼ばれる
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
print("デバイストークン : \(token)")
} }
// APNs 登録失敗時に呼ばれる
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("APNs 登録に失敗しました : \(error.localizedDescription)")
} }
} }
...@@ -134,7 +160,33 @@ extension AppDelegate: UNUserNotificationCenterDelegate { ...@@ -134,7 +160,33 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo let userInfo = notification.request.content.userInfo
print(debug: userInfo) print(debug: userInfo)
if !userInfo.isEmpty {
guard let senTypeStr = userInfo["sendType"] as? String else {
completionHandler([.badge, .sound, .banner, .list])
return
}
// switch PushNotificationTypes.SendType(Int32(sendTypeStr) ?? -1){
// case .NewChatMessage:
// //foreground時、通知の内容種別がチャットなら通知を表示しない
// let semaphore = DispatchSemaphore(value: 0)
// SessionManager().prepareSession(semaphore: semaphore)
// let sessionGetWatchingApp = SessionGetWatchingApp()
// let sessionGetWatcherApp = SessionGetWatcherApp()
//
// DispatchQueue(label: "WebAppRequest").async {
// semaphore.wait()
// sessionGetWatchingApp.ErrCnt = 0
// sessionGetWatchingApp.RequestGetWatchingApp("arrivedChatPush")
//
// sessionGetWatcherApp.ErrCnt = 0
// sessionGetWatcherApp.RequestGetWatcherApp("arrivedChatPush")
// }
// completionHandler([])
// return
// default:
// break
// }
}
completionHandler([[.banner, .badge, .sound]]) completionHandler([[.banner, .badge, .sound]])
} }
......
...@@ -50,7 +50,6 @@ class ServerSession{ ...@@ -50,7 +50,6 @@ class ServerSession{
do{ do{
if let error = error{ if let error = error{
let err = APIError.clientError
throw APIError.clientError throw APIError.clientError
} }
guard let indata = data, let inresponse = response as? HTTPURLResponse else { guard let indata = data, let inresponse = response as? HTTPURLResponse else {
...@@ -119,7 +118,7 @@ class ServerSession{ ...@@ -119,7 +118,7 @@ class ServerSession{
func deleteJson(_ req_url : URL, completion: @escaping ((Result<Data, APIError>)) -> Void){ func deleteJson(_ req_url : URL, completion: @escaping ((Result<Data, APIError>)) -> Void){
var req = URLRequest(url: req_url) var req = URLRequest(url: req_url)
req.httpMethod = "DELTE" req.httpMethod = "DELETE"
req.addValue("application/json", forHTTPHeaderField: "Content-Type") req.addValue("application/json", forHTTPHeaderField: "Content-Type")
req.timeoutInterval = 20 // タイムアウト3秒 → Amedasでタイムアウトエラー20秒に変更 req.timeoutInterval = 20 // タイムアウト3秒 → Amedasでタイムアウトエラー20秒に変更
......
...@@ -118,7 +118,7 @@ class SharingData{ ...@@ -118,7 +118,7 @@ class SharingData{
static var eca = Eca() static var eca = Eca()
class Eca: ObservableObject{ class Eca: ObservableObject{
@Published var ecaArea: Dictionary<String, RegisteredEca> = [:] @Published var ecaArea: Dictionary<String, RegisteredEca> = [:]
@Published var foucusEca: String? = nil @Published var focusEca: String? = nil
@Published var isShowEcaAlert: Bool = false @Published var isShowEcaAlert: Bool = false
func setEcaArea(key: String, value: RegisteredEca) { func setEcaArea(key: String, value: RegisteredEca) {
...@@ -241,6 +241,7 @@ class SharingData{ ...@@ -241,6 +241,7 @@ class SharingData{
static var pushHistory = PushHistory() static var pushHistory = PushHistory()
class PushHistory: ObservableObject{ class PushHistory: ObservableObject{
@Published var pushHistoryData: Dictionary<Int, ResPushHistory> = [:] @Published var pushHistoryData: Dictionary<Int, ResPushHistory> = [:]
@Published var focusPushHistory: Int? = nil
func setPushHistory(key: Int, value: ResPushHistory) { func setPushHistory(key: Int, value: ResPushHistory) {
pushHistoryData.updateValue(value, forKey: key) pushHistoryData.updateValue(value, forKey: key)
......
...@@ -18,11 +18,13 @@ enum Tab: String, CaseIterable{ ...@@ -18,11 +18,13 @@ enum Tab: String, CaseIterable{
} }
} }
struct MainTabView: View { struct MainTabView: View {
@EnvironmentObject var selectedTabModel: SelectedTabModel
@EnvironmentObject private var selectedTabModel: SelectedTabModel
@EnvironmentObject private var sceneDelegate: SceneDelegate @EnvironmentObject private var sceneDelegate: SceneDelegate
@ObservedObject var my = SharingData.my
@State var isSignout = false
@State var isLogin = false
init() { init() {
let appearance: UITabBarAppearance = UITabBarAppearance() let appearance: UITabBarAppearance = UITabBarAppearance()
appearance.backgroundColor = .clear appearance.backgroundColor = .clear
...@@ -44,7 +46,7 @@ struct MainTabView: View { ...@@ -44,7 +46,7 @@ struct MainTabView: View {
NotificationView() NotificationView()
.tag(Tab.alert) .tag(Tab.alert)
MenuView() MenuView(isSignout: $isSignout)
.tag(Tab.menu) .tag(Tab.menu)
} }
.hideNativeTabBar() .hideNativeTabBar()
...@@ -103,11 +105,9 @@ struct CustomTabBar: View { ...@@ -103,11 +105,9 @@ struct CustomTabBar: View {
} message: { } message: {
Text("Do you change an emargency mode?") Text("Do you change an emargency mode?")
} }
} }
} }
#Preview { #Preview {
MainTabView() MainTabView()
.environmentObject(SelectedTabModel()) .environmentObject(SelectedTabModel())
......
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