forked from mirrors/linphone-iphone
Add account settings view
This commit is contained in:
parent
35eb8cb8df
commit
6d116b6cec
5 changed files with 1781 additions and 501 deletions
|
|
@ -151,6 +151,8 @@
|
|||
D7C3650E2AF15BF200FE6142 /* PhotoPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */; };
|
||||
D7C48DF42AFA66F900D938CB /* EditContactController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C48DF32AFA66F900D938CB /* EditContactController.swift */; };
|
||||
D7C48DF62AFCDF4700D938CB /* ContactInnerActionsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C48DF52AFCDF4700D938CB /* ContactInnerActionsFragment.swift */; };
|
||||
D7C500402D27F16C00DD53EC /* AccountSettingsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C5003F2D27F16900DD53EC /* AccountSettingsFragment.swift */; };
|
||||
D7C500422D2BE98100DD53EC /* AccountSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C500412D2BE96E00DD53EC /* AccountSettingsViewModel.swift */; };
|
||||
D7CEE0352B7A210300FD79B7 /* ConversationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE0342B7A210300FD79B7 /* ConversationsView.swift */; };
|
||||
D7CEE0382B7A214F00FD79B7 /* ConversationsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE0372B7A214F00FD79B7 /* ConversationsListViewModel.swift */; };
|
||||
D7CEE03B2B7A234200FD79B7 /* ConversationsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7CEE03A2B7A234200FD79B7 /* ConversationsFragment.swift */; };
|
||||
|
|
@ -347,6 +349,8 @@
|
|||
D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPicker.swift; sourceTree = "<group>"; };
|
||||
D7C48DF32AFA66F900D938CB /* EditContactController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditContactController.swift; sourceTree = "<group>"; };
|
||||
D7C48DF52AFCDF4700D938CB /* ContactInnerActionsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactInnerActionsFragment.swift; sourceTree = "<group>"; };
|
||||
D7C5003F2D27F16900DD53EC /* AccountSettingsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingsFragment.swift; sourceTree = "<group>"; };
|
||||
D7C500412D2BE96E00DD53EC /* AccountSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingsViewModel.swift; sourceTree = "<group>"; };
|
||||
D7CEE0342B7A210300FD79B7 /* ConversationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsView.swift; sourceTree = "<group>"; };
|
||||
D7CEE0372B7A214F00FD79B7 /* ConversationsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsListViewModel.swift; sourceTree = "<group>"; };
|
||||
D7CEE03A2B7A234200FD79B7 /* ConversationsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsFragment.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -927,6 +931,7 @@
|
|||
D7DC096B2CFA192F00A6D47C /* Fragments */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7C5003F2D27F16900DD53EC /* AccountSettingsFragment.swift */,
|
||||
D7DC096E2CFA1D7400A6D47C /* AccountProfileFragment.swift */,
|
||||
);
|
||||
path = Fragments;
|
||||
|
|
@ -942,6 +947,7 @@
|
|||
D7DC096D2CFA194600A6D47C /* ViewModel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7C500412D2BE96E00DD53EC /* AccountSettingsViewModel.swift */,
|
||||
D7DC09702CFDBF8300A6D47C /* AccountProfileViewModel.swift */,
|
||||
);
|
||||
path = ViewModel;
|
||||
|
|
@ -1189,6 +1195,7 @@
|
|||
C6A5A9452C10B6270070FEA4 /* OIDAuthStateExtension.swift in Sources */,
|
||||
D732A90F2B04C3B400DB42BA /* HistoryFragment.swift in Sources */,
|
||||
D79F1C162CD3D6AD00FF0A05 /* ConversationInfoFragment.swift in Sources */,
|
||||
D7C500422D2BE98100DD53EC /* AccountSettingsViewModel.swift in Sources */,
|
||||
D79622342B1DFE600037EACD /* DialerBottomSheet.swift in Sources */,
|
||||
C67586B02C09F247002E77BF /* URIHandler.swift in Sources */,
|
||||
C62817282C1B389700DBA646 /* SideMenuAccountRow.swift in Sources */,
|
||||
|
|
@ -1214,6 +1221,7 @@
|
|||
D7702EF22AC7205000557C00 /* WelcomeView.swift in Sources */,
|
||||
D732A9152B04C7FE00DB42BA /* HistoryListViewModel.swift in Sources */,
|
||||
6646A7A32BB2E224006B842A /* ScheduleMeetingFragment.swift in Sources */,
|
||||
D7C500402D27F16C00DD53EC /* AccountSettingsFragment.swift in Sources */,
|
||||
D71FCA7F2AE1397200D2E43E /* ContactsListViewModel.swift in Sources */,
|
||||
D71FCA812AE14CFC00D2E43E /* ContactsListFragment.swift in Sources */,
|
||||
D734499B2BC694C900778C56 /* MeetingWaitingRoomViewModel.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -150,6 +150,421 @@
|
|||
},
|
||||
"9" : {
|
||||
|
||||
},
|
||||
"A subject and at least one participant is required to create a meeting" : {
|
||||
|
||||
},
|
||||
"Accept all" : {
|
||||
|
||||
},
|
||||
"Account successfully logged out" : {
|
||||
|
||||
},
|
||||
"account_settings_audio_video_conference_factory_uri_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Audio/video conference factory URI"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URI de l'usine à réunions"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_avpf_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "AVPF"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "AVPF"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_bundle_mode_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Bundle mode"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Mode \"bundle\""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_ccmp_server_url_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "CCMP server URL"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URL du serveur CCMP"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_conference_factory_uri_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Conference factory URI"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URI de l'usine à conversations"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_cpim_in_basic_conversations_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Use CPIM in \"basic\" conversations"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Utiliser CPIM dans les conversations \"basiques\""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_enable_ice_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Enable ICE"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Activer ICE"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_enable_turn_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Enable TURN"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Activer TURN"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_expire_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Expire (in seconds)"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Expiration (en secondes)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_im_encryption_mandatory_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "IM encryption mandatory"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Chiffrement obligatoire des conversations"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_lime_server_url_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "E2E encryption keys server URL"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URL du serveur d'échange de clés de chiffrement"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_mwi_uri_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "MWI server URI (Message Waiting Indicator)"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URI du serveur MWI (Message Waiting Indicator)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_nat_policy_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "NAT policy settings"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Paramètres de politique NAT"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_outbound_proxy_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Outbound proxy"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Serveur mandataire sortant"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_push_notification_not_available_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Push notifications aren't available!"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Les notifications poussées ne sont pas disponibles !"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_push_notification_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Allow push notifications"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Autoriser les notifications poussées"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_sip_proxy_url_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "SIP proxy server URL"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URL du serveur mandataire"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_stun_server_url_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "STUN/TURN server URL"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URL du serveur STUN/TURN"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Account settings"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Paramètres de compte"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_turn_password_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "TURN password"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Mot de passe TURN"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_turn_username_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "TURN username"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Utilisateur TURN"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_update_password_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Update password"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Mettre à jour le mot de passe"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_settings_voicemail_uri_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Voicemail URI"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "URI du serveur de messagerie vocale"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Active" : {
|
||||
|
||||
},
|
||||
"Administrateur" : {
|
||||
|
||||
},
|
||||
"All calls will be removed from the history." : {
|
||||
|
||||
},
|
||||
"All contacts" : {
|
||||
|
||||
},
|
||||
"All modifications will be canceled." : {
|
||||
|
||||
},
|
||||
"assistant_account_create" : {
|
||||
"localizations" : {
|
||||
|
|
@ -5266,6 +5681,32 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"Send cancellation notifications" : {
|
||||
|
||||
},
|
||||
"Send Logs" : {
|
||||
|
||||
},
|
||||
"Send notification to participants ?" : {
|
||||
|
||||
},
|
||||
"settings_advanced_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Advanced settings"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "needs_review",
|
||||
"value" : "Paramètres avancés"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings_title" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ struct AccountProfileFragment: View {
|
|||
private let avatarSize = 100.0
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack {
|
||||
VStack(spacing: 1) {
|
||||
Rectangle()
|
||||
|
|
@ -542,8 +543,13 @@ struct AccountProfileFragment: View {
|
|||
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 18) {
|
||||
Button(action: {
|
||||
}, label: {
|
||||
if accountProfileViewModel.accountModelIndex != nil && CoreContext.shared.accounts.count > accountProfileViewModel.accountModelIndex! {
|
||||
NavigationLink(
|
||||
destination:
|
||||
AccountSettingsFragment(
|
||||
accountModel: CoreContext.shared.accounts[accountProfileViewModel.accountModelIndex!]
|
||||
),
|
||||
label: {
|
||||
HStack {
|
||||
Image("gear")
|
||||
.renderingMode(.template)
|
||||
|
|
@ -556,7 +562,9 @@ struct AccountProfileFragment: View {
|
|||
.default_text_style(styleSize: 16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
|
|
@ -643,6 +651,10 @@ struct AccountProfileFragment: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("")
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle())
|
||||
}
|
||||
|
||||
func saveImage() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,598 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// swiftlint:disable type_body_length
|
||||
struct AccountSettingsFragment: View {
|
||||
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
@StateObject private var accountSettingsViewModel: AccountSettingsViewModel
|
||||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
@State var natPolicySettingsIsOpen: Bool = false
|
||||
@State var advancedSettingsIsOpen: Bool = false
|
||||
@State var isSecured: Bool = true
|
||||
|
||||
@FocusState var isVoicemailUriFocused: Bool
|
||||
@FocusState var isMwiUriFocused: Bool
|
||||
@FocusState var isStunServerUriFocused: Bool
|
||||
@FocusState var isTurnUsernameFocused: Bool
|
||||
@FocusState var isTurnPasswordFocused: Bool
|
||||
@FocusState var isSipProxyUrlFocused: Bool
|
||||
@FocusState var isSettingsExpireFocused: Bool
|
||||
@FocusState var isConferenceFactoryUriFocused: Bool
|
||||
@FocusState var isAudioVideoConferenceFactoryUriFocused: Bool
|
||||
@FocusState var isCcmpServerUrlFocused: Bool
|
||||
@FocusState var isLimeServerUrlFocused: Bool
|
||||
|
||||
init(accountModel: AccountModel) {
|
||||
_accountSettingsViewModel = StateObject(wrappedValue: AccountSettingsViewModel(accountModel: accountModel))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
VStack(spacing: 1) {
|
||||
Rectangle()
|
||||
.foregroundColor(Color.orangeMain500)
|
||||
.edgesIgnoringSafeArea(.top)
|
||||
.frame(height: 0)
|
||||
|
||||
HStack {
|
||||
Image("caret-left")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.orangeMain500)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
.padding(.top, 4)
|
||||
.padding(.leading, -10)
|
||||
.onTapGesture {
|
||||
accountSettingsViewModel.saveChanges()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
Text("account_settings_title")
|
||||
.default_text_style_orange_800(styleSize: 16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 4)
|
||||
.lineLimit(1)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 50)
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom, 4)
|
||||
.background(.white)
|
||||
|
||||
ScrollView {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 30) {
|
||||
Toggle("account_settings_push_notification_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.pushNotification },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.pushNotification.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
Toggle("account_settings_im_encryption_mandatory_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.imEncryptionMandatory },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.imEncryptionMandatory.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_voicemail_uri_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_voicemail_uri_title", text: Binding(
|
||||
get: { accountSettingsViewModel.voicemailUri },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.voicemailUri = newValue
|
||||
}
|
||||
))
|
||||
.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(isVoicemailUriFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isVoicemailUriFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_mwi_uri_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_mwi_uri_title", text: Binding(
|
||||
get: { accountSettingsViewModel.mwiUri },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.mwiUri = newValue
|
||||
}
|
||||
))
|
||||
.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(isMwiUriFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isMwiUriFocused)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 30)
|
||||
.padding(.horizontal, 20)
|
||||
}
|
||||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
.padding(.horizontal)
|
||||
.padding(.top, 10)
|
||||
.background(Color.gray100)
|
||||
|
||||
HStack(alignment: .center) {
|
||||
Text("account_settings_nat_policy_title")
|
||||
.default_text_style_800(styleSize: 18)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Spacer()
|
||||
|
||||
Image(natPolicySettingsIsOpen ? "caret-up" : "caret-down")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
.frame(width: 25, height: 25, alignment: .leading)
|
||||
.padding(.all, 10)
|
||||
}
|
||||
.padding(.top, 30)
|
||||
.padding(.bottom, 10)
|
||||
.padding(.horizontal, 20)
|
||||
.background(Color.gray100)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
natPolicySettingsIsOpen.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
if natPolicySettingsIsOpen {
|
||||
if accountSettingsViewModel.accountModel.avatarModel != nil {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 30) {
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_stun_server_url_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_stun_server_url_title", text: Binding(
|
||||
get: { accountSettingsViewModel.stunServerUrl },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.stunServerUrl = newValue
|
||||
}
|
||||
))
|
||||
.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(isStunServerUriFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isStunServerUriFocused)
|
||||
}
|
||||
|
||||
Toggle("account_settings_enable_ice_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.enableIce },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.enableIce.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
Toggle("account_settings_enable_turn_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.enableTurn },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.enableTurn.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_turn_username_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_turn_username_title", text: Binding(
|
||||
get: { accountSettingsViewModel.turnUsername },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.turnUsername = newValue
|
||||
}
|
||||
))
|
||||
.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(isTurnUsernameFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isTurnUsernameFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_turn_password_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
ZStack(alignment: .trailing) {
|
||||
Group {
|
||||
if isSecured {
|
||||
SecureField("account_settings_turn_password_title", text: Binding(
|
||||
get: { accountSettingsViewModel.turnPassword },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.turnPassword = newValue
|
||||
}
|
||||
))
|
||||
.default_text_style(styleSize: 15)
|
||||
.frame(height: 25)
|
||||
.focused($isTurnPasswordFocused)
|
||||
} else {
|
||||
TextField("account_settings_turn_password_title", text: Binding(
|
||||
get: { accountSettingsViewModel.turnPassword },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.turnPassword = newValue
|
||||
}
|
||||
))
|
||||
.default_text_style(styleSize: 15)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.frame(height: 25)
|
||||
.focused($isTurnPasswordFocused)
|
||||
}
|
||||
}
|
||||
|
||||
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(isTurnPasswordFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 30)
|
||||
.padding(.horizontal, 20)
|
||||
}
|
||||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
.padding(.horizontal)
|
||||
.zIndex(-1)
|
||||
.transition(.move(edge: .top))
|
||||
}
|
||||
}
|
||||
|
||||
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, 30)
|
||||
.padding(.bottom, 10)
|
||||
.padding(.horizontal, 20)
|
||||
.background(Color.gray100)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
advancedSettingsIsOpen.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
if advancedSettingsIsOpen {
|
||||
if accountSettingsViewModel.accountModel.avatarModel != nil {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 30) {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Transport")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
Menu {
|
||||
Button("TLS") { accountSettingsViewModel.transport = "TLS" }
|
||||
Button("TCP") { accountSettingsViewModel.transport = "TCP" }
|
||||
Button("UDP") { accountSettingsViewModel.transport = "UDP" }
|
||||
} label: {
|
||||
Text(accountSettingsViewModel.transport)
|
||||
.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)
|
||||
)
|
||||
}
|
||||
|
||||
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: Binding(
|
||||
get: { accountSettingsViewModel.sipProxyUrl },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.sipProxyUrl = newValue
|
||||
}
|
||||
))
|
||||
.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(isSipProxyUrlFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isSipProxyUrlFocused)
|
||||
}
|
||||
|
||||
Toggle("account_settings_outbound_proxy_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.outboundProxy },
|
||||
set: { _ in
|
||||
//accountProfileViewModel.toggleRegister()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
Toggle("account_settings_avpf_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.avpf },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.avpf.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
Toggle("account_settings_bundle_mode_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.bundleMode },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.bundleMode.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
Toggle("account_settings_cpim_in_basic_conversations_title", isOn: Binding(
|
||||
get: { accountSettingsViewModel.cpimInBasicConversations },
|
||||
set: { _ in
|
||||
accountSettingsViewModel.cpimInBasicConversations.toggle()
|
||||
}
|
||||
))
|
||||
.default_text_style_700(styleSize: 15)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_expire_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_expire_title", text: Binding(
|
||||
get: { accountSettingsViewModel.expire },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.expire = newValue
|
||||
}
|
||||
))
|
||||
.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(isSettingsExpireFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isSettingsExpireFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_conference_factory_uri_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_conference_factory_uri_title", text: Binding(
|
||||
get: { accountSettingsViewModel.conferenceFactoryUri },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.conferenceFactoryUri = newValue
|
||||
}
|
||||
))
|
||||
.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(isConferenceFactoryUriFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isConferenceFactoryUriFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_audio_video_conference_factory_uri_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_audio_video_conference_factory_uri_title", text: Binding(
|
||||
get: { accountSettingsViewModel.audioVideoConferenceFactoryUri },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.audioVideoConferenceFactoryUri = newValue
|
||||
}
|
||||
))
|
||||
.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(isAudioVideoConferenceFactoryUriFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isAudioVideoConferenceFactoryUriFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_ccmp_server_url_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_ccmp_server_url_title", text: Binding(
|
||||
get: { accountSettingsViewModel.ccmpServerUrl },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.ccmpServerUrl = newValue
|
||||
}
|
||||
))
|
||||
.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(isCcmpServerUrlFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isCcmpServerUrlFocused)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
Text("account_settings_lime_server_url_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
TextField("account_settings_lime_server_url_title", text: Binding(
|
||||
get: { accountSettingsViewModel.limeServerUrl },
|
||||
set: { newValue in
|
||||
accountSettingsViewModel.limeServerUrl = newValue
|
||||
}
|
||||
))
|
||||
.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(isLimeServerUrlFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
|
||||
)
|
||||
.focused($isLimeServerUrlFocused)
|
||||
}
|
||||
|
||||
/*
|
||||
Button {
|
||||
// TODO Update password
|
||||
} label: {
|
||||
Text("account_settings_update_password_title")
|
||||
.default_text_style_700(styleSize: 15)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
*/
|
||||
}
|
||||
.padding(.vertical, 30)
|
||||
.padding(.horizontal, 20)
|
||||
}
|
||||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
.padding(.horizontal)
|
||||
.zIndex(-2)
|
||||
.transition(.move(edge: .top))
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: sharedMainViewModel.maxWidth)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.background(Color.gray100)
|
||||
}
|
||||
.background(Color.gray100)
|
||||
}
|
||||
.navigationTitle("")
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
// swiftlint:enable type_body_length
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import linphonesw
|
||||
|
||||
class AccountSettingsViewModel: ObservableObject {
|
||||
|
||||
static let TAG = "[AccountSettingsViewModel]"
|
||||
|
||||
@Published var accountModel: AccountModel
|
||||
|
||||
@Published var pushNotification: Bool
|
||||
@Published var imEncryptionMandatory: Bool
|
||||
@Published var voicemailUri: String
|
||||
@Published var mwiUri: String
|
||||
@Published var stunServerUrl: String
|
||||
@Published var enableIce: Bool
|
||||
@Published var enableTurn: Bool
|
||||
@Published var turnUsername: String
|
||||
@Published var turnPassword: String
|
||||
@Published var transport: String
|
||||
@Published var sipProxyUrl: String
|
||||
@Published var outboundProxy: Bool
|
||||
@Published var avpf: Bool
|
||||
@Published var bundleMode: Bool
|
||||
@Published var cpimInBasicConversations: Bool
|
||||
@Published var expire: String
|
||||
@Published var conferenceFactoryUri: String
|
||||
@Published var audioVideoConferenceFactoryUri: String
|
||||
@Published var ccmpServerUrl: String
|
||||
@Published var limeServerUrl: String
|
||||
|
||||
private var natPolicy: NatPolicy?
|
||||
private var natPolicyAuthInfo: AuthInfo?
|
||||
|
||||
init(accountModel: AccountModel) {
|
||||
self.accountModel = accountModel
|
||||
|
||||
self.pushNotification = accountModel.account.params?.pushNotificationAllowed ?? false
|
||||
self.imEncryptionMandatory = accountModel.account.params?.instantMessagingEncryptionMandatory ?? false
|
||||
self.voicemailUri = accountModel.account.params?.voicemailAddress?.asStringUriOnly() ?? ""
|
||||
self.mwiUri = accountModel.account.params?.mwiServerAddress?.asStringUriOnly() ?? ""
|
||||
|
||||
self.natPolicy = accountModel.account.params?.natPolicy
|
||||
self.stunServerUrl = accountModel.account.params?.natPolicy?.stunServer ?? ""
|
||||
self.enableIce = accountModel.account.params?.natPolicy?.iceEnabled ?? false
|
||||
self.enableTurn = accountModel.account.params?.natPolicy?.turnEnabled ?? false
|
||||
let turnUsernameTmp = accountModel.account.params?.natPolicy?.stunServerUsername ?? ""
|
||||
self.turnUsername = turnUsernameTmp
|
||||
self.turnPassword = ""
|
||||
|
||||
let transportTmp = accountModel.account.params?.transport
|
||||
if transportTmp == .Tls {
|
||||
self.transport = "TLS"
|
||||
} else if transportTmp == .Tcp {
|
||||
self.transport = "TCP"
|
||||
} else if transportTmp == .Udp {
|
||||
self.transport = "UDP"
|
||||
} else {
|
||||
self.transport = "DTLS"
|
||||
}
|
||||
|
||||
self.sipProxyUrl = accountModel.account.params?.serverAddress?.asStringUriOnly() ?? ""
|
||||
self.outboundProxy = accountModel.account.params?.outboundProxyEnabled ?? false
|
||||
self.avpf = accountModel.account.avpfEnabled
|
||||
self.bundleMode = accountModel.account.params?.rtpBundleEnabled ?? false
|
||||
self.cpimInBasicConversations = accountModel.account.params?.cpimInBasicChatRoomEnabled ?? false
|
||||
self.expire = accountModel.account.params?.expires.description ?? ""
|
||||
self.conferenceFactoryUri = accountModel.account.params?.conferenceFactoryAddress?.asStringUriOnly() ?? ""
|
||||
self.audioVideoConferenceFactoryUri = accountModel.account.params?.audioVideoConferenceFactoryAddress?.asStringUriOnly() ?? ""
|
||||
self.ccmpServerUrl = accountModel.account.params?.ccmpServerUrl ?? ""
|
||||
self.limeServerUrl = accountModel.account.params?.limeServerUrl ?? ""
|
||||
|
||||
if !turnUsernameTmp.isEmpty {
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
let authInfo = core.findAuthInfo(realm: nil, username: turnUsernameTmp, sipDomain: nil)
|
||||
if authInfo == nil {
|
||||
Log.warn("\(AccountSettingsViewModel.TAG) TURN username not empty but unable to find matching auth info!")
|
||||
} else {
|
||||
self.natPolicyAuthInfo = authInfo!
|
||||
DispatchQueue.main.async {
|
||||
self.turnPassword = authInfo!.password ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
if accountModel.account.params?.natPolicy == nil {
|
||||
self.natPolicy = try? core.createNatPolicy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func saveChanges() {
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
print("\(AccountSettingsViewModel.TAG) Saving changes...")
|
||||
|
||||
if let newParams = self.accountModel.account.params?.clone() {
|
||||
newParams.pushNotificationAllowed = self.pushNotification
|
||||
newParams.remotePushNotificationAllowed = self.pushNotification
|
||||
|
||||
newParams.instantMessagingEncryptionMandatory = self.imEncryptionMandatory
|
||||
|
||||
if !self.sipProxyUrl.isEmpty {
|
||||
if let serverAddress = core.interpretUrl(url: self.sipProxyUrl, applyInternationalPrefix: false) {
|
||||
|
||||
var transportTmp: TransportType = .Tls
|
||||
|
||||
if self.transport == "TLS" {
|
||||
transportTmp = .Tls
|
||||
} else if self.transport == "TCP" {
|
||||
transportTmp = .Tcp
|
||||
} else if self.transport == "UDP" {
|
||||
transportTmp = .Udp
|
||||
} else {
|
||||
transportTmp = .Dtls
|
||||
}
|
||||
|
||||
try? serverAddress.setTransport(newValue: transportTmp)
|
||||
try? newParams.setServeraddress(newValue: serverAddress)
|
||||
}
|
||||
}
|
||||
newParams.outboundProxyEnabled = self.outboundProxy
|
||||
|
||||
if let natPolicy = self.natPolicy {
|
||||
print("\(AccountSettingsViewModel.TAG) Also applying changes to NAT policy")
|
||||
natPolicy.stunServer = self.stunServerUrl
|
||||
natPolicy.stunEnabled = !self.stunServerUrl.isEmpty
|
||||
natPolicy.iceEnabled = self.enableIce
|
||||
natPolicy.turnEnabled = self.enableTurn
|
||||
let stunTurnUsername = self.turnUsername
|
||||
natPolicy.stunServerUsername = stunTurnUsername
|
||||
newParams.natPolicy = natPolicy
|
||||
|
||||
if let natPolicyAuthInfo = self.natPolicyAuthInfo {
|
||||
if stunTurnUsername.isEmpty {
|
||||
print("\(AccountSettingsViewModel.TAG) NAT policy TURN username is now empty, removing existing auth info")
|
||||
core.removeAuthInfo(info: natPolicyAuthInfo)
|
||||
} else {
|
||||
print("\(AccountSettingsViewModel.TAG) Found NAT policy auth info, updating it")
|
||||
natPolicyAuthInfo.username = stunTurnUsername
|
||||
natPolicyAuthInfo.password = self.turnPassword
|
||||
}
|
||||
} else if !stunTurnUsername.isEmpty {
|
||||
print("\(AccountSettingsViewModel.TAG) No NAT policy auth info found, creating it with")
|
||||
if let authInfo = try? Factory.Instance.createAuthInfo(
|
||||
username: stunTurnUsername,
|
||||
userid: nil,
|
||||
passwd: self.turnPassword,
|
||||
ha1: nil,
|
||||
realm: nil,
|
||||
domain: nil
|
||||
) {
|
||||
core.addAuthInfo(info: authInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newParams.avpfMode = self.avpf ? .Enabled : .Disabled
|
||||
|
||||
newParams.rtpBundleEnabled = self.bundleMode
|
||||
|
||||
newParams.cpimInBasicChatRoomEnabled = self.cpimInBasicConversations
|
||||
|
||||
if !self.mwiUri.isEmpty {
|
||||
newParams.mwiServerAddress = core.interpretUrl(url: self.mwiUri, applyInternationalPrefix: false)
|
||||
} else {
|
||||
newParams.mwiServerAddress = nil
|
||||
}
|
||||
|
||||
if !self.voicemailUri.isEmpty {
|
||||
newParams.voicemailAddress = core.interpretUrl(url: self.voicemailUri, applyInternationalPrefix: false)
|
||||
} else {
|
||||
newParams.voicemailAddress = nil
|
||||
}
|
||||
|
||||
let expireInt: Int = {
|
||||
if !self.expire.isEmpty {
|
||||
return Int(self.expire) ?? 31536000
|
||||
}
|
||||
return 31536000
|
||||
}()
|
||||
|
||||
newParams.expires = expireInt
|
||||
|
||||
if !self.conferenceFactoryUri.isEmpty {
|
||||
newParams.conferenceFactoryAddress = core.interpretUrl(url: self.conferenceFactoryUri, applyInternationalPrefix: false)
|
||||
} else {
|
||||
newParams.conferenceFactoryAddress = nil
|
||||
}
|
||||
|
||||
if !self.audioVideoConferenceFactoryUri.isEmpty {
|
||||
newParams.audioVideoConferenceFactoryAddress = core.interpretUrl(url: self.audioVideoConferenceFactoryUri, applyInternationalPrefix: false)
|
||||
} else {
|
||||
newParams.audioVideoConferenceFactoryAddress = nil
|
||||
}
|
||||
|
||||
newParams.ccmpServerUrl = self.ccmpServerUrl
|
||||
newParams.limeServerUrl = self.limeServerUrl
|
||||
|
||||
self.accountModel.account.params = newParams
|
||||
print("\(AccountSettingsViewModel.TAG) Changes have been saved")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue