mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 02:58:07 +00:00
Add advanced settings to third-party SIP account login view
This commit is contained in:
parent
1d0df11c61
commit
4cf1dbd8b5
8 changed files with 163 additions and 22 deletions
|
|
@ -93,6 +93,7 @@
|
|||
"assistant_third_party_sip_account_warning_explanation" = "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.";
|
||||
"assistant_third_party_sip_account_warning_ok" = "I understand";
|
||||
"assistant_web_platform_link" = "subscribe.linphone.org";
|
||||
"authentication_id" = "Authentication ID (if different)";
|
||||
"bottom_navigation_calls_label" = "Calls";
|
||||
"bottom_navigation_contacts_label" = "Contacts";
|
||||
"bottom_navigation_conversations_label" = "Conversations";
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@
|
|||
"assistant_third_party_sip_account_warning_explanation" = "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.";
|
||||
"assistant_third_party_sip_account_warning_ok" = "J’ai compris";
|
||||
"assistant_web_platform_link" = "subscribe.linphone.org";
|
||||
"authentication_id" = "Identifiant de connexion (si différent)";
|
||||
"bottom_navigation_calls_label" = "Appels";
|
||||
"bottom_navigation_contacts_label" = "Contacts";
|
||||
"bottom_navigation_conversations_label" = "Conversations";
|
||||
|
|
|
|||
|
|
@ -18,12 +18,14 @@
|
|||
*/
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
struct LoginFragment: View {
|
||||
|
||||
@ObservedObject private var coreContext = CoreContext.shared
|
||||
|
||||
@StateObject private var accountLoginViewModel = AccountLoginViewModel()
|
||||
@StateObject private var keyboard = KeyboardResponder()
|
||||
|
||||
@State private var isSecured: Bool = true
|
||||
|
||||
|
|
@ -377,6 +379,7 @@ struct LoginFragment: View {
|
|||
.clipped()
|
||||
}
|
||||
.frame(minHeight: geometry.size.height)
|
||||
.padding(.bottom, keyboard.currentHeight)
|
||||
}
|
||||
|
||||
func acceptGeneralTerms() {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ struct RegisterFragment: View {
|
|||
@ObservedObject var registerViewModel: RegisterViewModel
|
||||
@ObservedObject var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
@StateObject private var keyboard = KeyboardResponder()
|
||||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
@State private var isSecured: Bool = true
|
||||
|
|
@ -181,14 +183,6 @@ struct RegisterFragment: View {
|
|||
.autocapitalization(.none)
|
||||
.padding(.leading, 5)
|
||||
.keyboardType(.numberPad)
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .keyboard) {
|
||||
Spacer()
|
||||
Button("Done") {
|
||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: registerViewModel.phoneNumber) { _ in
|
||||
if !registerViewModel.phoneNumberError.isEmpty {
|
||||
registerViewModel.phoneNumberError = ""
|
||||
|
|
@ -355,11 +349,8 @@ struct RegisterFragment: View {
|
|||
.clipped()
|
||||
}
|
||||
.frame(minHeight: geometry.size.height)
|
||||
.padding(.bottom, keyboard.currentHeight)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
RegisterFragment(registerViewModel: RegisterViewModel())
|
||||
}
|
||||
|
||||
// swiftlint:enable line_length
|
||||
|
|
|
|||
|
|
@ -24,25 +24,61 @@ struct ThirdPartySipAccountLoginFragment: View {
|
|||
@ObservedObject private var coreContext = CoreContext.shared
|
||||
@ObservedObject var accountLoginViewModel: AccountLoginViewModel
|
||||
|
||||
@StateObject private var keyboard = KeyboardResponder()
|
||||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
@State private var isSecured: Bool = true
|
||||
@State private var advancedSettingsIsOpen: Bool = false
|
||||
|
||||
@FocusState var isNameFocused: Bool
|
||||
@FocusState var isPasswordFocused: Bool
|
||||
@FocusState var isDomainFocused: Bool
|
||||
@FocusState var isDisplayNameFocused: Bool
|
||||
@FocusState var isSipProxyUrlFocused: Bool
|
||||
@FocusState var isAuthIdFocused: Bool
|
||||
@FocusState var isOutboundProxyFocused: Bool
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
if #available(iOS 16.4, *) {
|
||||
ScrollView(.vertical) {
|
||||
innerScrollView(geometry: geometry)
|
||||
}
|
||||
.scrollBounceBehavior(.basedOnSize)
|
||||
} else {
|
||||
ScrollView(.vertical) {
|
||||
innerScrollView(geometry: geometry)
|
||||
ScrollViewReader { proxy in
|
||||
if #available(iOS 16.4, *) {
|
||||
ScrollView(.vertical) {
|
||||
innerScrollView(geometry: geometry)
|
||||
}
|
||||
.scrollBounceBehavior(.basedOnSize)
|
||||
.onChange(of: isAuthIdFocused) { field in
|
||||
if field {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
proxy.scrollTo(2, anchor: .top)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: isOutboundProxyFocused) { field in
|
||||
if field {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
proxy.scrollTo(2, anchor: .top)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ScrollView(.vertical) {
|
||||
innerScrollView(geometry: geometry)
|
||||
}
|
||||
.onChange(of: isAuthIdFocused) { field in
|
||||
if field {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
proxy.scrollTo(2, anchor: .top)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onChange(of: isOutboundProxyFocused) { field in
|
||||
if field {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
proxy.scrollTo(2, anchor: .top)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -208,6 +244,74 @@ struct ThirdPartySipAccountLoginFragment: View {
|
|||
.stroke(Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.padding(.bottom)
|
||||
|
||||
HStack(alignment: .center) {
|
||||
Text("settings_advanced_title")
|
||||
.default_text_style_800(styleSize: 18)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(advancedSettingsIsOpen ? "caret-up" : "caret-down")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 10)
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
advancedSettingsIsOpen.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
if advancedSettingsIsOpen {
|
||||
VStack(alignment: .leading) {
|
||||
Text("authentication_id")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("authentication_id", text: $accountLoginViewModel.authId)
|
||||
.id(1)
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(height: 25)
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 15)
|
||||
.background(.white)
|
||||
.cornerRadius(60)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 60)
|
||||
.inset(by: 0.5)
|
||||
.stroke(isAuthIdFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isAuthIdFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_sip_proxy_url_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_sip_proxy_url_title", text: $accountLoginViewModel.outboundProxy)
|
||||
.id(2)
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(height: 25)
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 15)
|
||||
.background(.white)
|
||||
.cornerRadius(60)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 60)
|
||||
.inset(by: 0.5)
|
||||
.stroke(isOutboundProxyFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isOutboundProxyFocused)
|
||||
}
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: SharedMainViewModel.shared.maxWidth)
|
||||
.padding(.horizontal, 20)
|
||||
|
|
@ -241,6 +345,7 @@ struct ThirdPartySipAccountLoginFragment: View {
|
|||
.clipped()
|
||||
}
|
||||
.frame(minHeight: geometry.size.height)
|
||||
.padding(.bottom, keyboard.currentHeight)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ class AccountLoginViewModel: ObservableObject {
|
|||
@Published var domain: String = "sip.linphone.org"
|
||||
@Published var displayName: String = ""
|
||||
@Published var transportType: String = "TLS"
|
||||
@Published var authId: String = ""
|
||||
@Published var outboundProxy: String = ""
|
||||
|
||||
private var mCoreDelegate: CoreDelegate!
|
||||
|
||||
|
|
@ -83,7 +85,7 @@ class AccountLoginViewModel: ObservableObject {
|
|||
// The realm will be determined automatically from the first register, as well as the algorithm
|
||||
let authInfo = try Factory.Instance.createAuthInfo(
|
||||
username: self.username,
|
||||
userid: "",
|
||||
userid: self.authId,
|
||||
passwd: self.passwd,
|
||||
ha1: "",
|
||||
realm: "",
|
||||
|
|
@ -100,7 +102,15 @@ class AccountLoginViewModel: ObservableObject {
|
|||
try accountParams.setIdentityaddress(newValue: identity)
|
||||
|
||||
// We also need to configure where the proxy server is located
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + self.domain))
|
||||
var serverAddress: Address
|
||||
if (!self.outboundProxy.isEmpty) {
|
||||
let server = self.outboundProxy.starts(with: "sip:") ? self.outboundProxy : String("sip:" + self.outboundProxy)
|
||||
serverAddress = try Factory.Instance.createAddress(addr: server)
|
||||
} else {
|
||||
serverAddress = try Factory.Instance.createAddress(addr: String("sip:" + self.domain))
|
||||
}
|
||||
|
||||
let address = serverAddress
|
||||
|
||||
// We use the Address object to easily set the transport protocol
|
||||
try address.setTransport(newValue: transport)
|
||||
|
|
@ -156,6 +166,8 @@ class AccountLoginViewModel: ObservableObject {
|
|||
DispatchQueue.main.async {
|
||||
self.domain = "sip.linphone.org"
|
||||
self.transportType = "TLS"
|
||||
self.authId = ""
|
||||
self.outboundProxy = ""
|
||||
}
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
|
|
|
|||
24
Linphone/Utils/KeyboardResponder.swift
Normal file
24
Linphone/Utils/KeyboardResponder.swift
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
final class KeyboardResponder: ObservableObject {
|
||||
@Published var currentHeight: CGFloat = 0
|
||||
|
||||
private var cancellables: Set<AnyCancellable> = []
|
||||
|
||||
init() {
|
||||
let willShow = NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
|
||||
.map { notification -> CGFloat in
|
||||
(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height ?? 0
|
||||
}
|
||||
|
||||
let willHide = NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)
|
||||
.map { _ in CGFloat(0) }
|
||||
|
||||
Publishers.Merge(willShow, willHide)
|
||||
.receive(on: RunLoop.main)
|
||||
.assign(to: \.currentHeight, on: self)
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
|
@ -108,6 +108,7 @@
|
|||
D73449992BC6932A00778C56 /* MeetingWaitingRoomFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D73449982BC6932A00778C56 /* MeetingWaitingRoomFragment.swift */; };
|
||||
D734499B2BC694C900778C56 /* MeetingWaitingRoomViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D734499A2BC694C900778C56 /* MeetingWaitingRoomViewModel.swift */; };
|
||||
D737AEEF2DA011F2005C1280 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D737AEED2DA011F2005C1280 /* Localizable.strings */; };
|
||||
D738ACEE2E857BF10039F7D1 /* KeyboardResponder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D738ACED2E857BEF0039F7D1 /* KeyboardResponder.swift */; };
|
||||
D7458F392E0BDCF4000C957A /* linphoneExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D7458F2F2E0BDCF4000C957A /* linphoneExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */; };
|
||||
D748BF2E2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */; };
|
||||
|
|
@ -334,6 +335,7 @@
|
|||
D734499A2BC694C900778C56 /* MeetingWaitingRoomViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingWaitingRoomViewModel.swift; sourceTree = "<group>"; };
|
||||
D737AEEE2DA011F2005C1280 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable/en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
D737AEF02DA01203005C1280 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = Localizable/fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
D738ACED2E857BEF0039F7D1 /* KeyboardResponder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardResponder.swift; sourceTree = "<group>"; };
|
||||
D7458F2F2E0BDCF4000C957A /* linphoneExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = linphoneExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountLoginFragment.swift; sourceTree = "<group>"; };
|
||||
D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountWarningFragment.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -583,6 +585,7 @@
|
|||
D717071C2AC591EF0037746F /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D738ACED2E857BEF0039F7D1 /* KeyboardResponder.swift */,
|
||||
D7DF8BE82E2104E5003A3BC7 /* EmojiPickerView.swift */,
|
||||
D703F7072DC8C5FF005B8F75 /* FilePicker.swift */,
|
||||
D717A10D2CEB770D00849D92 /* ShareSheetController.swift */,
|
||||
|
|
@ -1279,6 +1282,7 @@
|
|||
D7DC096F2CFA1D7600A6D47C /* AccountProfileFragment.swift in Sources */,
|
||||
D717A10E2CEB772300849D92 /* ShareSheetController.swift in Sources */,
|
||||
66C491FD2B24D36500CEA16D /* AudioRouteUtils.swift in Sources */,
|
||||
D738ACEE2E857BF10039F7D1 /* KeyboardResponder.swift in Sources */,
|
||||
D70959F12B8DF3EC0014AC0B /* ConversationModel.swift in Sources */,
|
||||
C6DC4E3D2C199C4E009096FD /* BundleExtenion.swift in Sources */,
|
||||
D7343FEF2D3FE16C0059D784 /* HelpViewModel.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue