diff --git a/Linphone.xcodeproj/project.pbxproj b/Linphone.xcodeproj/project.pbxproj index fe845df79..f4fe4d61b 100644 --- a/Linphone.xcodeproj/project.pbxproj +++ b/Linphone.xcodeproj/project.pbxproj @@ -18,6 +18,8 @@ D719ABC92ABC6FD700B41C10 /* CoreContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABC82ABC6FD700B41C10 /* CoreContext.swift */; }; D719ABCC2ABC769C00B41C10 /* AssistantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABCB2ABC769C00B41C10 /* AssistantView.swift */; }; D719ABCF2ABC779A00B41C10 /* AccountLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABCE2ABC779A00B41C10 /* AccountLoginViewModel.swift */; }; + D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */; }; + D748BF2E2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */; }; D74C9CF82ACACECE0021626A /* WelcomePage1Fragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CF72ACACECE0021626A /* WelcomePage1Fragment.swift */; }; D74C9CFA2ACACF2D0021626A /* WelcomePage2Fragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CF92ACACF2D0021626A /* WelcomePage2Fragment.swift */; }; D74C9CFC2ACACF370021626A /* WelcomePage3Fragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CFB2ACACF370021626A /* WelcomePage3Fragment.swift */; }; @@ -53,6 +55,8 @@ D719ABC82ABC6FD700B41C10 /* CoreContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreContext.swift; sourceTree = ""; }; D719ABCB2ABC769C00B41C10 /* AssistantView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssistantView.swift; sourceTree = ""; }; D719ABCE2ABC779A00B41C10 /* AccountLoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountLoginViewModel.swift; sourceTree = ""; }; + D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountLoginFragment.swift; sourceTree = ""; }; + D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountWarningFragment.swift; sourceTree = ""; }; D74C9CF72ACACECE0021626A /* WelcomePage1Fragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomePage1Fragment.swift; sourceTree = ""; }; D74C9CF92ACACF2D0021626A /* WelcomePage2Fragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomePage2Fragment.swift; sourceTree = ""; }; D74C9CFB2ACACF370021626A /* WelcomePage3Fragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomePage3Fragment.swift; sourceTree = ""; }; @@ -275,6 +279,8 @@ children = ( D7DA67612ACCB2FA00E95002 /* LoginFragment.swift */, D7DA67632ACCB31700E95002 /* ProfileModeFragment.swift */, + D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */, + D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */, ); path = Fragments; sourceTree = ""; @@ -411,6 +417,8 @@ D7A2EDD62AC18115005D90FC /* SharedMainViewModel.swift in Sources */, D7A03FC62ACC458A0081A588 /* SplashScreen.swift in Sources */, D7A03FC02ACC2E390081A588 /* HistoryView.swift in Sources */, + D748BF2E2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift in Sources */, + D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */, D74C9CF82ACACECE0021626A /* WelcomePage1Fragment.swift in Sources */, D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */, D7DA67642ACCB31700E95002 /* ProfileModeFragment.swift in Sources */, diff --git a/Linphone/Assets.xcassets/Conversation.imageset/Contents.json b/Linphone/Assets.xcassets/Conversation.imageset/Contents.json new file mode 100644 index 000000000..ac4b400d4 --- /dev/null +++ b/Linphone/Assets.xcassets/Conversation.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Conversation.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Linphone/Assets.xcassets/Conversation.imageset/Conversation.svg b/Linphone/Assets.xcassets/Conversation.imageset/Conversation.svg new file mode 100644 index 000000000..27d2bfb1b --- /dev/null +++ b/Linphone/Assets.xcassets/Conversation.imageset/Conversation.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Linphone/Assets.xcassets/Linphone.imageset/Contents.json b/Linphone/Assets.xcassets/Linphone.imageset/Contents.json index e87351a00..ff043ddb2 100644 --- a/Linphone/Assets.xcassets/Linphone.imageset/Contents.json +++ b/Linphone/Assets.xcassets/Linphone.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Linphone.svg", + "filename" : "linphone.svg", "idiom" : "universal", "scale" : "1x" }, diff --git a/Linphone/Assets.xcassets/caret-down.imageset/Contents.json b/Linphone/Assets.xcassets/caret-down.imageset/Contents.json new file mode 100644 index 000000000..cc33c146a --- /dev/null +++ b/Linphone/Assets.xcassets/caret-down.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "caret-down.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Linphone/Assets.xcassets/caret-down.imageset/caret-down.svg b/Linphone/Assets.xcassets/caret-down.imageset/caret-down.svg new file mode 100644 index 000000000..42f37b716 --- /dev/null +++ b/Linphone/Assets.xcassets/caret-down.imageset/caret-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/caret-left.imageset/Contents.json b/Linphone/Assets.xcassets/caret-left.imageset/Contents.json new file mode 100644 index 000000000..a5f91ffff --- /dev/null +++ b/Linphone/Assets.xcassets/caret-left.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "caret-left.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Linphone/Assets.xcassets/caret-left.imageset/caret-left.svg b/Linphone/Assets.xcassets/caret-left.imageset/caret-left.svg new file mode 100644 index 000000000..a3a1e39a6 --- /dev/null +++ b/Linphone/Assets.xcassets/caret-left.imageset/caret-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Linphone/Assets.xcassets/video-call.imageset/Contents.json b/Linphone/Assets.xcassets/video-call.imageset/Contents.json new file mode 100644 index 000000000..0617b9467 --- /dev/null +++ b/Linphone/Assets.xcassets/video-call.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "VideoCall.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Linphone/Assets.xcassets/video-call.imageset/VideoCall.svg b/Linphone/Assets.xcassets/video-call.imageset/VideoCall.svg new file mode 100644 index 000000000..5bfd91cd2 --- /dev/null +++ b/Linphone/Assets.xcassets/video-call.imageset/VideoCall.svg @@ -0,0 +1,3 @@ + + + diff --git a/Linphone/Localizable.xcstrings b/Linphone/Localizable.xcstrings index 24e0bd2b5..9fbfb1302 100644 --- a/Linphone/Localizable.xcstrings +++ b/Linphone/Localizable.xcstrings @@ -6,6 +6,12 @@ }, " or " : { + }, + "[Forgotten password?](https://subscribe.linphone.org/)" : { + + }, + "[linphone.org/contact](https://linphone.org/contact)" : { + }, "[nos conditions d’utilisation](https://linphone.org/general-terms)" : { @@ -106,6 +112,9 @@ }, "Contacts View" : { + }, + "Continue" : { + }, "Default" : { @@ -115,6 +124,12 @@ }, "Deny all" : { + }, + "Display Name" : { + + }, + "Domain" : { + }, "En continuant, vous acceptez ces conditions, %@ et %@." : { "localizations" : { @@ -126,10 +141,13 @@ } } }, - "Forgotten password?" : { + "History View" : { }, - "History View" : { + "I prefere create an account" : { + + }, + "I understand" : { }, "Interoperable" : { @@ -169,6 +187,9 @@ } } } + }, + "Personnalize your profil mode" : { + }, "Register" : { @@ -178,9 +199,15 @@ }, "Sécurisé" : { + }, + "sip.linphone.org" : { + }, "Skip" : { + }, + "Some features require a Linphone account, such as group messaging, video conferences...\n\nThese features are hidden when you register with a third party SIP account.\n\nTo enable it in a commercial projet, please contact us. " : { + }, "Start" : { @@ -199,12 +226,21 @@ }, "to Linphone" : { + }, + "Transport" : { + + }, + "UDP" : { + }, "Une application de communication **sécurisée**, **open source** et **française**." : { }, "Une application open source et un **service gratuit** depuis **2001**." : { + }, + "Use a SIP account" : { + }, "Use SIP Account" : { @@ -231,6 +267,9 @@ }, "Welcome" : { + }, + "You will change this mode later" : { + } }, "version" : "1.0" diff --git a/Linphone/UI/Assistant/AssistantView.swift b/Linphone/UI/Assistant/AssistantView.swift index 8eb653895..a974cce31 100644 --- a/Linphone/UI/Assistant/AssistantView.swift +++ b/Linphone/UI/Assistant/AssistantView.swift @@ -21,12 +21,17 @@ import SwiftUI struct AssistantView: View { + @ObservedObject var sharedMainViewModel : SharedMainViewModel + var body: some View { - //LoginFragment(accountLoginViewModel: AccountLoginViewModel()) - ProfileModeFragment() + if sharedMainViewModel.displayProfileMode != true { + LoginFragment(accountLoginViewModel: AccountLoginViewModel(), sharedMainViewModel: sharedMainViewModel) + } else { + ProfileModeFragment(sharedMainViewModel: sharedMainViewModel) + } } } #Preview { - AssistantView() + AssistantView(sharedMainViewModel: SharedMainViewModel()) } diff --git a/Linphone/UI/Assistant/Fragments/LoginFragment.swift b/Linphone/UI/Assistant/Fragments/LoginFragment.swift index ad9c536f6..b1ba24389 100644 --- a/Linphone/UI/Assistant/Fragments/LoginFragment.swift +++ b/Linphone/UI/Assistant/Fragments/LoginFragment.swift @@ -23,6 +23,7 @@ struct LoginFragment: View { @ObservedObject private var coreContext = CoreContext.shared @ObservedObject var accountLoginViewModel : AccountLoginViewModel + @ObservedObject var sharedMainViewModel : SharedMainViewModel @State private var isSecured: Bool = true @@ -30,184 +31,141 @@ struct LoginFragment: View { @FocusState var isPasswordFocused:Bool var body: some View { - GeometryReader { geometry in - ScrollView(.vertical) { - VStack { - ZStack { - Image("mountain") - .resizable() - .scaledToFill() - .frame(width: geometry.size.width, height: 100) - .clipped() - Text("assistant_account_login") - .default_text_style_white_800(styleSize: 20) - .padding(.top, 20) - } - .padding(.top, 35) - .padding(.bottom, 10) - - VStack(alignment: .leading) { - Text(String(localized: "username")+"*") - .default_text_style_700(styleSize: 15) - .padding(.bottom, -5) + NavigationView { + GeometryReader { geometry in + ScrollView(.vertical) { + VStack { + ZStack { + Image("mountain") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 100) + .clipped() + Text("assistant_account_login") + .default_text_style_white_800(styleSize: 20) + .padding(.top, 20) + } + .padding(.top, 35) + .padding(.bottom, 10) - TextField("username", text : $accountLoginViewModel.username) - .default_text_style(styleSize: 15) + VStack(alignment: .leading) { + Text(String(localized: "username")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("username", text : $accountLoginViewModel.username) + .default_text_style(styleSize: 15) + .disabled(coreContext.loggedIn) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isNameFocused) + + Text(String(localized: "password")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + ZStack(alignment: .trailing) { + Group { + if isSecured { + SecureField("password", text: $accountLoginViewModel.passwd) + .default_text_style(styleSize: 15) + .frame(height: 25) + .focused($isPasswordFocused) + } else { + TextField("password", text: $accountLoginViewModel.passwd) + .default_text_style(styleSize: 15) + .frame(height: 25) + .focused($isPasswordFocused) + } + } + Button(action: { + isSecured.toggle() + }) { + Image(self.isSecured ? "eye-slash" : "eye") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20) + } + } .disabled(coreContext.loggedIn) - .frame(height: 25) .padding(.horizontal, 20) .padding(.vertical, 15) .cornerRadius(60) .overlay( RoundedRectangle(cornerRadius: 60) .inset(by: 0.5) - .stroke(isNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) + .stroke(isPasswordFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) ) .padding(.bottom) - .focused($isNameFocused) - - Text(String(localized: "password")+"*") - .default_text_style_700(styleSize: 15) - .padding(.bottom, -5) - - ZStack(alignment: .trailing) { - Group { - if isSecured { - SecureField("password", text: $accountLoginViewModel.passwd) - .default_text_style(styleSize: 15) - .frame(height: 25) - .focused($isPasswordFocused) + + Button(action: { + sharedMainViewModel.displayProfileMode = true + if (self.coreContext.loggedIn){ + self.accountLoginViewModel.unregister() + self.accountLoginViewModel.delete() } else { - TextField("password", text: $accountLoginViewModel.passwd) - .default_text_style(styleSize: 15) - .frame(height: 25) - .focused($isPasswordFocused) + self.accountLoginViewModel.login() } - } - Button(action: { - isSecured.toggle() }) { - Image(self.isSecured ? "eye-slash" : "eye") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.gray_main2_500) - .frame(width: 20, height: 20) - } - } - .disabled(coreContext.loggedIn) - .padding(.horizontal, 20) - .padding(.vertical, 15) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(isPasswordFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) - ) - .padding(.bottom) - - Button(action: { - if (self.coreContext.loggedIn){ - self.accountLoginViewModel.unregister() - self.accountLoginViewModel.delete() - } else { - self.accountLoginViewModel.login() - } - }) { - Text(coreContext.loggedIn ? "Log out" : "assistant_account_login") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - } - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background((accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) ? Color.orange_main_100 : Color.orange_main_500) - .cornerRadius(60) - .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) - .padding(.bottom) - - Button(action: { - - }) { - Text("Forgotten password?") - .underline() - .default_text_style_600(styleSize: 15) - .foregroundStyle(Color.gray_main2_500) - } - .frame(maxWidth: .infinity) - .padding(.bottom, 30) - - HStack { - VStack{ - Divider() - } - Text(" or ") - .default_text_style(styleSize: 15) - .foregroundStyle(Color.gray_main2_500) - VStack{ - Divider() - } - } - .padding(.bottom, 10) - - Button(action: { - - }) { - HStack { - Image("qr-code") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.orange_main_500) - .frame(width: 20, height: 20) - - Text("Scan QR code") - .default_text_style_orange_600(styleSize: 20) + Text(coreContext.loggedIn ? "Log out" : "assistant_account_login") + .default_text_style_white_600(styleSize: 20) .frame(height: 35) + .frame(maxWidth: .infinity) + } + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background((accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) ? Color.orange_main_100 : Color.orange_main_500) + .cornerRadius(60) + .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) + .padding(.bottom) + + HStack { + Text("[Forgotten password?](https://subscribe.linphone.org/)") + .underline() + .tint(Color.gray_main2_600) + .default_text_style_600(styleSize: 15) + .foregroundStyle(Color.gray_main2_500) } .frame(maxWidth: .infinity) - } - .padding(.horizontal, 20) - .padding(.vertical, 10) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(Color.orange_main_500, lineWidth: 1) - ) - .padding(.bottom) - - Button(action: { + .padding(.bottom, 30) - }) { - Text("Use SIP Account") - .default_text_style_orange_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - } - .padding(.horizontal, 20) - .padding(.vertical, 10) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(Color.orange_main_500, lineWidth: 1) - ) - .padding(.bottom) - - HStack(alignment: .center) { - - Spacer() - - Text("Not account yet?") - .default_text_style(styleSize: 15) - .foregroundStyle(Color.gray_main2_700) - .padding(.horizontal, 10) + HStack { + VStack{ + Divider() + } + Text(" or ") + .default_text_style(styleSize: 15) + .foregroundStyle(Color.gray_main2_500) + VStack{ + Divider() + } + } + .padding(.bottom, 10) Button(action: { }) { - Text("Register") - .default_text_style_orange_600(styleSize: 20) - .frame(height: 35) + HStack { + Image("qr-code") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.orange_main_500) + .frame(width: 20, height: 20) + + Text("Scan QR code") + .default_text_style_orange_600(styleSize: 20) + .frame(height: 35) + } + .frame(maxWidth: .infinity) } .padding(.horizontal, 20) .padding(.vertical, 10) @@ -217,13 +175,59 @@ struct LoginFragment: View { .inset(by: 0.5) .stroke(Color.orange_main_500, lineWidth: 1) ) - .padding(.horizontal, 10) + .padding(.bottom) - Spacer() + NavigationLink(destination: { + ThirdPartySipAccountWarningFragment(accountLoginViewModel: accountLoginViewModel) + }, label: { + Text("Use SIP Account") + .default_text_style_orange_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orange_main_500, lineWidth: 1) + ) + .padding(.bottom) + + HStack(alignment: .center) { + + Spacer() + + Text("Not account yet?") + .default_text_style(styleSize: 15) + .foregroundStyle(Color.gray_main2_700) + .padding(.horizontal, 10) + + Button(action: { + + }) { + Text("Register") + .default_text_style_orange_600(styleSize: 20) + .frame(height: 35) + } + .padding(.horizontal, 20) + .padding(.vertical, 10) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orange_main_500, lineWidth: 1) + ) + .padding(.horizontal, 10) + + Spacer() + } + .padding(.bottom) } - .padding(.bottom) + .padding(.horizontal, 20) } - .padding(.horizontal, 20) } } } @@ -231,5 +235,5 @@ struct LoginFragment: View { } #Preview { - LoginFragment(accountLoginViewModel: AccountLoginViewModel()) + LoginFragment(accountLoginViewModel: AccountLoginViewModel(), sharedMainViewModel: SharedMainViewModel()) } diff --git a/Linphone/UI/Assistant/Fragments/ProfileModeFragment.swift b/Linphone/UI/Assistant/Fragments/ProfileModeFragment.swift index 44c0c66ff..447fae4e8 100644 --- a/Linphone/UI/Assistant/Fragments/ProfileModeFragment.swift +++ b/Linphone/UI/Assistant/Fragments/ProfileModeFragment.swift @@ -21,6 +21,8 @@ import SwiftUI struct ProfileModeFragment: View { + @ObservedObject var sharedMainViewModel : SharedMainViewModel + @State var options: Int = 1 @State private var isShowPopup = false @State private var isShowPopupForDefault = true @@ -35,9 +37,12 @@ struct ProfileModeFragment: View { .scaledToFill() .frame(width: geometry.size.width, height: 100) .clipped() - Text("assistant_account_login") + Text("Personnalize your profil mode") .default_text_style_white_800(styleSize: 20) - .padding(.top, 20) + .padding(.top, -10) + Text("You will change this mode later") + .default_text_style_white(styleSize: 15) + .padding(.top, 40) } .padding(.top, 35) .padding(.bottom, 10) @@ -110,12 +115,29 @@ struct ProfileModeFragment: View { .cornerRadius(15) } .padding() + + Spacer() + + Button(action: { + sharedMainViewModel.displayProfileMode = false + }) { + Text("Continue") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + } + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orange_main_500) + .cornerRadius(60) + .padding(.horizontal) } + .frame(minHeight: geometry.size.height) } + if self.isShowPopup { PopupView(isShowPopup: $isShowPopup, title: Text(isShowPopupForDefault ? "Default mode" : "Interoperable mode"), content: Text(isShowPopupForDefault ? "Texte explicatif du default mode : lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula." : "Texte explicatif du interoperable mode : lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula."), titleFirstButton: nil, actionFirstButton: {}, titleSecondButton: Text("Close"), actionSecondButton: {self.isShowPopup.toggle()}) .background(.black.opacity(0.65)) - .edgesIgnoringSafeArea(.all) .onTapGesture { self.isShowPopup.toggle() } @@ -125,5 +147,5 @@ struct ProfileModeFragment: View { } #Preview { - ProfileModeFragment() + ProfileModeFragment(sharedMainViewModel: SharedMainViewModel()) } diff --git a/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift new file mode 100644 index 000000000..f072ff1f5 --- /dev/null +++ b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-iphone + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import SwiftUI + +struct ThirdPartySipAccountLoginFragment: View { + + @ObservedObject private var coreContext = CoreContext.shared + @ObservedObject var accountLoginViewModel : AccountLoginViewModel + + @Environment(\.dismiss) var dismiss + + @State private var isSecured: Bool = true + + @FocusState var isNameFocused:Bool + @FocusState var isPasswordFocused:Bool + @FocusState var isDomainFocused:Bool + @FocusState var isDisplayNameFocused:Bool + + var body: some View { + GeometryReader { geometry in + ScrollView(.vertical) { + VStack { + ZStack { + Image("mountain") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 100) + .clipped() + + VStack (alignment: .leading) { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20, alignment: .leading) + .padding(.top, -65) + .onTapGesture { + withAnimation { + accountLoginViewModel.domain = "sip.linphone.org" + accountLoginViewModel.transportType = "TLS" + dismiss() + } + } + + Spacer() + } + .padding(.leading) + } + .frame(width: geometry.size.width) + + Text("Use a SIP account") + .default_text_style_white_800(styleSize: 20) + .padding(.top, 20) + } + .padding(.top, 35) + .padding(.bottom, 10) + + VStack(alignment: .leading) { + Text(String(localized: "username")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("username", text : $accountLoginViewModel.username) + .default_text_style(styleSize: 15) + .disabled(coreContext.loggedIn) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isNameFocused) + + Text(String(localized: "password")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + ZStack(alignment: .trailing) { + Group { + if isSecured { + SecureField("password", text: $accountLoginViewModel.passwd) + .default_text_style(styleSize: 15) + .frame(height: 25) + .focused($isPasswordFocused) + } else { + TextField("password", text: $accountLoginViewModel.passwd) + .default_text_style(styleSize: 15) + .frame(height: 25) + .focused($isPasswordFocused) + } + } + Button(action: { + isSecured.toggle() + }) { + Image(self.isSecured ? "eye-slash" : "eye") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20) + } + } + .disabled(coreContext.loggedIn) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isPasswordFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) + ) + .padding(.bottom) + + Text(String(localized: "Domain")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("sip.linphone.org", text : $accountLoginViewModel.domain) + .default_text_style(styleSize: 15) + .disabled(coreContext.loggedIn) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isDomainFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isDomainFocused) + + Text(String(localized: "Display Name")) + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("Display Name", text : $accountLoginViewModel.displayName) + .default_text_style(styleSize: 15) + .disabled(coreContext.loggedIn) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isDisplayNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isDisplayNameFocused) + + Text(String(localized: "Transport")) + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + Menu { + Button("TLS") {accountLoginViewModel.transportType = "TLS"} + Button("TCP") {accountLoginViewModel.transportType = "TCP"} + Button("UDP") {accountLoginViewModel.transportType = "UDP"} + } label: { + Text(accountLoginViewModel.transportType) + .default_text_style(styleSize: 15) + .frame(maxWidth: .infinity, alignment: .leading) + Image("caret-down") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20) + } + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.gray_200, lineWidth: 1) + ) + .padding(.bottom) + + Spacer() + + Button(action: { + if (self.coreContext.loggedIn){ + self.accountLoginViewModel.unregister() + self.accountLoginViewModel.delete() + } else { + self.accountLoginViewModel.login() + } + + accountLoginViewModel.domain = "sip.linphone.org" + accountLoginViewModel.transportType = "TLS" + }) { + Text(coreContext.loggedIn ? "Log out" : "assistant_account_login") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + } + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background((accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty) ? Color.orange_main_100 : Color.orange_main_500) + .cornerRadius(60) + .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty) + } + .padding(.horizontal, 20) + } + .frame(minHeight: geometry.size.height) + } + } + .navigationBarHidden(true) + } +} + +#Preview { + ThirdPartySipAccountLoginFragment(accountLoginViewModel: AccountLoginViewModel()) +} diff --git a/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift new file mode 100644 index 000000000..386f98b57 --- /dev/null +++ b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-iphone + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import SwiftUI + +struct ThirdPartySipAccountWarningFragment: View { + + @ObservedObject private var coreContext = CoreContext.shared + @ObservedObject var accountLoginViewModel : AccountLoginViewModel + + @Environment(\.dismiss) var dismiss + + var body: some View { + NavigationView { + GeometryReader { geometry in + ScrollView(.vertical) { + VStack { + ZStack { + Image("mountain") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 100) + .clipped() + + VStack (alignment: .leading) { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20, alignment: .leading) + .padding(.top, -65) + .onTapGesture { + withAnimation { + dismiss() + } + } + + Spacer() + } + .padding(.leading) + } + .frame(width: geometry.size.width) + + Text("Use a SIP account") + .default_text_style_white_800(styleSize: 20) + .padding(.top, 20) + } + .padding(.top, 35) + .padding(.bottom, 10) + + Spacer() + + VStack(alignment: .leading) { + HStack { + Spacer() + HStack(alignment: .center) { + Image("conversation") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20, alignment: .leading) + .onTapGesture { + withAnimation { + dismiss() + } + } + } + .padding(16) + .background(Color.gray_main2_200) + .cornerRadius(40) + .padding(.horizontal) + + HStack(alignment: .center) { + Image("video-call") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.gray_main2_500) + .frame(width: 20, height: 20, alignment: .leading) + .onTapGesture { + withAnimation { + dismiss() + } + } + } + .padding(16) + .background(Color.gray_main2_200) + .cornerRadius(40) + .padding(.horizontal) + + Spacer() + } + .padding(.bottom, 40) + + Text("Some features require a Linphone account, such as group messaging, video conferences...\n\nThese features are hidden when you register with a third party SIP account.\n\nTo enable it in a commercial projet, please contact us. ") + .default_text_style(styleSize: 15) + .multilineTextAlignment(.center) + .padding(.bottom) + + HStack { + Spacer() + + HStack { + Text("[linphone.org/contact](https://linphone.org/contact)") + .tint(Color.orange_main_500) + .default_text_style_orange_600(styleSize: 15) + .frame(height: 35) + } + .padding(.horizontal, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orange_main_500, lineWidth: 1) + ) + + Spacer() + } + .padding(.vertical) + } + .padding(.horizontal, 20) + + Spacer() + + Button(action: { + dismiss() + }) { + Text("I prefere create an account") + .default_text_style_orange_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + } + .padding(.horizontal, 20) + .padding(.vertical, 10) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orange_main_500, lineWidth: 1) + ) + .padding(.horizontal) + + NavigationLink(destination: { + ThirdPartySipAccountLoginFragment(accountLoginViewModel: accountLoginViewModel) + }, label: { + Text("I understand") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orange_main_500) + .cornerRadius(60) + .padding(.horizontal) + } + .frame(minHeight: geometry.size.height) + } + } + } + .navigationBarHidden(true) + } +} + +#Preview { + ThirdPartySipAccountWarningFragment(accountLoginViewModel: AccountLoginViewModel()) +} diff --git a/Linphone/UI/Assistant/Viewmodel/AccountLoginViewModel.swift b/Linphone/UI/Assistant/Viewmodel/AccountLoginViewModel.swift index 3920bce13..7a6da1d2d 100644 --- a/Linphone/UI/Assistant/Viewmodel/AccountLoginViewModel.swift +++ b/Linphone/UI/Assistant/Viewmodel/AccountLoginViewModel.swift @@ -27,6 +27,7 @@ class AccountLoginViewModel : ObservableObject { @Published var username : String = "" @Published var passwd : String = "" @Published var domain : String = "sip.linphone.org" + @Published var displayName : String = "" @Published var transportType : String = "TLS" init() {} diff --git a/Linphone/UI/Main/ContentView.swift b/Linphone/UI/Main/ContentView.swift index a30a20a4c..c0404cd2f 100644 --- a/Linphone/UI/Main/ContentView.swift +++ b/Linphone/UI/Main/ContentView.swift @@ -27,9 +27,9 @@ struct ContentView: View { var body: some View { if UserDefaults.standard.bool(forKey: "general_terms") == false { WelcomeView(sharedMainViewModel: sharedMainViewModel) - } else if coreContext.mCore.defaultAccount == nil { - AssistantView() - } else { + } else if coreContext.mCore.defaultAccount == nil || sharedMainViewModel.displayProfileMode { + AssistantView(sharedMainViewModel: sharedMainViewModel) + } else { TabView { ContactsView() .tabItem { @@ -46,5 +46,5 @@ struct ContentView: View { } #Preview { - ContentView(sharedMainViewModel: SharedMainViewModel()) + ContentView(sharedMainViewModel: SharedMainViewModel()) } diff --git a/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift b/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift index 31a93e888..ac654f468 100644 --- a/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift +++ b/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift @@ -20,7 +20,9 @@ import linphonesw class SharedMainViewModel : ObservableObject { - + + @Published var displayProfileMode : Bool = false + @Published var generalTermsAccepted = false init() { diff --git a/Linphone/UI/Welcome/WelcomeView.swift b/Linphone/UI/Welcome/WelcomeView.swift index 03710d291..ce4052e11 100644 --- a/Linphone/UI/Welcome/WelcomeView.swift +++ b/Linphone/UI/Welcome/WelcomeView.swift @@ -30,7 +30,7 @@ struct WelcomeView: View{ var body: some View { GeometryReader { geometry in - ZStack { + ScrollView { VStack { ZStack { Image("mountain") @@ -67,6 +67,8 @@ struct WelcomeView: View{ .padding(.top, 35) .padding(.bottom, 10) + Spacer() + VStack{ TabView(selection: $index) { ForEach((0..<3), id: \.self) { index in @@ -82,11 +84,14 @@ struct WelcomeView: View{ } } .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) + .frame(minHeight: 300) .onAppear { setupAppearance() } } + Spacer() + Button(action: { if index < 2 { withAnimation { @@ -107,18 +112,17 @@ struct WelcomeView: View{ .padding(.vertical, 10) .background(Color.orange_main_500) .cornerRadius(60) - .padding(.bottom) .padding(.horizontal) } - - if self.isShowPopup { - PopupView(isShowPopup: $isShowPopup, title: Text("Conditions de service"), content: Text("En continuant, vous acceptez ces conditions, \(Text("[notre politique de confidentialité](https://linphone.org/privacy-policy)").underline()) et \(Text("[nos conditions d’utilisation](https://linphone.org/general-terms)").underline())."), titleFirstButton: Text("Deny all"), actionFirstButton: {self.isShowPopup.toggle()}, titleSecondButton: Text("Accept all"), actionSecondButton: {permissionManager.photoLibraryRequestPermission()}) - .background(.black.opacity(0.65)) - .edgesIgnoringSafeArea(.all) - .onTapGesture { - self.isShowPopup.toggle() - } - } + .frame(minHeight: geometry.size.height) + } + + if self.isShowPopup { + PopupView(isShowPopup: $isShowPopup, title: Text("Conditions de service"), content: Text("En continuant, vous acceptez ces conditions, \(Text("[notre politique de confidentialité](https://linphone.org/privacy-policy)").underline()) et \(Text("[nos conditions d’utilisation](https://linphone.org/general-terms)").underline())."), titleFirstButton: Text("Deny all"), actionFirstButton: {self.isShowPopup.toggle()}, titleSecondButton: Text("Accept all"), actionSecondButton: {permissionManager.photoLibraryRequestPermission()}) + .background(.black.opacity(0.65)) + .onTapGesture { + self.isShowPopup.toggle() + } } } .onReceive(permissionManager.$photoLibraryPermissionGranted, perform: { (granted) in