Commit 866c9797 authored by shigemi miura's avatar shigemi miura

QRコードでのログイン対応

画像ファイルの日本語削除
parent 6bbe751a
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "h1_signinのコピー.svg", "filename" : "h1_signin_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "logo_signinのコピー.svg", "filename" : "logo_signin_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "passwordのコピー.svg", "filename" : "password_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "chatのコピー3.svg", "filename" : "chat.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "chatのコピー.svg", "filename" : "chat_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "chatのコピー2.svg", "filename" : "chat.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "navigation_menuのコピー3.svg", "filename" : "navigation_menu.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "navigation_menuのコピー.svg", "filename" : "navigation_menu_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "navigation_menuのコピー2.svg", "filename" : "navigation_menu.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "navigation_notificationのコピー3.svg", "filename" : "navigation_notification.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "navigation_notificationのコピー.svg", "filename" : "navigation_notification_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "navigation_notificationのコピー2.svg", "filename" : "navigation_notification.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "navigation_taskのコピー3.svg", "filename" : "navigation_task.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
"value" : "dark" "value" : "dark"
} }
], ],
"filename" : "navigation_taskのコピー.svg", "filename" : "navigation_task_Dark.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "navigation_taskのコピー2.svg", "filename" : "navigation_task.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
{ {
"images" : [ "images" : [
{ {
"filename" : "閉じる.svg", "filename" : "close.svg",
"idiom" : "universal", "idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
......
...@@ -9,10 +9,9 @@ import SwiftUI ...@@ -9,10 +9,9 @@ import SwiftUI
struct ContentView: View { struct ContentView: View {
@State var isLogin = false//ContentView.LoginCheck() @State var isLogin = false//ContentView.LoginCheck()
@EnvironmentObject private var sceneDelegate: SceneDelegate @EnvironmentObject private var sceneDelegate: SceneDelegate
var selectedTabModel = SelectedTabModel() var selectedTabModel = SelectedTabModel()
var body: some View { var body: some View {
NavigationStack{ NavigationStack{
MainTabView() MainTabView()
...@@ -33,15 +32,6 @@ struct ContentView: View { ...@@ -33,15 +32,6 @@ struct ContentView: View {
LoginView(isLogin: $isLogin) LoginView(isLogin: $isLogin)
}) })
} }
///ログイン認証が必要かチェック
private static func LoginCheck() -> Bool {
let lastUnixTime = Preferences.lastLoginDate_Int64 ?? 0
let lastDate = DateTextLib.UnixTime2Date(lastUnixTime)
let interval = Date.now.timeIntervalSince(lastDate)
return interval < 2592000
}
} }
#Preview { #Preview {
......
...@@ -8,25 +8,6 @@ ...@@ -8,25 +8,6 @@
import Foundation import Foundation
import CoreLocation import CoreLocation
//class RegisteredEca {
// var id: UInt32 = 0
// var isEnable: Bool = false //ECA有効
// var isRunning: Bool = false //ECA実行中
// var name: String = "" //ECA名称
// var swNotice: UInt32 = 6 //ECA通知[NM]
// var swStart: UInt32 = 5 //ECA開始[NM]
// var swFinish: UInt32 = 4 //ECA終了[NM]
// var datetime: String = "" //時刻(UTC ISO8601準拠)
// var color: String = "" //ライン色(ARGB)
// var width: UInt32 = 1 //ライン幅
// var points: [CLLocationCoordinate2D] = []
//
// init?( ecaName: String ) {
// self.name = ecaName
// }
//}
class RegisteredEca: ObservableObject { class RegisteredEca: ObservableObject {
@Published var id: UInt32 = 0 @Published var id: UInt32 = 0
@Published var isEnable: Bool = false //ECA有効 @Published var isEnable: Bool = false //ECA有効
......
...@@ -7,14 +7,21 @@ ...@@ -7,14 +7,21 @@
import Foundation import Foundation
// TODO: サイトのアドレスを変更
#if DEBUG #if DEBUG
//MARK: デバッグサーバー用 //MARK: デバッグサーバー用
enum HttpRequestType : String { enum HttpRequestType : String {
case RegisterLogin = "https://ssv-canary-web.azurewebsites.net/applogin" case RegisterLogin = "https://ssv-canary-web.azurewebsites.net/applogin"
case SitePolicy = "https://www.google.co.jp/"
case CookiePolicy = "https://www.google.co.jp/2"
case PrivacyPolicy = "https://www.google.co.jp/3"
} }
#else #else
//MARK: 運用サーバー用 //MARK: 運用サーバー用
enum HttpRequestType : String { enum HttpRequestType : String {
case RegisterLogin = "https://ssv-canary-web.azurewebsites.net/applogin" case RegisterLogin = "https://ssv-canary-web.azurewebsites.net/applogin"
case SitePolicy = "https://www.google.co.jp/"
case CookiePolicy = "https://www.google.co.jp/2"
case PrivacyPolicy = "https://www.google.co.jp/3"
} }
#endif #endif
...@@ -87,12 +87,12 @@ enum TextInputType{ ...@@ -87,12 +87,12 @@ enum TextInputType{
return constraint return constraint
case .UserId: case .UserId:
var constraint = TextConstraint() var constraint = TextConstraint()
constraint.charSet = .Alphanumeric constraint.charSet = .FreeCharset
constraint.textStructure = "^S[a-zA-Z]{1}[0-9]{8}$" constraint.textStructure = "^[!-~]{30}$"
var lengthConst = LengthConstraint() var lengthConst = LengthConstraint()
lengthConst.lcType = .OnlyEqual lengthConst.lcType = .OnlyEqual
lengthConst.lcEnableEmpty = false lengthConst.lcEnableEmpty = false
lengthConst.lcSize.append(10) lengthConst.lcSize.append(30)
constraint.length = lengthConst constraint.length = lengthConst
return constraint return constraint
} }
......
...@@ -16,6 +16,11 @@ enum LoginViewMode: String{ ...@@ -16,6 +16,11 @@ enum LoginViewMode: String{
case InputUserName case InputUserName
} }
enum AlertType: String {
case loginFailure
case Expired
}
class LoginViewParam: ObservableObject{ class LoginViewParam: ObservableObject{
@Published var shipId: String = "" @Published var shipId: String = ""
@Published var password: String = "" @Published var password: String = ""
...@@ -23,12 +28,16 @@ class LoginViewParam: ObservableObject{ ...@@ -23,12 +28,16 @@ class LoginViewParam: ObservableObject{
} }
struct LoginView: View { struct LoginView: View {
@Binding var isLogin: Bool
@State var isQrRead: Bool = false @State var isQrRead: Bool = false
@State var viewMode: LoginViewMode = .SelectType @State var viewMode: LoginViewMode = .SelectType
@Binding var isLogin: Bool @State var isProgressView = false
@State var isAlert = false
@State var alertType: AlertType = .loginFailure
@ObservedObject var scannerViewModel = ScannerViewModel() @ObservedObject var scannerViewModel = ScannerViewModel()
@State var loginViewParam = LoginViewParam() @State var loginViewParam = LoginViewParam()
var sessionLogin = SessionLogin()
var body: some View { var body: some View {
ZStack{ ZStack{
Triangle() Triangle()
...@@ -41,45 +50,106 @@ struct LoginView: View { ...@@ -41,45 +50,106 @@ struct LoginView: View {
.resizable() .resizable()
.scaledToFit() .scaledToFit()
.frame(width: 135, height: 66.85) .frame(width: 135, height: 66.85)
Image("h1_signin") Image("h1_signin")
.frame(width: 250, height: 21.94) .frame(width: 250, height: 21.94)
} }
.padding(.top, 64) .padding(.top, 64)
Spacer() Spacer()
switch viewMode{ if !isProgressView {
case .SelectType: switch viewMode{
LoginTypeSelectView(isQrRead: $scannerViewModel.isShowing, viewMode: $viewMode) case .SelectType:
case .InputIdPassword: LoginTypeSelectView(isQrRead: $scannerViewModel.isShowing, viewMode: $viewMode)
InputIdPassWordView(viewMode: $viewMode, param: $loginViewParam) case .InputIdPassword:
case .InputUserName: InputIdPassWordView(viewMode: $viewMode, param: $loginViewParam)
InputUserNameView(isLogin: $isLogin, param: $loginViewParam, viewMode: $viewMode) case .InputUserName:
InputUserNameView(isLogin: $isLogin, param: $loginViewParam, viewMode: $viewMode, isProgressView: $isProgressView, isAlert: $isAlert, alertType: $alertType)
}
} else {
Text("Login Check").padding()
ProgressView()
} }
Spacer() Spacer()
VStack(spacing: 40){ VStack(spacing: 40){
VStack(spacing: 30) { VStack(spacing: 30) {
// TODO: サイトのアドレスを変更 if !isProgressView {
Link("Site policy", destination: URL(string: "https://www.google.co.jp/")!) Link("Site policy", destination: URL(string: HttpRequestType.SitePolicy.rawValue)!)
Link("Cookie policy", destination: URL(string: "https://www.google.co.jp/")!) Link("Cookie policy", destination: URL(string: HttpRequestType.CookiePolicy.rawValue)!)
Link("Privacy policy", destination: URL(string: "https://www.google.co.jp/")!) Link("Privacy policy", destination: URL(string: HttpRequestType.PrivacyPolicy.rawValue)!)
} else {
EmptyView()
}
} }
.font(FontStyle.SupplementText.font) .font(FontStyle.SupplementText.font)
.foregroundColor(ColorSet.Body.color) .foregroundColor(ColorSet.Body.color)
Text("Ver. \(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String)") Text("Ver. \(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String)")
.font(FontStyle.VersionText.font) .font(FontStyle.VersionText.font)
.foregroundColor(ColorSet.BodyDescriptiion.color) .foregroundColor(ColorSet.BodyDescriptiion.color)
} }
.padding(.bottom, 30) .padding(.bottom, 30)
.alert(isPresented: $isAlert) {
switch alertType {
case .loginFailure:
return Alert(title: Text("error"),
message: Text("Login failure."),
dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
)
case .Expired:
return Alert(title: Text("error"),
message: Text("Expired."),
dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
)
}
}
} }
} }
.fullScreenCover(isPresented: $scannerViewModel.isShowing, content: { .fullScreenCover(isPresented: $scannerViewModel.isShowing, onDismiss: {LoginCheckQR()}, content: {
QRReadView(viewMode: .constant(.SelectType), viewModel: scannerViewModel) QRReadView(viewMode: .constant(.SelectType), viewModel: scannerViewModel)
}) })
.onAppear() {
LoginCheck()
}
}
func LoginCheckQR() -> () {
loginViewParam.shipId = Preferences.ShipId
loginViewParam.password = Preferences.ShipPassword
viewMode = .InputUserName
}
func LoginCheck() -> () {
let lastUnixTime = Preferences.lastLoginDate_Int64 ?? 0
let lastDate = DateTextLib.UnixTime2Date(lastUnixTime)
let interval = Date.now.timeIntervalSince(lastDate)
if interval < 2592000 {
if Preferences.ShipId != "" && Preferences.ShipPassword != "" && Preferences.UserName != ""{
isProgressView = true
let login = ReqLogin(Id: Preferences.ShipId, Password: Preferences.ShipPassword)
sessionLogin.RequestLogin(login, completion: responseLogin)
}
}
}
func responseLogin(result: Result<Data, APIError>) {
print(debug: "calld")
switch result {
case .success(let resultData):
let jsonstr = String(data: resultData, encoding: .utf8)!
Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
isLogin = true
case .failure(let errorCode):
isLogin = false
isAlert = true
alertType = .loginFailure
break
}
isProgressView = false
} }
} }
......
...@@ -12,8 +12,10 @@ struct InputUserNameView: View { ...@@ -12,8 +12,10 @@ struct InputUserNameView: View {
@Binding var isLogin: Bool @Binding var isLogin: Bool
@Binding var param: LoginViewParam @Binding var param: LoginViewParam
@Binding var viewMode : LoginViewMode @Binding var viewMode : LoginViewMode
@State private var isAlert = false @Binding var isProgressView : Bool
@State private var alertType: AlertType = .userNameEmpty @Binding var isAlert : Bool
@Binding var alertType: AlertType
@State private var isEmptyAlert = false
let itemHPadding: Double = 16 let itemHPadding: Double = 16
let dialogBottomPadding: Double = 32 let dialogBottomPadding: Double = 32
let textFieldHeight: Double = 40 let textFieldHeight: Double = 40
...@@ -21,11 +23,6 @@ struct InputUserNameView: View { ...@@ -21,11 +23,6 @@ struct InputUserNameView: View {
let dialogHeight: CGFloat = 250 let dialogHeight: CGFloat = 250
let dialogWidth = UIScreen.main.bounds.width - 32 let dialogWidth = UIScreen.main.bounds.width - 32
enum AlertType {
case userNameEmpty
case loginFailure
}
var body: some View { var body: some View {
HStack { HStack {
Spacer() Spacer()
...@@ -60,20 +57,15 @@ struct InputUserNameView: View { ...@@ -60,20 +57,15 @@ struct InputUserNameView: View {
} }
.frame(height: inputAreaHeight) .frame(height: inputAreaHeight)
Spacer() Spacer()
Button(action: { Button(action: {
if param.userName.isEmpty { if param.userName.isEmpty {
isAlert = true isEmptyAlert = true
alertType = .userNameEmpty
} else { } else {
//TODO: API通信 ログイン認証処理
print(debug: "signin: id(\(param.shipId)), pass(\(param.password)), name(\(param.userName))") print(debug: "signin: id(\(param.shipId)), pass(\(param.password)), name(\(param.userName))")
isAlert = false isAlert = false
// param.shipId = "jrcetest01@gmail.com" isProgressView = true
// param.password = "JRCEtest01_"
let login = ReqLogin(Id: param.shipId, Password: param.password) let login = ReqLogin(Id: param.shipId, Password: param.password)
sessionLogin.RequestLogin(login, completion: responseLogin) sessionLogin.RequestLogin(login, completion: responseLogin)
} }
...@@ -84,19 +76,10 @@ struct InputUserNameView: View { ...@@ -84,19 +76,10 @@ struct InputUserNameView: View {
.foregroundColor(ColorSet.ButtonText.color) .foregroundColor(ColorSet.ButtonText.color)
.background(ColorSet.PrimaryActiveIcon.color) .background(ColorSet.PrimaryActiveIcon.color)
}) })
.alert(isPresented: $isAlert) { .alert(isPresented: $isEmptyAlert) {
switch alertType { return Alert(title: Text("error"),
case .userNameEmpty: message: Text("User Nmae not entered.")
return Alert(title: Text("error"), )
message: Text("User Nmae not entered.")
)
case .loginFailure:
return Alert(title: Text("error"),
message: Text("Login failure."),
dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
)
}
} }
Spacer() Spacer()
.frame(height: dialogBottomPadding) .frame(height: dialogBottomPadding)
...@@ -113,15 +96,16 @@ struct InputUserNameView: View { ...@@ -113,15 +96,16 @@ struct InputUserNameView: View {
print(debug: "calld") print(debug: "calld")
switch result { switch result {
case .success(let resultData): case .success(let resultData):
let jsonstr = String(data: resultData, encoding: .utf8)! let serverSession = ServerSession()
let resjson = serverSession.fromJSON(resultData: resultData, resltType: ResLogin.self)
Preferences.ShipId = param.shipId Preferences.ShipId = param.shipId
Preferences.ShipPassword = param.password Preferences.ShipPassword = param.password
Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date()) Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
isProgressView = false
isLogin = true isLogin = true
isAlert = false isAlert = false
case .failure(let errorCode): case .failure(let errorCode):
param.shipId = "" isProgressView = false
param.password = ""
isLogin = false isLogin = false
isAlert = true isAlert = true
alertType = .loginFailure alertType = .loginFailure
...@@ -131,5 +115,5 @@ struct InputUserNameView: View { ...@@ -131,5 +115,5 @@ struct InputUserNameView: View {
} }
#Preview { #Preview {
InputUserNameView(isLogin: .constant(false), param: .constant(LoginViewParam()), viewMode: .constant(.InputIdPassword)) InputUserNameView(isLogin: .constant(false), param: .constant(LoginViewParam()), viewMode: .constant(.InputIdPassword), isProgressView: .constant(false), isAlert: .constant(false), alertType: .constant(.loginFailure))
} }
...@@ -17,7 +17,7 @@ struct LoginTypeSelectView: View{ ...@@ -17,7 +17,7 @@ struct LoginTypeSelectView: View{
Button(action: { Button(action: {
isQrRead = true isQrRead = true
}, label: { }, label: {
Text("QRを読み込む") Text("Read the QR code")
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.frame(height: 50) .frame(height: 50)
.foregroundColor(ColorSet.ButtonText.color) .foregroundColor(ColorSet.ButtonText.color)
...@@ -29,7 +29,7 @@ struct LoginTypeSelectView: View{ ...@@ -29,7 +29,7 @@ struct LoginTypeSelectView: View{
print("change mode") print("change mode")
viewMode = .InputIdPassword viewMode = .InputIdPassword
}, label: { }, label: {
Text("Ship ID/Passwordを入力") Text("Enter Ship ID / Password")
.underline() .underline()
.font(FontStyle.SupplementText.font) .font(FontStyle.SupplementText.font)
.foregroundColor(ColorSet.ToggleBackGround.color) .foregroundColor(ColorSet.ToggleBackGround.color)
......
...@@ -64,10 +64,11 @@ struct QrCodeScannerView: UIViewRepresentable { ...@@ -64,10 +64,11 @@ struct QrCodeScannerView: UIViewRepresentable {
uiView.layer.addSublayer(previewLayer) uiView.layer.addSublayer(previewLayer)
uiView.previewLayer = previewLayer uiView.previewLayer = previewLayer
session.startRunning() DispatchQueue.global(qos: .background).async {
session.startRunning()
}
} }
} }
} }
func makeUIView(context: UIViewRepresentableContext<QrCodeScannerView>) -> QrCodeScannerView.UIViewType { func makeUIView(context: UIViewRepresentableContext<QrCodeScannerView>) -> QrCodeScannerView.UIViewType {
......
...@@ -6,19 +6,30 @@ ...@@ -6,19 +6,30 @@
// //
import Foundation import Foundation
import SwiftUI
class ScannerViewModel: ObservableObject { class ScannerViewModel: ObservableObject {
let scanInterval: Double = 1.0 /// QRコードを読み取る時間間隔
/// QRコードを読み取る時間間隔
let scanInterval: Double = 1.0
@Published var lastQrCode: String = "QRコード" @Published var lastQrCode: String = "QRコード"
@Published var isShowing: Bool = false @Published var isShowing: Bool = false
/// QRコード読み取り時に実行される。 /// QRコード読み取り時に実行される。
func onFoundQrCode(_ code: String) { func onFoundQrCode(_ code: String) {
self.lastQrCode = code do {
self.lastQrCode = code
let decoder = JSONDecoder()
let jsonData = self.lastQrCode.data(using: .utf8)!
let resjson: ReqLogin = try decoder.decode(ReqLogin.self, from: jsonData)
Preferences.ShipId = resjson.Id
Preferences.ShipPassword = resjson.Password
Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
} catch {
print(debug: "decodeエラー")
Preferences.ShipId = ""
Preferences.ShipPassword = ""
}
isShowing = false isShowing = 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