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 000000000..d1880df74 Binary files /dev/null and b/Linphone/Assets.xcassets/mountain2.imageset/mountain2.png differ 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, *) {