From 273c77edbe90b38805b74896cc5a403d41a47b5a Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Tue, 4 Mar 2025 18:08:16 +0100 Subject: [PATCH] Moved mountain image to the bottom of all Login views --- .../mountain2.imageset/Contents.json | 21 + .../mountain2.imageset/mountain2.png | Bin 0 -> 6926 bytes Linphone/Localizable.xcstrings | 12 +- .../Assistant/Fragments/LoginFragment.swift | 499 +++++++++-------- .../Fragments/PermissionsFragment.swift | 324 +++++------ .../RegisterCodeConfirmationFragment.swift | 236 ++++---- .../Fragments/RegisterFragment.swift | 524 +++++++++--------- .../ThirdPartySipAccountLoginFragment.swift | 403 +++++++------- .../ThirdPartySipAccountWarningFragment.swift | 282 +++++----- .../Main/Viewmodel/SharedMainViewModel.swift | 2 +- .../Fragments/WelcomePage1Fragment.swift | 4 +- .../Fragments/WelcomePage2Fragment.swift | 4 +- .../Fragments/WelcomePage3Fragment.swift | 4 +- Linphone/UI/Welcome/WelcomeView.swift | 219 ++++---- 14 files changed, 1310 insertions(+), 1224 deletions(-) create mode 100644 Linphone/Assets.xcassets/mountain2.imageset/Contents.json create mode 100644 Linphone/Assets.xcassets/mountain2.imageset/mountain2.png diff --git a/Linphone/Assets.xcassets/mountain2.imageset/Contents.json b/Linphone/Assets.xcassets/mountain2.imageset/Contents.json new file mode 100644 index 000000000..8372f4dbd --- /dev/null +++ b/Linphone/Assets.xcassets/mountain2.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "mountain2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Linphone/Assets.xcassets/mountain2.imageset/mountain2.png b/Linphone/Assets.xcassets/mountain2.imageset/mountain2.png new file mode 100644 index 0000000000000000000000000000000000000000..d1880df74082d9a58e2491f31361edee75208053 GIT binary patch literal 6926 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 literal 0 HcmV?d00001 diff --git a/Linphone/Localizable.xcstrings b/Linphone/Localizable.xcstrings index f07797c31..38bff373a 100644 --- a/Linphone/Localizable.xcstrings +++ b/Linphone/Localizable.xcstrings @@ -1055,13 +1055,13 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Some features require a %@ 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 project, please contact us." + "value" : "Some features require a %@ 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 project, please contact us." } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "Certaines fonctionnalités telles que les conversations de groupe, les vidéo-conférences, etc… nécessitent un compte %@.\\n\\nCes fonctionnalités seront masquées si vous utilisez un compte SIP tiers.\\n\\nPour les activer dans un projet commercial, merci de nous contacter." + "value" : "Certaines fonctionnalités telles que les conversations de groupe, les vidéo-conférences, etc… nécessitent un compte %@.\n\nCes fonctionnalités seront masquées si vous utilisez un compte SIP tiers.\n\nPour les activer dans un projet commercial, merci de nous contacter." } } } @@ -7677,12 +7677,12 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Your communications are safe thanks to our end-to-end encryption." + "value" : "Your communications are safe thanks to our **end-to-end encryption**." } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Vos communications sont en sécurité grâce au **chiffrement de bout en bout**." } } @@ -7709,12 +7709,12 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "A free and open source application since 2001." + "value" : "A **free** and open source application since **2001**." } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Une application open source et un **service gratuit** depuis **2001**." } } diff --git a/Linphone/UI/Assistant/Fragments/LoginFragment.swift b/Linphone/UI/Assistant/Fragments/LoginFragment.swift index ce93a7a25..8c74c3d17 100644 --- a/Linphone/UI/Assistant/Fragments/LoginFragment.swift +++ b/Linphone/UI/Assistant/Fragments/LoginFragment.swift @@ -45,251 +45,15 @@ struct LoginFragment: View { NavigationView { ZStack { GeometryReader { geometry in - ScrollView(.vertical) { - VStack { - ZStack { - Image("mountain") - .resizable() - .scaledToFill() - .frame(width: geometry.size.width, height: 100) - .clipped() - - if isShowBack { - VStack(alignment: .leading) { - HStack { - Image("caret-left") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, -75) - .padding(.leading, -10) - .onTapGesture { - withAnimation { - onBackPressed?() - } - } - - Spacer() - } - .padding(.leading) - } - .frame(width: geometry.size.width) - } - - 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) - - TextField("username", text: $accountLoginViewModel.username) - .default_text_style(styleSize: 15) - .disableAutocorrection(true) - .autocapitalization(.none) - .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.orangeMain500 : Color.gray200, 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) - .disableAutocorrection(true) - .autocapitalization(.none) - .frame(height: 25) - .focused($isPasswordFocused) - } - } - - Button(action: { - isSecured.toggle() - }, label: { - Image(self.isSecured ? "eye-slash" : "eye") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .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.orangeMain500 : Color.gray200, lineWidth: 1) - ) - .padding(.bottom) - - Button(action: { - sharedMainViewModel.changeDisplayProfileMode() - self.accountLoginViewModel.login() - coreContext.loggingInProgress = true - }, label: { - Text(coreContext.loggedIn ? "manage_account_delete" : "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.orangeMain100 : Color.orangeMain500) - .cornerRadius(60) - .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) - .padding(.bottom) - - HStack { - Text(.init(String(format: ("[%@](%@)"), String(localized: "assistant_forgotten_password"), "https://subscribe.linphone.org/"))) - .underline() - .tint(Color.grayMain2c600) - .default_text_style_600(styleSize: 15) - .foregroundStyle(Color.grayMain2c500) - } - .frame(maxWidth: .infinity) - .padding(.bottom, 30) - - HStack { - VStack { - Divider() - } - Text("or") - .default_text_style(styleSize: 15) - .foregroundStyle(Color.grayMain2c500) - VStack { - Divider() - } - } - .padding(.bottom, 10) - - NavigationLink(destination: { - QrCodeScannerFragment() - }, label: { - HStack { - Image("qr-code") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.orangeMain500) - .frame(width: 20, height: 20) - - Text("assistant_scan_qr_code") - .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.orangeMain500, lineWidth: 1) - ) - .padding(.bottom) - - NavigationLink(isActive: $isLinkSIPActive, destination: { - ThirdPartySipAccountWarningFragment(accountLoginViewModel: accountLoginViewModel) - }, label: { - Text("assistant_login_third_party_sip_account") - .default_text_style_orange_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - - }) - .disabled(!sharedMainViewModel.generalTermsAccepted) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(Color.orangeMain500, lineWidth: 1) - ) - .padding(.bottom) - .simultaneousGesture( - TapGesture().onEnded { - self.linkActive = "SIP" - if !sharedMainViewModel.generalTermsAccepted { - withAnimation { - self.isShowPopup.toggle() - } - } else { - self.isLinkSIPActive = true - } - } - ) - - Spacer() - - HStack(alignment: .center) { - - Spacer() - - Text("assistant_no_account_yet") - .default_text_style(styleSize: 15) - .foregroundStyle(Color.grayMain2c700) - .padding(.horizontal, 10) - - NavigationLink(destination: RegisterFragment(registerViewModel: RegisterViewModel()), isActive: $isLinkREGActive, label: { Text("assistant_account_register") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - }) - .disabled(!sharedMainViewModel.generalTermsAccepted) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .padding(.horizontal, 10) - .simultaneousGesture( - TapGesture().onEnded { - self.linkActive = "REG" - if !sharedMainViewModel.generalTermsAccepted { - withAnimation { - self.isShowPopup.toggle() - } - } else { - self.isLinkREGActive = true - } - } - ) - - Spacer() - } - .padding(.bottom) - } - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal, 20) + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) + } + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) } if self.isShowPopup { @@ -336,10 +100,257 @@ struct LoginFragment: View { } .navigationTitle("") .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) } .navigationViewStyle(StackNavigationViewStyle()) } + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + HStack { + if isShowBack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25) + .padding(.all, 10) + .onTapGesture { + withAnimation { + onBackPressed?() + } + } + } else { + Color.clear + .frame(width: 25, height: 25) + .padding(.all, 10) + } + + Spacer() + } + + Text("assistant_account_login") + .default_text_style_800(styleSize: 20) + } + .frame(width: geometry.size.width) + .padding(.top, 10) + .padding(.bottom, 20) + + 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) + .disableAutocorrection(true) + .autocapitalization(.none) + .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.orangeMain500 : Color.gray200, 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) + .disableAutocorrection(true) + .autocapitalization(.none) + .frame(height: 25) + .focused($isPasswordFocused) + } + } + + Button(action: { + isSecured.toggle() + }, label: { + Image(self.isSecured ? "eye-slash" : "eye") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .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.orangeMain500 : Color.gray200, lineWidth: 1) + ) + .padding(.bottom) + + Button(action: { + sharedMainViewModel.changeDisplayProfileMode() + self.accountLoginViewModel.login() + coreContext.loggingInProgress = true + }, label: { + Text(coreContext.loggedIn ? "manage_account_delete" : "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.orangeMain100 : Color.orangeMain500) + .cornerRadius(60) + .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) + .padding(.bottom) + + HStack { + Text(.init(String(format: ("[%@](%@)"), String(localized: "assistant_forgotten_password"), "https://subscribe.linphone.org/"))) + .underline() + .tint(Color.grayMain2c600) + .default_text_style_600(styleSize: 15) + .foregroundStyle(Color.grayMain2c500) + } + .frame(maxWidth: .infinity) + .padding(.bottom, 30) + + HStack { + VStack { + Divider() + } + Text("or") + .default_text_style(styleSize: 15) + .foregroundStyle(Color.grayMain2c500) + VStack { + Divider() + } + } + .padding(.bottom, 10) + + NavigationLink(destination: { + QrCodeScannerFragment() + }, label: { + HStack { + Image("qr-code") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.orangeMain500) + .frame(width: 20, height: 20) + + Text("assistant_scan_qr_code") + .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.orangeMain500, lineWidth: 1) + ) + .padding(.bottom) + + NavigationLink(isActive: $isLinkSIPActive, destination: { + ThirdPartySipAccountWarningFragment(accountLoginViewModel: accountLoginViewModel) + }, label: { + Text("assistant_login_third_party_sip_account") + .default_text_style_orange_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + + }) + .disabled(!sharedMainViewModel.generalTermsAccepted) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orangeMain500, lineWidth: 1) + ) + .padding(.bottom) + .simultaneousGesture( + TapGesture().onEnded { + self.linkActive = "SIP" + if !sharedMainViewModel.generalTermsAccepted { + withAnimation { + self.isShowPopup.toggle() + } + } else { + self.isLinkSIPActive = true + } + } + ) + } + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal, 20) + + Spacer() + + HStack(alignment: .center) { + + Spacer() + + Text("assistant_no_account_yet") + .default_text_style(styleSize: 15) + .foregroundStyle(Color.grayMain2c700) + .padding(.horizontal, 10) + + NavigationLink(destination: RegisterFragment(registerViewModel: RegisterViewModel()), isActive: $isLinkREGActive, label: { Text("assistant_account_register") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + }) + .disabled(!sharedMainViewModel.generalTermsAccepted) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .padding(.horizontal, 10) + .simultaneousGesture( + TapGesture().onEnded { + self.linkActive = "REG" + if !sharedMainViewModel.generalTermsAccepted { + withAnimation { + self.isShowPopup.toggle() + } + } else { + self.isLinkREGActive = true + } + } + ) + + Spacer() + } + .padding(.bottom) + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) + } + func acceptGeneralTerms() { sharedMainViewModel.changeGeneralTerms() self.isShowPopup.toggle() diff --git a/Linphone/UI/Assistant/Fragments/PermissionsFragment.swift b/Linphone/UI/Assistant/Fragments/PermissionsFragment.swift index dd1bc8836..d35a5594d 100644 --- a/Linphone/UI/Assistant/Fragments/PermissionsFragment.swift +++ b/Linphone/UI/Assistant/Fragments/PermissionsFragment.swift @@ -29,170 +29,21 @@ struct PermissionsFragment: View { 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.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, -75) - .padding(.leading, -10) - .onTapGesture { - withAnimation { - dismiss() - } - } - - Spacer() - } - .padding(.leading) - } - .frame(width: geometry.size.width) - - Text("assistant_permissions_title") - .default_text_style_white_800(styleSize: 20) - .padding(.top, 20) - } - .padding(.top, 35) - .padding(.bottom, 10) - - Text(String(format: String(localized: "assistant_permissions_subtitle"), Bundle.main.displayName)) - .default_text_style(styleSize: 15) - .multilineTextAlignment(.center) - - Spacer() - - VStack(alignment: .leading) { - HStack { - HStack(alignment: .center) { - Image("bell-ringing") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20, alignment: .leading) - } - .padding(16) - .background(Color.grayMain2c200) - .cornerRadius(40) - - Text("assistant_permissions_post_notifications_title") - .default_text_style(styleSize: 15) - .padding(.leading, 10) - } - .padding(.bottom) - - HStack { - HStack(alignment: .center) { - Image("address-book") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20, alignment: .leading) - } - .padding(16) - .background(Color.grayMain2c200) - .cornerRadius(40) - Text(.init(String(format: String(localized: "assistant_permissions_read_contacts_title"), Bundle.main.displayName))) - .default_text_style(styleSize: 15) - .padding(.leading, 10) - } - .padding(.bottom) - - HStack { - HStack(alignment: .center) { - Image("microphone") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20, alignment: .leading) - } - .padding(16) - .background(Color.grayMain2c200) - .cornerRadius(40) - - Text("assistant_permissions_record_audio_title") - .default_text_style(styleSize: 15) - .padding(.leading, 10) - } - .padding(.bottom) - - HStack { - HStack(alignment: .center) { - Image("video-camera") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20, alignment: .leading) - } - .padding(16) - .background(Color.grayMain2c200) - .cornerRadius(40) - - Text("assistant_permissions_access_camera_title") - .default_text_style(styleSize: 15) - .padding(.leading, 10) - } - .padding(.bottom) - } - .frame(maxWidth: sharedMainViewModel.maxWidth) - .frame(maxHeight: .infinity) - .padding(.horizontal, 20) - - Spacer() - - Button(action: { - withAnimation { - sharedMainViewModel.changeWelcomeView() - } - }, label: { - Text("assistant_permissions_skip_permissions") - .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.orangeMain500, lineWidth: 1) - ) - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal) - - Button { - permissionManager.getPermissions() - } label: { - Text("assistant_permissions_grant_all_of_them") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - } - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal) - .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) + } + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) } } .navigationViewStyle(StackNavigationViewStyle()) .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) .onReceive(permissionManager.$allPermissionsHaveBeenDisplayed, perform: { (granted) in if granted { withAnimation { @@ -201,6 +52,161 @@ struct PermissionsFragment: View { } }) } + + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25) + .padding(.all, 10) + .onTapGesture { + withAnimation { + dismiss() + } + } + Spacer() + } + + Text("assistant_permissions_title") + .default_text_style_800(styleSize: 20) + } + .frame(width: geometry.size.width) + .padding(.top, 10) + .padding(.bottom, 20) + + Text(String(format: String(localized: "assistant_permissions_subtitle"), Bundle.main.displayName)) + .default_text_style(styleSize: 15) + .multilineTextAlignment(.center) + + Spacer() + + VStack(alignment: .leading) { + HStack { + HStack(alignment: .center) { + Image("bell-ringing") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 20, height: 20, alignment: .leading) + } + .padding(16) + .background(Color.grayMain2c200) + .cornerRadius(40) + + Text("assistant_permissions_post_notifications_title") + .default_text_style(styleSize: 15) + .padding(.leading, 10) + } + .padding(.bottom) + + HStack { + HStack(alignment: .center) { + Image("address-book") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 20, height: 20, alignment: .leading) + } + .padding(16) + .background(Color.grayMain2c200) + .cornerRadius(40) + Text(.init(String(format: String(localized: "assistant_permissions_read_contacts_title"), Bundle.main.displayName))) + .default_text_style(styleSize: 15) + .padding(.leading, 10) + } + .padding(.bottom) + + HStack { + HStack(alignment: .center) { + Image("microphone") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 20, height: 20, alignment: .leading) + } + .padding(16) + .background(Color.grayMain2c200) + .cornerRadius(40) + + Text("assistant_permissions_record_audio_title") + .default_text_style(styleSize: 15) + .padding(.leading, 10) + } + .padding(.bottom) + + HStack { + HStack(alignment: .center) { + Image("video-camera") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 20, height: 20, alignment: .leading) + } + .padding(16) + .background(Color.grayMain2c200) + .cornerRadius(40) + + Text("assistant_permissions_access_camera_title") + .default_text_style(styleSize: 15) + .padding(.leading, 10) + } + .padding(.bottom) + } + .frame(maxWidth: sharedMainViewModel.maxWidth) + .frame(maxHeight: .infinity) + .padding(.horizontal, 20) + + Spacer() + + Button(action: { + withAnimation { + sharedMainViewModel.changeWelcomeView() + } + }, label: { + Text("assistant_permissions_skip_permissions") + .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.orangeMain500, lineWidth: 1) + ) + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal) + + Button { + permissionManager.getPermissions() + } label: { + Text("assistant_permissions_grant_all_of_them") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + } + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal) + .padding(.bottom) + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) + } } #Preview { diff --git a/Linphone/UI/Assistant/Fragments/RegisterCodeConfirmationFragment.swift b/Linphone/UI/Assistant/Fragments/RegisterCodeConfirmationFragment.swift index 374c362c6..837890bee 100644 --- a/Linphone/UI/Assistant/Fragments/RegisterCodeConfirmationFragment.swift +++ b/Linphone/UI/Assistant/Fragments/RegisterCodeConfirmationFragment.swift @@ -41,121 +41,14 @@ struct RegisterCodeConfirmationFragment: View { NavigationView { GeometryReader { geometry in ZStack { - 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.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, -75) - .padding(.leading, -10) - .onTapGesture { - withAnimation { - dismiss() - } - } - - Spacer() - } - .padding(.leading) - } - .frame(width: geometry.size.width) - - Text("assistant_account_register") - .default_text_style_white_800(styleSize: 20) - .padding(.top, 20) - } - .padding(.top, 35) - .padding(.bottom, 10) - - ZStack { - VStack { - Spacer() - HStack { - Spacer() - Image("confirm_sms_code_illu") - .padding(.bottom, -geometry.safeAreaInsets.bottom) - } - } - VStack(alignment: .center) { - Spacer() - - Text(String(format: NSLocalizedString("assistant_account_creation_sms_confirmation_explanation", comment: ""), registerViewModel.phoneNumber)) - .default_text_style(styleSize: 15) - .foregroundStyle(Color.grayMain2c700) - .padding(.horizontal, 10) - .frame(maxWidth: .infinity, alignment: .center) - .multilineTextAlignment(.center) - - VStack { - ZStack { - - HStack(spacing: spaceBetweenBoxes) { - otpText(text: registerViewModel.otp1, focused: registerViewModel.otpField.isEmpty) - otpText(text: registerViewModel.otp2, focused: registerViewModel.otpField.count == 1) - otpText(text: registerViewModel.otp3, focused: registerViewModel.otpField.count == 2) - otpText(text: registerViewModel.otp4, focused: registerViewModel.otpField.count == 3) - } - - TextField("", text: $registerViewModel.otpField) - .default_text_style_600(styleSize: 80) - .frame(width: isFocused ? 0 : textFieldOriginalWidth, height: textBoxHeight) - .textContentType(.oneTimeCode) - .foregroundColor(.clear) - .accentColor(.clear) - .background(.clear) - .keyboardType(.numberPad) - .focused($isFocused) - .onChange(of: registerViewModel.otpField) { _ in - limitText(textLimit) - if registerViewModel.otpField.count > 3 { - registerViewModel.validateCode() - } - } - } - } - .frame(maxWidth: .infinity, alignment: .center) - .padding(.vertical, 20) - - Button(action: { - dismiss() - }, label: { - Text("assistant_account_creation_wrong_phone_number") - .default_text_style_orange_600(styleSize: 15) - .frame(height: 35) - }) - .padding(.horizontal, 15) - .padding(.vertical, 5) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(Color.orangeMain500, lineWidth: 1) - ) - .padding(.bottom) - .frame(maxWidth: .infinity) - - Spacer() - Spacer() - } - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal, 20) - } + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) - .onAppear { - registerViewModel.otpField = "" + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } } @@ -167,12 +60,127 @@ struct RegisterCodeConfirmationFragment: View { } .navigationTitle("") .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) } .navigationViewStyle(StackNavigationViewStyle()) .navigationTitle("") .navigationBarHidden(true) } + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25) + .padding(.all, 10) + .onTapGesture { + withAnimation { + dismiss() + } + } + Spacer() + } + + Text("assistant_account_register") + .default_text_style_800(styleSize: 20) + } + .frame(width: geometry.size.width) + .padding(.top, 10) + .padding(.bottom, 20) + + ZStack { + VStack { + Spacer() + HStack { + Spacer() + Image("confirm_sms_code_illu") + .padding(.bottom, -geometry.safeAreaInsets.bottom) + } + } + VStack(alignment: .center) { + Spacer() + + Text(String(format: NSLocalizedString("assistant_account_creation_sms_confirmation_explanation", comment: ""), registerViewModel.phoneNumber)) + .default_text_style(styleSize: 15) + .foregroundStyle(Color.grayMain2c700) + .padding(.horizontal, 10) + .frame(maxWidth: .infinity, alignment: .center) + .multilineTextAlignment(.center) + + VStack { + ZStack { + + HStack(spacing: spaceBetweenBoxes) { + otpText(text: registerViewModel.otp1, focused: registerViewModel.otpField.isEmpty) + otpText(text: registerViewModel.otp2, focused: registerViewModel.otpField.count == 1) + otpText(text: registerViewModel.otp3, focused: registerViewModel.otpField.count == 2) + otpText(text: registerViewModel.otp4, focused: registerViewModel.otpField.count == 3) + } + + TextField("", text: $registerViewModel.otpField) + .default_text_style_600(styleSize: 80) + .frame(width: isFocused ? 0 : textFieldOriginalWidth, height: textBoxHeight) + .textContentType(.oneTimeCode) + .foregroundColor(.clear) + .accentColor(.clear) + .background(.clear) + .keyboardType(.numberPad) + .focused($isFocused) + .onChange(of: registerViewModel.otpField) { _ in + limitText(textLimit) + if registerViewModel.otpField.count > 3 { + registerViewModel.validateCode() + } + } + } + } + .frame(maxWidth: .infinity, alignment: .center) + .padding(.vertical, 20) + + Button(action: { + dismiss() + }, label: { + Text("assistant_account_creation_wrong_phone_number") + .default_text_style_orange_600(styleSize: 15) + .frame(height: 35) + }) + .padding(.horizontal, 15) + .padding(.vertical, 5) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orangeMain500, lineWidth: 1) + ) + .padding(.bottom) + .frame(maxWidth: .infinity) + + Spacer() + Spacer() + } + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal, 20) + } + + Spacer() + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) + .onAppear { + registerViewModel.otpField = "" + } + } + private func otpText(text: String, focused: Bool) -> some View { return Text(text) diff --git a/Linphone/UI/Assistant/Fragments/RegisterFragment.swift b/Linphone/UI/Assistant/Fragments/RegisterFragment.swift index 387220a66..946f9b48e 100644 --- a/Linphone/UI/Assistant/Fragments/RegisterFragment.swift +++ b/Linphone/UI/Assistant/Fragments/RegisterFragment.swift @@ -39,266 +39,15 @@ struct RegisterFragment: View { NavigationView { GeometryReader { geometry in ZStack { - 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.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, -75) - .padding(.leading, -10) - .onTapGesture { - withAnimation { - dismiss() - } - } - - Spacer() - } - .padding(.leading) - } - .frame(width: geometry.size.width) - - Text("assistant_account_register") - .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: $registerViewModel.username) - .default_text_style(styleSize: 15) - .disableAutocorrection(true) - .autocapitalization(.none) - .frame(height: 25) - .padding(.horizontal, 20) - .padding(.vertical, 15) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(isNameFocused ? Color.orangeMain500 : (!registerViewModel.usernameError.isEmpty ? Color.redDanger500 : Color.gray200), lineWidth: 1) - ) - .focused($isNameFocused) - .onChange(of: registerViewModel.username) { _ in - if !registerViewModel.usernameError.isEmpty { - registerViewModel.usernameError = "" - } - } - - Text(registerViewModel.usernameError) - .foregroundStyle(Color.redDanger500) - .default_text_style_600(styleSize: 15) - .padding(.bottom) - - Text(String(localized: "phone_number")+"*") - .default_text_style_700(styleSize: 15) - .padding(.bottom, -5) - - HStack { - Menu { - Picker("", selection: $registerViewModel.dialPlanValueSelected) { - ForEach(Array(registerViewModel.dialPlansLabelList.enumerated()), id: \.offset) { index, dialPlan in - Text(dialPlan).tag(registerViewModel.dialPlansShortLabelList[index]) - } - } - } label: { - HStack { - Text(registerViewModel.dialPlanValueSelected) - - Image("caret-down") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.blue) - .frame(width: 15, height: 15) - } - } - .padding(.trailing, 5) - - Divider() - - TextField("phone_number", text: $registerViewModel.phoneNumber) - .default_text_style(styleSize: 15) - .disableAutocorrection(true) - .autocapitalization(.none) - .padding(.leading, 5) - .keyboardType(.numberPad) - .onChange(of: registerViewModel.phoneNumber) { _ in - if !registerViewModel.phoneNumberError.isEmpty { - registerViewModel.phoneNumberError = "" - } - } - } - .frame(height: 25) - .padding(.horizontal, 20) - .padding(.vertical, 15) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(isPhoneNumberFocused ? Color.orangeMain500 : (!registerViewModel.phoneNumberError.isEmpty ? Color.redDanger500 : Color.gray200), lineWidth: 1) - ) - .focused($isPhoneNumberFocused) - - Text(registerViewModel.phoneNumberError) - .foregroundStyle(Color.redDanger500) - .default_text_style_600(styleSize: 15) - .padding(.bottom) - - Text(String(localized: "password")+"*") - .default_text_style_700(styleSize: 15) - .padding(.bottom, -5) - - ZStack(alignment: .trailing) { - Group { - if isSecured { - SecureField("password", text: $registerViewModel.passwd) - .default_text_style(styleSize: 15) - .frame(height: 25) - .focused($isPasswordFocused) - .onChange(of: registerViewModel.passwd) { _ in - if !registerViewModel.passwordError.isEmpty { - registerViewModel.passwordError = "" - } - } - } else { - TextField("password", text: $registerViewModel.passwd) - .default_text_style(styleSize: 15) - .disableAutocorrection(true) - .autocapitalization(.none) - .frame(height: 25) - .focused($isPasswordFocused) - .onChange(of: registerViewModel.passwd) { _ in - if !registerViewModel.passwordError.isEmpty { - registerViewModel.passwordError = "" - } - } - } - } - - Button(action: { - isSecured.toggle() - }, label: { - Image(self.isSecured ? "eye-slash" : "eye") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20) - }) - } - .padding(.horizontal, 20) - .padding(.vertical, 15) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(isPasswordFocused ? Color.orangeMain500 : (!registerViewModel.passwordError.isEmpty ? Color.redDanger500 : Color.gray200), lineWidth: 1) - ) - - Text(registerViewModel.passwordError) - .foregroundStyle(Color.redDanger500) - .default_text_style_600(styleSize: 15) - .padding(.bottom) - - NavigationLink(isActive: $registerViewModel.isLinkActive, destination: { - RegisterCodeConfirmationFragment(registerViewModel: registerViewModel) - }, label: { - Text("assistant_account_create") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - - }) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background((registerViewModel.username.isEmpty || registerViewModel.phoneNumber.isEmpty || registerViewModel.passwd.isEmpty) ? Color.orangeMain100 : Color.orangeMain500) - .cornerRadius(60) - .disabled(!registerViewModel.isLinkActive) - .padding(.bottom) - .simultaneousGesture( - TapGesture().onEnded { - if !(registerViewModel.username.isEmpty || registerViewModel.phoneNumber.isEmpty || registerViewModel.passwd.isEmpty) { - withAnimation { - self.isShowPopup = true - } - } - } - ) - - Spacer() - - Text("assistant_create_account_using_email_on_our_web_platform") - .default_text_style(styleSize: 15) - .foregroundStyle(Color.grayMain2c700) - .padding(.horizontal, 10) - .frame(maxWidth: .infinity, alignment: .center) - - Button(action: { - UIApplication.shared.open(URL(string: "https://subscribe.linphone.org/register/email")!) - }, label: { - Text("assistant_web_platform_link") - .default_text_style_orange_600(styleSize: 15) - .frame(height: 35) - }) - .padding(.horizontal, 15) - .padding(.vertical, 5) - .cornerRadius(60) - .overlay( - RoundedRectangle(cornerRadius: 60) - .inset(by: 0.5) - .stroke(Color.orangeMain500, lineWidth: 1) - ) - .padding(.bottom) - .frame(maxWidth: .infinity) - - Spacer() - - HStack(alignment: .center) { - - Spacer() - - Text("assistant_already_have_an_account") - .default_text_style(styleSize: 15) - .foregroundStyle(Color.grayMain2c700) - .padding(.horizontal, 10) - - Button(action: { - dismiss() - }, label: { - Text("assistant_account_login") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - }) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .padding(.horizontal, 10) - - Spacer() - } - .padding(.bottom) - } - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal, 20) + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) + } + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) } if self.isShowPopup { @@ -335,11 +84,268 @@ struct RegisterFragment: View { } .navigationTitle("") .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) } .navigationViewStyle(StackNavigationViewStyle()) .navigationTitle("") .navigationBarHidden(true) } + + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25) + .padding(.all, 10) + .onTapGesture { + withAnimation { + dismiss() + } + } + Spacer() + } + + Text("assistant_account_register") + .default_text_style_800(styleSize: 20) + } + .frame(width: geometry.size.width) + .padding(.top, 10) + .padding(.bottom, 20) + + VStack(alignment: .leading) { + Text(String(localized: "username")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("username", text: $registerViewModel.username) + .default_text_style(styleSize: 15) + .disableAutocorrection(true) + .autocapitalization(.none) + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isNameFocused ? Color.orangeMain500 : (!registerViewModel.usernameError.isEmpty ? Color.redDanger500 : Color.gray200), lineWidth: 1) + ) + .focused($isNameFocused) + .onChange(of: registerViewModel.username) { _ in + if !registerViewModel.usernameError.isEmpty { + registerViewModel.usernameError = "" + } + } + + Text(registerViewModel.usernameError) + .foregroundStyle(Color.redDanger500) + .default_text_style_600(styleSize: 15) + .padding(.bottom) + + Text(String(localized: "phone_number")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + HStack { + Menu { + Picker("", selection: $registerViewModel.dialPlanValueSelected) { + ForEach(Array(registerViewModel.dialPlansLabelList.enumerated()), id: \.offset) { index, dialPlan in + Text(dialPlan).tag(registerViewModel.dialPlansShortLabelList[index]) + } + } + } label: { + HStack { + Text(registerViewModel.dialPlanValueSelected) + + Image("caret-down") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.blue) + .frame(width: 15, height: 15) + } + } + .padding(.trailing, 5) + + Divider() + + TextField("phone_number", text: $registerViewModel.phoneNumber) + .default_text_style(styleSize: 15) + .disableAutocorrection(true) + .autocapitalization(.none) + .padding(.leading, 5) + .keyboardType(.numberPad) + .onChange(of: registerViewModel.phoneNumber) { _ in + if !registerViewModel.phoneNumberError.isEmpty { + registerViewModel.phoneNumberError = "" + } + } + } + .frame(height: 25) + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isPhoneNumberFocused ? Color.orangeMain500 : (!registerViewModel.phoneNumberError.isEmpty ? Color.redDanger500 : Color.gray200), lineWidth: 1) + ) + .focused($isPhoneNumberFocused) + + Text(registerViewModel.phoneNumberError) + .foregroundStyle(Color.redDanger500) + .default_text_style_600(styleSize: 15) + .padding(.bottom) + + Text(String(localized: "password")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + ZStack(alignment: .trailing) { + Group { + if isSecured { + SecureField("password", text: $registerViewModel.passwd) + .default_text_style(styleSize: 15) + .frame(height: 25) + .focused($isPasswordFocused) + .onChange(of: registerViewModel.passwd) { _ in + if !registerViewModel.passwordError.isEmpty { + registerViewModel.passwordError = "" + } + } + } else { + TextField("password", text: $registerViewModel.passwd) + .default_text_style(styleSize: 15) + .disableAutocorrection(true) + .autocapitalization(.none) + .frame(height: 25) + .focused($isPasswordFocused) + .onChange(of: registerViewModel.passwd) { _ in + if !registerViewModel.passwordError.isEmpty { + registerViewModel.passwordError = "" + } + } + } + } + + Button(action: { + isSecured.toggle() + }, label: { + Image(self.isSecured ? "eye-slash" : "eye") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 20, height: 20) + }) + } + .padding(.horizontal, 20) + .padding(.vertical, 15) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(isPasswordFocused ? Color.orangeMain500 : (!registerViewModel.passwordError.isEmpty ? Color.redDanger500 : Color.gray200), lineWidth: 1) + ) + + Text(registerViewModel.passwordError) + .foregroundStyle(Color.redDanger500) + .default_text_style_600(styleSize: 15) + .padding(.bottom) + + NavigationLink(isActive: $registerViewModel.isLinkActive, destination: { + RegisterCodeConfirmationFragment(registerViewModel: registerViewModel) + }, label: { + Text("assistant_account_create") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background((registerViewModel.username.isEmpty || registerViewModel.phoneNumber.isEmpty || registerViewModel.passwd.isEmpty) ? Color.orangeMain100 : Color.orangeMain500) + .cornerRadius(60) + .disabled(!registerViewModel.isLinkActive) + .padding(.bottom) + .simultaneousGesture( + TapGesture().onEnded { + if !(registerViewModel.username.isEmpty || registerViewModel.phoneNumber.isEmpty || registerViewModel.passwd.isEmpty) { + withAnimation { + self.isShowPopup = true + } + } + } + ) + + Spacer() + + Text("assistant_create_account_using_email_on_our_web_platform") + .default_text_style(styleSize: 15) + .foregroundStyle(Color.grayMain2c700) + .padding(.horizontal, 10) + .frame(maxWidth: .infinity, alignment: .center) + + Button(action: { + UIApplication.shared.open(URL(string: "https://subscribe.linphone.org/register/email")!) + }, label: { + Text("assistant_web_platform_link") + .default_text_style_orange_600(styleSize: 15) + .frame(height: 35) + }) + .padding(.horizontal, 15) + .padding(.vertical, 5) + .cornerRadius(60) + .overlay( + RoundedRectangle(cornerRadius: 60) + .inset(by: 0.5) + .stroke(Color.orangeMain500, lineWidth: 1) + ) + .padding(.bottom) + .frame(maxWidth: .infinity) + } + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal, 20) + + Spacer() + + HStack(alignment: .center) { + + Spacer() + + Text("assistant_already_have_an_account") + .default_text_style(styleSize: 15) + .foregroundStyle(Color.grayMain2c700) + .padding(.horizontal, 10) + + Button(action: { + dismiss() + }, label: { + Text("assistant_account_login") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .padding(.horizontal, 10) + + Spacer() + } + .padding(.bottom) + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) + } } #Preview { diff --git a/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift index b814a2e25..8a728fc78 100644 --- a/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift +++ b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountLoginFragment.swift @@ -36,207 +36,216 @@ struct ThirdPartySipAccountLoginFragment: View { 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.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, -75) - .padding(.leading, -10) - .onTapGesture { - withAnimation { - accountLoginViewModel.domain = "sip.linphone.org" - accountLoginViewModel.transportType = "TLS" - dismiss() - } - } - - Spacer() - } - .padding(.leading) - } - .frame(width: geometry.size.width) - - Text("assistant_login_third_party_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) - .disableAutocorrection(true) - .autocapitalization(.none) - .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.orangeMain500 : Color.gray200, 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) - .disableAutocorrection(true) - .autocapitalization(.none) - .frame(height: 25) - .focused($isPasswordFocused) - } - } - Button(action: { - isSecured.toggle() - }, label: { - Image(self.isSecured ? "eye-slash" : "eye") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .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.orangeMain500 : Color.gray200, lineWidth: 1) - ) - .padding(.bottom) - - Text(String(localized: "sip_address_domain")+"*") - .default_text_style_700(styleSize: 15) - .padding(.bottom, -5) - - TextField("sip.linphone.org", text: $accountLoginViewModel.domain) - .default_text_style(styleSize: 15) - .disableAutocorrection(true) - .autocapitalization(.none) - .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.orangeMain500 : Color.gray200, lineWidth: 1) - ) - .padding(.bottom) - .focused($isDomainFocused) - - Text(String(localized: "sip_address_display_name")) - .default_text_style_700(styleSize: 15) - .padding(.bottom, -5) - - TextField("sip_address_display_name", text: $accountLoginViewModel.displayName) - .default_text_style(styleSize: 15) - .disableAutocorrection(true) - .autocapitalization(.none) - .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.orangeMain500 : Color.gray200, lineWidth: 1) - ) - .padding(.bottom) - .focused($isDisplayNameFocused) - - Text(String(localized: "assistant_sip_account_transport_protocol")) - .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.grayMain2c500) - .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.gray200, lineWidth: 1) - ) - .padding(.bottom) - - Spacer() - - Button(action: { - self.accountLoginViewModel.login() - }, label: { - Text(coreContext.loggedIn ? "manage_account_delete" : "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.orangeMain100 - : Color.orangeMain500) - .cornerRadius(60) - .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty) - .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) - } - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal, 20) + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) + } + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) } } + .navigationTitle("") .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) + } + + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25) + .padding(.all, 10) + .onTapGesture { + withAnimation { + accountLoginViewModel.domain = "sip.linphone.org" + accountLoginViewModel.transportType = "TLS" + dismiss() + } + } + Spacer() + } + + Text("assistant_login_third_party_sip_account") + .default_text_style_800(styleSize: 20) + } + .frame(width: geometry.size.width) + .padding(.top, 10) + .padding(.bottom, 20) + + 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) + .disableAutocorrection(true) + .autocapitalization(.none) + .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.orangeMain500 : Color.gray200, 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) + .disableAutocorrection(true) + .autocapitalization(.none) + .frame(height: 25) + .focused($isPasswordFocused) + } + } + Button(action: { + isSecured.toggle() + }, label: { + Image(self.isSecured ? "eye-slash" : "eye") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .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.orangeMain500 : Color.gray200, lineWidth: 1) + ) + .padding(.bottom) + + Text(String(localized: "sip_address_domain")+"*") + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("sip.linphone.org", text: $accountLoginViewModel.domain) + .default_text_style(styleSize: 15) + .disableAutocorrection(true) + .autocapitalization(.none) + .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.orangeMain500 : Color.gray200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isDomainFocused) + + Text(String(localized: "sip_address_display_name")) + .default_text_style_700(styleSize: 15) + .padding(.bottom, -5) + + TextField("sip_address_display_name", text: $accountLoginViewModel.displayName) + .default_text_style(styleSize: 15) + .disableAutocorrection(true) + .autocapitalization(.none) + .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.orangeMain500 : Color.gray200, lineWidth: 1) + ) + .padding(.bottom) + .focused($isDisplayNameFocused) + + Text(String(localized: "assistant_sip_account_transport_protocol")) + .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.grayMain2c500) + .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.gray200, lineWidth: 1) + ) + .padding(.bottom) + } + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal, 20) + + Spacer() + + Button(action: { + self.accountLoginViewModel.login() + }, label: { + Text(coreContext.loggedIn ? "manage_account_delete" : "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.orangeMain100 + : Color.orangeMain500) + .cornerRadius(60) + .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty) + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal) + .padding(.bottom) + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) } } diff --git a/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift index 7e027730d..8ab788d7a 100644 --- a/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift +++ b/Linphone/UI/Assistant/Fragments/ThirdPartySipAccountWarningFragment.swift @@ -30,154 +30,160 @@ struct ThirdPartySipAccountWarningFragment: View { 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.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - .padding(.all, 10) - .padding(.top, -75) - .padding(.leading, -10) - .onTapGesture { - withAnimation { - dismiss() - } - } - - Spacer() - } - .padding(.leading) - } - .frame(width: geometry.size.width) - - Text("assistant_login_third_party_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("chat-teardrop-text-slash") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20, alignment: .leading) - } - .padding(16) - .background(Color.grayMain2c200) - .cornerRadius(40) - .padding(.horizontal) - - HStack(alignment: .center) { - Image("video-camera-slash") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 20, height: 20, alignment: .leading) - } - .padding(16) - .background(Color.grayMain2c200) - .cornerRadius(40) - .padding(.horizontal) - - Spacer() - } - .padding(.bottom, 40) - - Text(.init(String(format: String(localized: "assistant_third_party_sip_account_warning_explanation"), Bundle.main.displayName))) - .default_text_style(styleSize: 15) - .multilineTextAlignment(.center) - .padding(.bottom) - - HStack { - Spacer() - - HStack { - Text("[linphone.org/contact](https://linphone.org/contact)") - .tint(Color.orangeMain500) - .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.orangeMain500, lineWidth: 1) - ) - - Spacer() - } - .padding(.vertical) - } - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal, 20) - - Spacer() - - Button(action: { - dismiss() - }, label: { - Text("assistant_third_party_sip_account_create_linphone_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.orangeMain500, lineWidth: 1) - ) - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal) - - NavigationLink(destination: { - ThirdPartySipAccountLoginFragment(accountLoginViewModel: accountLoginViewModel) - }, label: { - Text("assistant_third_party_sip_account_warning_ok") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - - }) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .frame(maxWidth: sharedMainViewModel.maxWidth) - .padding(.horizontal) - .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) + } + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) } } .navigationTitle("") .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) } .navigationViewStyle(StackNavigationViewStyle()) .navigationTitle("") .navigationBarHidden(true) } + + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + HStack { + Image("caret-left") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25) + .padding(.all, 10) + .onTapGesture { + withAnimation { + dismiss() + } + } + Spacer() + } + + Text("assistant_login_third_party_sip_account") + .default_text_style_800(styleSize: 20) + } + .frame(width: geometry.size.width) + .padding(.top, 10) + .padding(.bottom, 20) + + Spacer() + + VStack(alignment: .leading) { + HStack { + Spacer() + HStack(alignment: .center) { + Image("chat-teardrop-text-slash") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25, alignment: .leading) + } + .padding(20) + .background(Color.grayMain2c200) + .cornerRadius(40) + .padding(.horizontal) + + HStack(alignment: .center) { + Image("video-camera-slash") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25, alignment: .leading) + } + .padding(20) + .background(Color.grayMain2c200) + .cornerRadius(40) + .padding(.horizontal) + + Spacer() + } + .padding(.bottom, 40) + + Text(.init(String(format: String(localized: "assistant_third_party_sip_account_warning_explanation"), Bundle.main.displayName))) + .default_text_style(styleSize: 15) + .multilineTextAlignment(.center) + .padding(.bottom) + + HStack { + Spacer() + + HStack { + Text("[linphone.org/contact](https://linphone.org/contact)") + .tint(Color.orangeMain500) + .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.orangeMain500, lineWidth: 1) + ) + + Spacer() + } + .padding(.vertical) + } + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal, 20) + + Spacer() + + Button(action: { + dismiss() + }, label: { + Text("assistant_third_party_sip_account_create_linphone_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.orangeMain500, lineWidth: 1) + ) + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal) + + NavigationLink(destination: { + ThirdPartySipAccountLoginFragment(accountLoginViewModel: accountLoginViewModel) + }, label: { + Text("assistant_third_party_sip_account_warning_ok") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .frame(maxWidth: sharedMainViewModel.maxWidth) + .padding(.horizontal) + .padding(.bottom) + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) + } } #Preview { diff --git a/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift b/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift index 468d6aac9..588994bcf 100644 --- a/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift +++ b/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift @@ -33,7 +33,7 @@ class SharedMainViewModel: ObservableObject { let displayProfileModeKey = "display_profile_mode" let defaultAvatarKey = "default_avatar" - var maxWidth = 400.0 + var maxWidth = 600.0 private init() { let preferences = UserDefaults.standard diff --git a/Linphone/UI/Welcome/Fragments/WelcomePage1Fragment.swift b/Linphone/UI/Welcome/Fragments/WelcomePage1Fragment.swift index ad318341f..9d04bfc51 100644 --- a/Linphone/UI/Welcome/Fragments/WelcomePage1Fragment.swift +++ b/Linphone/UI/Welcome/Fragments/WelcomePage1Fragment.swift @@ -39,7 +39,9 @@ struct WelcomePage1Fragment: View { .multilineTextAlignment(.center) } - Spacer() + .padding(.horizontal) + .padding(.bottom, 60) + Spacer() } .frame(maxWidth: .infinity) diff --git a/Linphone/UI/Welcome/Fragments/WelcomePage2Fragment.swift b/Linphone/UI/Welcome/Fragments/WelcomePage2Fragment.swift index 0671ad332..3f9d45cfa 100644 --- a/Linphone/UI/Welcome/Fragments/WelcomePage2Fragment.swift +++ b/Linphone/UI/Welcome/Fragments/WelcomePage2Fragment.swift @@ -39,7 +39,9 @@ struct WelcomePage2Fragment: View { .multilineTextAlignment(.center) } - Spacer() + .padding(.horizontal) + .padding(.bottom, 60) + Spacer() } .frame(maxWidth: .infinity) diff --git a/Linphone/UI/Welcome/Fragments/WelcomePage3Fragment.swift b/Linphone/UI/Welcome/Fragments/WelcomePage3Fragment.swift index 6dd0f61c4..6333a8302 100644 --- a/Linphone/UI/Welcome/Fragments/WelcomePage3Fragment.swift +++ b/Linphone/UI/Welcome/Fragments/WelcomePage3Fragment.swift @@ -39,7 +39,9 @@ struct WelcomePage3Fragment: View { .multilineTextAlignment(.center) } - Spacer() + .padding(.horizontal) + .padding(.bottom, 60) + Spacer() } .frame(maxWidth: .infinity) diff --git a/Linphone/UI/Welcome/WelcomeView.swift b/Linphone/UI/Welcome/WelcomeView.swift index 73ef01cbf..d55cd0e5f 100644 --- a/Linphone/UI/Welcome/WelcomeView.swift +++ b/Linphone/UI/Welcome/WelcomeView.swift @@ -28,118 +28,131 @@ struct WelcomeView: View { var body: some View { NavigationView { GeometryReader { geometry in - ScrollView { - VStack { - ZStack { - Image("mountain") - .resizable() - .scaledToFill() - .frame(width: geometry.size.width, height: 100) - .clipped() - - VStack(alignment: .trailing) { - NavigationLink(destination: { - PermissionsFragment() - }, label: { - Text("welcome_carousel_skip") - .underline() - .default_text_style_600(styleSize: 15) - - }) - .padding(.top, -35) - .padding(.trailing, 20) - .simultaneousGesture( - TapGesture().onEnded { - self.index = 2 - } - ) - Text("welcome_page_title") - .welcome_text_style_white_800(styleSize: 35) - .padding(.trailing, 100) - .frame(width: geometry.size.width) - .padding(.bottom, -25) - Text(String(format: String(localized: "welcome_page_subtitle"), Bundle.main.displayName)) - .welcome_text_style_white_800(styleSize: 25) - .padding(.leading, 100) - .frame(width: geometry.size.width) - .padding(.bottom, -10) - } - .frame(width: geometry.size.width) - } - .padding(.top, 35) - .padding(.bottom, 10) - - Spacer() - - VStack { - TabView(selection: $index) { - ForEach((0..<3), id: \.self) { index in - if index == 0 { - WelcomePage1Fragment() - } else if index == 1 { - WelcomePage2Fragment() - } else if index == 2 { - WelcomePage3Fragment() - } else { - WelcomePage1Fragment() - } - } - } - .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) - .frame(minHeight: 300) - .onAppear { - setupAppearance() - } - } - - Spacer() - - if index == 2 { - NavigationLink(destination: { - PermissionsFragment() - }, label: { - Text("start") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - - }) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .padding(.horizontal) - .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) - .frame(maxWidth: sharedMainViewModel.maxWidth) - } else { - Button(action: { - withAnimation { - index += 1 - } - }, label: { - Text("next") - .default_text_style_white_600(styleSize: 20) - .frame(height: 35) - .frame(maxWidth: .infinity) - }) - .padding(.horizontal, 20) - .padding(.vertical, 10) - .background(Color.orangeMain500) - .cornerRadius(60) - .padding(.horizontal) - .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) - .frame(maxWidth: sharedMainViewModel.maxWidth) - } + if #available(iOS 16.4, *) { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) + } + .scrollBounceBehavior(.basedOnSize) + } else { + ScrollView(.vertical) { + innerScrollView(geometry: geometry) } - .frame(minHeight: geometry.size.height) } } .navigationTitle("") .navigationBarHidden(true) + .edgesIgnoringSafeArea(.bottom) + .edgesIgnoringSafeArea(.horizontal) } .navigationViewStyle(StackNavigationViewStyle()) } + func innerScrollView(geometry: GeometryProxy) -> some View { + VStack { + ZStack { + VStack(alignment: .trailing) { + NavigationLink(destination: { + PermissionsFragment() + }, label: { + Text("welcome_carousel_skip") + .underline() + .default_text_style_600(styleSize: 15) + + }) + .padding(.top, -35) + .padding(.trailing, 20) + .simultaneousGesture( + TapGesture().onEnded { + self.index = 2 + } + ) + Text("welcome_page_title") + .default_text_style_800(styleSize: 35) + .padding(.trailing, 100) + .frame(width: geometry.size.width) + .padding(.bottom, -25) + Text(String(format: String(localized: "welcome_page_subtitle"), Bundle.main.displayName)) + .default_text_style_800(styleSize: 25) + .padding(.leading, 100) + .frame(width: geometry.size.width) + .padding(.bottom, -10) + } + .frame(width: geometry.size.width) + } + .padding(.top, 35) + .padding(.bottom, 10) + + Spacer() + + VStack { + TabView(selection: $index) { + ForEach((0..<3), id: \.self) { index in + if index == 0 { + WelcomePage1Fragment() + } else if index == 1 { + WelcomePage2Fragment() + } else if index == 2 { + WelcomePage3Fragment() + } else { + WelcomePage1Fragment() + } + } + } + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) + .frame(minHeight: 300) + .onAppear { + setupAppearance() + } + } + + Spacer() + + if index == 2 { + NavigationLink(destination: { + PermissionsFragment() + }, label: { + Text("start") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .padding(.horizontal) + .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) + .frame(maxWidth: sharedMainViewModel.maxWidth) + } else { + Button(action: { + withAnimation { + index += 1 + } + }, label: { + Text("next") + .default_text_style_white_600(styleSize: 20) + .frame(height: 35) + .frame(maxWidth: .infinity) + }) + .padding(.horizontal, 20) + .padding(.vertical, 10) + .background(Color.orangeMain500) + .cornerRadius(60) + .padding(.horizontal) + .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) + .frame(maxWidth: sharedMainViewModel.maxWidth) + } + + Image("mountain2") + .resizable() + .scaledToFill() + .frame(width: geometry.size.width, height: 60) + .clipped() + } + .frame(minHeight: geometry.size.height) + } + func setupAppearance() { UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.orangeMain500) if #available(iOS 16.0, *) {