Use SwiftLint

This commit is contained in:
Benoit Martins 2023-10-10 11:58:07 +02:00
parent 3669674eae
commit adc8b00d6d
31 changed files with 984 additions and 900 deletions

32
.swiftlint.yml Normal file
View file

@ -0,0 +1,32 @@
disabled_rules:
- trailing_whitespace
opt_in_rules:
- empty_count
- empty_string
excluded:
- Carthage
- Pods
- SwiftLint/Common/3rdPartyLib
line_length:
warning: 150
error: 200
ignores_function_declarations: true
ignores_comments: true
ignores_urls: true
function_body_length:
warning: 300
error: 500
function_parameter_count:
warning: 6
error: 8
type_body_length:
warning: 300
error: 500
file_length:
warning: 1000
error: 1500
ignore_comment_only_lines: true
cyclomatic_complexity:
warning: 15
error: 25
reporter: "xcode"

View file

@ -7,7 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
2B416B2E7C90375B792A28AE /* Pods_Linphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C08FB4788AD667D35BAE64D /* Pods_Linphone.framework */; }; 0DF2F35F000C9BBAE8FCB4A0 /* Pods_Linphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C92C314A5427A62F953EB70 /* Pods_Linphone.framework */; };
D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */; }; D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */; };
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; }; D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; };
D71707202AC5989C0037746F /* TextExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071F2AC5989C0037746F /* TextExtension.swift */; }; D71707202AC5989C0037746F /* TextExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071F2AC5989C0037746F /* TextExtension.swift */; };
@ -47,8 +47,9 @@
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
2C08FB4788AD667D35BAE64D /* Pods_Linphone.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Linphone.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3A132937ACADB95696E2F906 /* Pods-Linphone.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.debug.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.debug.xcconfig"; sourceTree = "<group>"; };
BC39A28B26EDB00C91AB7756 /* Pods-Linphone.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.release.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.release.xcconfig"; sourceTree = "<group>"; }; 3E2758142B8F42856C3A34DF /* Pods-Linphone.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.release.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.release.xcconfig"; sourceTree = "<group>"; };
7C92C314A5427A62F953EB70 /* Pods_Linphone.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Linphone.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; }; D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
D717071D2AC5922E0037746F /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; }; D717071D2AC5922E0037746F /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; };
D717071F2AC5989C0037746F /* TextExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextExtension.swift; sourceTree = "<group>"; }; D717071F2AC5989C0037746F /* TextExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextExtension.swift; sourceTree = "<group>"; };
@ -88,7 +89,6 @@
D7DA67612ACCB2FA00E95002 /* LoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFragment.swift; sourceTree = "<group>"; }; D7DA67612ACCB2FA00E95002 /* LoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginFragment.swift; sourceTree = "<group>"; };
D7DA67632ACCB31700E95002 /* ProfileModeFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModeFragment.swift; sourceTree = "<group>"; }; D7DA67632ACCB31700E95002 /* ProfileModeFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileModeFragment.swift; sourceTree = "<group>"; };
D7FB55102AD447FD00A5AB15 /* RegisterFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterFragment.swift; sourceTree = "<group>"; }; D7FB55102AD447FD00A5AB15 /* RegisterFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterFragment.swift; sourceTree = "<group>"; };
FBDE73581C1DC4F98CC3DF3A /* Pods-Linphone.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.debug.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -96,17 +96,17 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
2B416B2E7C90375B792A28AE /* Pods_Linphone.framework in Frameworks */, 0DF2F35F000C9BBAE8FCB4A0 /* Pods_Linphone.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
9FFD5E6302DF1093E1CB7311 /* Frameworks */ = { 1110B8CBF3C1BFD76F8BBFB2 /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
2C08FB4788AD667D35BAE64D /* Pods_Linphone.framework */, 7C92C314A5427A62F953EB70 /* Pods_Linphone.framework */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
@ -114,8 +114,8 @@
A31AF2AB8C6A3D7B7EA3B424 /* Pods */ = { A31AF2AB8C6A3D7B7EA3B424 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FBDE73581C1DC4F98CC3DF3A /* Pods-Linphone.debug.xcconfig */, 3A132937ACADB95696E2F906 /* Pods-Linphone.debug.xcconfig */,
BC39A28B26EDB00C91AB7756 /* Pods-Linphone.release.xcconfig */, 3E2758142B8F42856C3A34DF /* Pods-Linphone.release.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
@ -126,7 +126,6 @@
D717071D2AC5922E0037746F /* ColorExtension.swift */, D717071D2AC5922E0037746F /* ColorExtension.swift */,
D717071F2AC5989C0037746F /* TextExtension.swift */, D717071F2AC5989C0037746F /* TextExtension.swift */,
D74C9D002ACB098C0021626A /* PermissionManager.swift */, D74C9D002ACB098C0021626A /* PermissionManager.swift */,
D72343312ACEFF58009AA24E /* QRScannerController.swift */,
); );
path = Utils; path = Utils;
sourceTree = "<group>"; sourceTree = "<group>";
@ -137,7 +136,7 @@
D719ABB52ABC67BF00B41C10 /* Linphone */, D719ABB52ABC67BF00B41C10 /* Linphone */,
D719ABB42ABC67BF00B41C10 /* Products */, D719ABB42ABC67BF00B41C10 /* Products */,
A31AF2AB8C6A3D7B7EA3B424 /* Pods */, A31AF2AB8C6A3D7B7EA3B424 /* Pods */,
9FFD5E6302DF1093E1CB7311 /* Frameworks */, 1110B8CBF3C1BFD76F8BBFB2 /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -220,6 +219,7 @@
children = ( children = (
D719ABCE2ABC779A00B41C10 /* AccountLoginViewModel.swift */, D719ABCE2ABC779A00B41C10 /* AccountLoginViewModel.swift */,
D72343332ACEFFC3009AA24E /* QRScanner.swift */, D72343332ACEFFC3009AA24E /* QRScanner.swift */,
D72343312ACEFF58009AA24E /* QRScannerController.swift */,
); );
path = Viewmodel; path = Viewmodel;
sourceTree = "<group>"; sourceTree = "<group>";
@ -310,11 +310,12 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = D719ABC22ABC67BF00B41C10 /* Build configuration list for PBXNativeTarget "Linphone" */; buildConfigurationList = D719ABC22ABC67BF00B41C10 /* Build configuration list for PBXNativeTarget "Linphone" */;
buildPhases = ( buildPhases = (
5387C360B232ECCFFE549C7A /* [CP] Check Pods Manifest.lock */, EAE6BD221624F991B659AC2E /* [CP] Check Pods Manifest.lock */,
D719ABAF2ABC67BF00B41C10 /* Sources */, D719ABAF2ABC67BF00B41C10 /* Sources */,
D719ABB02ABC67BF00B41C10 /* Frameworks */, D719ABB02ABC67BF00B41C10 /* Frameworks */,
D719ABB12ABC67BF00B41C10 /* Resources */, D719ABB12ABC67BF00B41C10 /* Resources */,
C6890D9F62DE340F66542619 /* [CP] Embed Pods Frameworks */, D7FB55122AD53FE200A5AB15 /* Run Script */,
A35AE8ABA69001024776F16C /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
@ -378,7 +379,43 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
5387C360B232ECCFFE549C7A /* [CP] Check Pods Manifest.lock */ = { A35AE8ABA69001024776F16C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
D7FB55122AD53FE200A5AB15 /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 12;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Run Script";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [[ \"$(uname -m)\" == arm64 ]]; then\n export PATH=\"/opt/homebrew/bin:$PATH\"\nfi\n\nif which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
EAE6BD221624F991B659AC2E /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@ -400,23 +437,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
C6890D9F62DE340F66542619 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@ -572,7 +592,7 @@
}; };
D719ABC32ABC67BF00B41C10 /* Debug */ = { D719ABC32ABC67BF00B41C10 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = FBDE73581C1DC4F98CC3DF3A /* Pods-Linphone.debug.xcconfig */; baseConfigurationReference = 3A132937ACADB95696E2F906 /* Pods-Linphone.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@ -616,7 +636,7 @@
}; };
D719ABC42ABC67BF00B41C10 /* Release */ = { D719ABC42ABC67BF00B41C10 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = BC39A28B26EDB00C91AB7756 /* Pods-Linphone.release.xcconfig */; baseConfigurationReference = 3E2758142B8F42856C3A34DF /* Pods-Linphone.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;

View file

@ -19,18 +19,18 @@
import linphonesw import linphonesw
final class CoreContext : ObservableObject { final class CoreContext: ObservableObject {
static let shared = CoreContext() static let shared = CoreContext()
var mCore: Core! var mCore: Core!
var mRegistrationDelegate : CoreDelegate! var mRegistrationDelegate: CoreDelegate!
var mConfigurationDelegate : CoreDelegate! var mConfigurationDelegate: CoreDelegate!
var coreVersion: String = Core.getVersion var coreVersion: String = Core.getVersion
@Published var loggedIn : Bool = false @Published var loggedIn: Bool = false
@Published var loggingInProgress : Bool = false @Published var loggingInProgress: Bool = false
@Published var toastMessage : String = "" @Published var toastMessage: String = ""
private init() {} private init() {}
@ -47,23 +47,23 @@ final class CoreContext : ObservableObject {
mRegistrationDelegate = mRegistrationDelegate =
CoreDelegateStub( CoreDelegateStub(
onConfiguringStatus: { (core: Core, state: Config.ConfiguringState, message: String) in onConfiguringStatus: {(_: Core, state: Config.ConfiguringState, message: String) in
NSLog("New configuration state is \(state) = \(message)\n") NSLog("New configuration state is \(state) = \(message)\n")
if (state == .Successful) { if state == .Successful {
self.toastMessage = "Successful" self.toastMessage = "Successful"
} else { } else {
self.toastMessage = "Failed" self.toastMessage = "Failed"
} }
}, },
onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in onAccountRegistrationStateChanged: {(_: Core, account: Account, state: RegistrationState, message: String) in
// If account has been configured correctly, we will go through Progress and Ok states // If account has been configured correctly, we will go through Progress and Ok states
// Otherwise, we will be Failed. // Otherwise, we will be Failed.
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n") NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString())) = \(message)\n")
if (state == .Ok) { if state == .Ok {
self.loggingInProgress = false self.loggingInProgress = false
self.loggedIn = true self.loggedIn = true
} else if (state == .Progress) { } else if state == .Progress {
self.loggingInProgress = true self.loggingInProgress = true
} else { } else {
self.toastMessage = "Registration failed" self.toastMessage = "Registration failed"

View file

@ -1,21 +1,21 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of linphone-iphone * This file is part of linphone-iphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
@ -25,14 +25,14 @@ struct LinphoneApp: App {
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
@State private var isActive = false @State private var isActive = false
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
if isActive { if isActive {
ContentView(sharedMainViewModel: SharedMainViewModel()) ContentView(sharedMainViewModel: SharedMainViewModel())
.toast(isShowing: $coreContext.toastMessage) .toast(isShowing: $coreContext.toastMessage)
}else { } else {
SplashScreen(isActive: $isActive) SplashScreen(isActive: $isActive)
} }
} }
} }
} }

View file

@ -3,9 +3,15 @@
"strings" : { "strings" : {
"" : { "" : {
},
" et " : {
}, },
" or " : { " or " : {
},
"." : {
}, },
"[Forgotten password?](https://subscribe.linphone.org/)" : { "[Forgotten password?](https://subscribe.linphone.org/)" : {
@ -131,15 +137,8 @@
"Domain" : { "Domain" : {
}, },
"En continuant, vous acceptez ces conditions, %@ et %@." : { "En continuant, vous acceptez ces conditions, " : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "En continuant, vous acceptez ces conditions, %1$@ et %2$@."
}
}
}
}, },
"Error" : { "Error" : {
@ -220,21 +219,12 @@
}, },
"Skip" : { "Skip" : {
},
"Some features require a Linphone account, such as group messaging, video conferences...\n\nThese features are hidden when you register with a third party SIP account.\n\nTo enable it in a commercial projet, please contact us. " : {
}, },
"Start" : { "Start" : {
}, },
"TCP" : { "TCP" : {
},
"Texte explicatif du default mode : lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula." : {
},
"Texte explicatif du interoperable mode : lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula." : {
}, },
"The user name or password is incorrects" : { "The user name or password is incorrects" : {

View file

@ -1,21 +1,21 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
@ -25,7 +25,7 @@ struct SplashScreen: View {
@Binding var isActive: Bool @Binding var isActive: Bool
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { _ in
VStack { VStack {
Spacer() Spacer()
HStack { HStack {
@ -50,5 +50,5 @@ struct SplashScreen: View {
} }
#Preview { #Preview {
SplashScreen(isActive: .constant(true)) SplashScreen(isActive: .constant(true))
} }

View file

@ -20,19 +20,19 @@
import SwiftUI import SwiftUI
struct AssistantView: View { struct AssistantView: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
var body: some View { var body: some View {
if (sharedMainViewModel.displayProfileMode && coreContext.loggedIn){ if sharedMainViewModel.displayProfileMode && coreContext.loggedIn {
ProfileModeFragment(sharedMainViewModel: sharedMainViewModel) ProfileModeFragment(sharedMainViewModel: sharedMainViewModel)
} else { } else {
LoginFragment(accountLoginViewModel: AccountLoginViewModel(), sharedMainViewModel: sharedMainViewModel) LoginFragment(accountLoginViewModel: AccountLoginViewModel(), sharedMainViewModel: sharedMainViewModel)
} }
} }
} }
#Preview { #Preview {
AssistantView(sharedMainViewModel: SharedMainViewModel()) AssistantView(sharedMainViewModel: SharedMainViewModel())
} }

View file

@ -22,13 +22,13 @@ import SwiftUI
struct LoginFragment: View { struct LoginFragment: View {
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
@ObservedObject var accountLoginViewModel : AccountLoginViewModel @ObservedObject var accountLoginViewModel: AccountLoginViewModel
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@State private var isSecured: Bool = true @State private var isSecured: Bool = true
@FocusState var isNameFocused:Bool @FocusState var isNameFocused: Bool
@FocusState var isPasswordFocused:Bool @FocusState var isPasswordFocused: Bool
@State private var isShowPopup = false @State private var isShowPopup = false
@ -62,7 +62,7 @@ struct LoginFragment: View {
.default_text_style_700(styleSize: 15) .default_text_style_700(styleSize: 15)
.padding(.bottom, -5) .padding(.bottom, -5)
TextField("username", text : $accountLoginViewModel.username) TextField("username", text: $accountLoginViewModel.username)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.disabled(coreContext.loggedIn) .disabled(coreContext.loggedIn)
.frame(height: 25) .frame(height: 25)
@ -72,7 +72,7 @@ struct LoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) .stroke(isNameFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
.focused($isNameFocused) .focused($isNameFocused)
@ -95,15 +95,16 @@ struct LoginFragment: View {
.focused($isPasswordFocused) .focused($isPasswordFocused)
} }
} }
Button(action: { Button(action: {
isSecured.toggle() isSecured.toggle()
}) { }, label: {
Image(self.isSecured ? "eye-slash" : "eye") Image(self.isSecured ? "eye-slash" : "eye")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 20, height: 20) .frame(width: 20, height: 20)
} })
} }
.disabled(coreContext.loggedIn) .disabled(coreContext.loggedIn)
.padding(.horizontal, 20) .padding(.horizontal, 20)
@ -112,26 +113,21 @@ struct LoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isPasswordFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) .stroke(isPasswordFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
Button(action: { Button(action: {
if (self.coreContext.loggedIn){ self.accountLoginViewModel.login()
self.accountLoginViewModel.unregister() }, label: {
self.accountLoginViewModel.delete()
} else {
self.accountLoginViewModel.login()
}
}) {
Text(coreContext.loggedIn ? "Log out" : "assistant_account_login") Text(coreContext.loggedIn ? "Log out" : "assistant_account_login")
.default_text_style_white_600(styleSize: 20) .default_text_style_white_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.background((accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) ? Color.orange_main_100 : Color.orange_main_500) .background((accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) ? Color.orangeMain100 : Color.orangeMain500)
.cornerRadius(60) .cornerRadius(60)
.disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty) .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty)
.padding(.bottom) .padding(.bottom)
@ -139,21 +135,21 @@ struct LoginFragment: View {
HStack { HStack {
Text("[Forgotten password?](https://subscribe.linphone.org/)") Text("[Forgotten password?](https://subscribe.linphone.org/)")
.underline() .underline()
.tint(Color.gray_main2_600) .tint(Color.grayMain2c600)
.default_text_style_600(styleSize: 15) .default_text_style_600(styleSize: 15)
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
} }
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding(.bottom, 30) .padding(.bottom, 30)
HStack { HStack {
VStack{ VStack {
Divider() Divider()
} }
Text(" or ") Text(" or ")
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
VStack{ VStack {
Divider() Divider()
} }
} }
@ -166,7 +162,7 @@ struct LoginFragment: View {
Image("qr-code") Image("qr-code")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
.frame(width: 20, height: 20) .frame(width: 20, height: 20)
Text("Scan QR code") Text("Scan QR code")
@ -183,19 +179,21 @@ struct LoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(Color.orange_main_500, lineWidth: 1) .stroke(Color.orangeMain500, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
.simultaneousGesture(TapGesture().onEnded{ .simultaneousGesture(
self.linkActive = "QR" TapGesture().onEnded {
if !sharedMainViewModel.generalTermsAccepted { self.linkActive = "QR"
withAnimation { if !sharedMainViewModel.generalTermsAccepted {
self.isShowPopup.toggle() withAnimation {
self.isShowPopup.toggle()
}
} else {
self.isLinkQRActive = true
} }
} else {
self.isLinkQRActive = true
} }
}) )
NavigationLink(isActive: $isLinkSIPActive, destination: { NavigationLink(isActive: $isLinkSIPActive, destination: {
ThirdPartySipAccountWarningFragment(sharedMainViewModel: sharedMainViewModel, accountLoginViewModel: accountLoginViewModel) ThirdPartySipAccountWarningFragment(sharedMainViewModel: sharedMainViewModel, accountLoginViewModel: accountLoginViewModel)
@ -213,19 +211,21 @@ struct LoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(Color.orange_main_500, lineWidth: 1) .stroke(Color.orangeMain500, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
.simultaneousGesture(TapGesture().onEnded{ .simultaneousGesture(
self.linkActive = "SIP" TapGesture().onEnded {
if !sharedMainViewModel.generalTermsAccepted { self.linkActive = "SIP"
withAnimation { if !sharedMainViewModel.generalTermsAccepted {
self.isShowPopup.toggle() withAnimation {
self.isShowPopup.toggle()
}
} else {
self.isLinkSIPActive = true
} }
} else {
self.isLinkSIPActive = true
} }
}) )
Spacer() Spacer()
@ -235,7 +235,7 @@ struct LoginFragment: View {
Text("Not account yet?") Text("Not account yet?")
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.foregroundStyle(Color.gray_main2_700) .foregroundStyle(Color.grayMain2c700)
.padding(.horizontal, 10) .padding(.horizontal, 10)
NavigationLink(destination: RegisterFragment(), isActive: $isLinkREGActive, label: {Text("Register") NavigationLink(destination: RegisterFragment(), isActive: $isLinkREGActive, label: {Text("Register")
@ -249,19 +249,21 @@ struct LoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(Color.orange_main_500, lineWidth: 1) .stroke(Color.orangeMain500, lineWidth: 1)
) )
.padding(.horizontal, 10) .padding(.horizontal, 10)
.simultaneousGesture(TapGesture().onEnded{ .simultaneousGesture(
self.linkActive = "REG" TapGesture().onEnded {
if !sharedMainViewModel.generalTermsAccepted { self.linkActive = "REG"
withAnimation { if !sharedMainViewModel.generalTermsAccepted {
self.isShowPopup.toggle() withAnimation {
self.isShowPopup.toggle()
}
} else {
self.isLinkREGActive = true
} }
} else { }
self.isLinkREGActive = true )
}
})
Spacer() Spacer()
} }
@ -274,14 +276,25 @@ struct LoginFragment: View {
} }
if self.isShowPopup { if self.isShowPopup {
PopupView(sharedMainViewModel: sharedMainViewModel, isShowPopup: $isShowPopup, title: Text("Conditions de service"), content: Text("En continuant, vous acceptez ces conditions, \(Text("[notre politique de confidentialité](https://linphone.org/privacy-policy)").underline()) et \(Text("[nos conditions dutilisation](https://linphone.org/general-terms)").underline())."), titleFirstButton: Text("Deny all"), actionFirstButton: {self.isShowPopup.toggle()}, titleSecondButton: Text("Accept all"), actionSecondButton: {acceptGeneralTerms()}) let contentPopup1 = Text("En continuant, vous acceptez ces conditions, ")
.background(.black.opacity(0.65)) let contentPopup2 = Text("[notre politique de confidentialité](https://linphone.org/privacy-policy)").underline()
.onTapGesture { let contentPopup3 = Text(" et ")
self.isShowPopup.toggle() let contentPopup4 = Text("[nos conditions dutilisation](https://linphone.org/general-terms)").underline()
} let contentPopup5 = Text(".")
PopupView(sharedMainViewModel: sharedMainViewModel, isShowPopup: $isShowPopup,
title: Text("Conditions de service"),
content: contentPopup1 + contentPopup2 + contentPopup3 + contentPopup4 + contentPopup5,
titleFirstButton: Text("Deny all"),
actionFirstButton: {self.isShowPopup.toggle()},
titleSecondButton: Text("Accept all"),
actionSecondButton: {acceptGeneralTerms()})
.background(.black.opacity(0.65))
.onTapGesture {
self.isShowPopup.toggle()
}
} }
} }
.onAppear{ .onAppear {
sharedMainViewModel.changeDisplayProfileMode() sharedMainViewModel.changeDisplayProfileMode()
} }
@ -291,7 +304,7 @@ struct LoginFragment: View {
} }
if !coreContext.loggingInProgress && !coreContext.loggedIn { if !coreContext.loggingInProgress && !coreContext.loggedIn {
ZStack{ ZStack {
}.onAppear { }.onAppear {
self.accountLoginViewModel.unregister() self.accountLoginViewModel.unregister()
@ -303,7 +316,7 @@ struct LoginFragment: View {
.navigationViewStyle(StackNavigationViewStyle()) .navigationViewStyle(StackNavigationViewStyle())
} }
func acceptGeneralTerms(){ func acceptGeneralTerms() {
sharedMainViewModel.changeGeneralTerms() sharedMainViewModel.changeGeneralTerms()
self.isShowPopup.toggle() self.isShowPopup.toggle()
switch linkActive { switch linkActive {

View file

@ -20,138 +20,152 @@
import SwiftUI import SwiftUI
struct ProfileModeFragment: View { struct ProfileModeFragment: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@State var options: Int = 1 @State var options: Int = 1
@State private var isShowPopup = false @State private var isShowPopup = false
@State private var isShowPopupForDefault = true @State private var isShowPopupForDefault = true
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
ScrollView(.vertical) { ScrollView(.vertical) {
VStack { VStack {
ZStack { ZStack {
Image("mountain") Image("mountain")
.resizable() .resizable()
.scaledToFill() .scaledToFill()
.frame(width: geometry.size.width, height: 100) .frame(width: geometry.size.width, height: 100)
.clipped() .clipped()
Text("Personnalize your profil mode") Text("Personnalize your profil mode")
.default_text_style_white_800(styleSize: 20) .default_text_style_white_800(styleSize: 20)
.padding(.top, -10) .padding(.top, -10)
Text("You will change this mode later") Text("You will change this mode later")
.default_text_style_white(styleSize: 15) .default_text_style_white(styleSize: 15)
.padding(.top, 40) .padding(.top, 40)
} }
.padding(.top, 35) .padding(.top, 35)
.padding(.bottom, 10) .padding(.bottom, 10)
VStack (spacing: 10) { VStack(spacing: 10) {
Button(action: { Button(action: {
options = 1 options = 1
}) { }, label: {
HStack { HStack {
Image(options == 1 ? "radio-button-fill" : "radio-button") Image(options == 1 ? "radio-button-fill" : "radio-button")
Text("Default") Text("Default")
.profile_mode_text_style_gray_800(styleSize: 16) .profile_mode_text_style_gray_800(styleSize: 16)
Image("info") Image("info")
.resizable() .resizable()
.frame(width: 25, height: 25) .frame(width: 25, height: 25)
.onTapGesture { .onTapGesture {
withAnimation { withAnimation {
self.isShowPopupForDefault = true self.isShowPopupForDefault = true
self.isShowPopup.toggle() self.isShowPopup.toggle()
} }
} }
Spacer() Spacer()
} }
} })
HStack { HStack {
Text("Chiffrement de bout en bout de tous vos échanges, grâce au mode default vos communications sont à labri des regards.") Text("Chiffrement de bout en bout de tous vos échanges, grâce au mode default vos communications sont à labri des regards.")
.profile_mode_text_style_gray(styleSize: 15) .profile_mode_text_style_gray(styleSize: 15)
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 16) .padding(.horizontal, 16)
.padding(.vertical, 20) .padding(.vertical, 20)
.background(Color.gray_100) .background(Color.gray100)
.cornerRadius(15) .cornerRadius(15)
.padding(.bottom, 5) .padding(.bottom, 5)
Image("profile-mode") Image("profile-mode")
.resizable() .resizable()
.frame(width: 150, height: 60) .frame(width: 150, height: 60)
.padding() .padding()
Button(action: { Button(action: {
options = 2 options = 2
}) { }, label: {
HStack { HStack {
Image(options == 2 ? "radio-button-fill" : "radio-button") Image(options == 2 ? "radio-button-fill" : "radio-button")
Text("Interoperable") Text("Interoperable")
.profile_mode_text_style_gray_800(styleSize: 16) .profile_mode_text_style_gray_800(styleSize: 16)
Image("info") Image("info")
.resizable() .resizable()
.frame(width: 25, height: 25) .frame(width: 25, height: 25)
.onTapGesture { .onTapGesture {
withAnimation { withAnimation {
self.isShowPopupForDefault = false self.isShowPopupForDefault = false
self.isShowPopup.toggle() self.isShowPopup.toggle()
} }
} }
Spacer() Spacer()
} }
} })
HStack { HStack {
Text("Ce mode vous permet dêtre interopérable avec dautres services SIP.\nVos communications seront chiffrées de point à point. ") Text("Ce mode vous permet dêtre interopérable avec dautres services SIP.\nVos communications seront chiffrées de point à point. ")
.profile_mode_text_style_gray(styleSize: 15) .profile_mode_text_style_gray(styleSize: 15)
} }
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding(.horizontal, 16) .padding(.horizontal, 16)
.padding(.vertical, 20) .padding(.vertical, 20)
.background(Color.gray_100) .background(Color.gray100)
.cornerRadius(15) .cornerRadius(15)
} }
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.padding() .padding()
Spacer() Spacer()
Button(action: { Button(action: {
sharedMainViewModel.changeHideProfileMode() sharedMainViewModel.changeHideProfileMode()
}) { }, label: {
Text("Continue") Text("Continue")
.default_text_style_white_600(styleSize: 20) .default_text_style_white_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.background(Color.orange_main_500) .background(Color.orangeMain500)
.cornerRadius(60) .cornerRadius(60)
.padding(.horizontal) .padding(.horizontal)
.padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0)
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
} }
.frame(minHeight: geometry.size.height) .frame(minHeight: geometry.size.height)
} }
.onAppear { .onAppear {
UserDefaults.standard.set(false, forKey: "display_profile_mode") UserDefaults.standard.set(false, forKey: "display_profile_mode")
} }
if self.isShowPopup { if self.isShowPopup {
PopupView(sharedMainViewModel: sharedMainViewModel, isShowPopup: $isShowPopup, title: Text(isShowPopupForDefault ? "Default mode" : "Interoperable mode"), content: Text(isShowPopupForDefault ? "Texte explicatif du default mode : lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula." : "Texte explicatif du interoperable mode : lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula."), titleFirstButton: nil, actionFirstButton: {}, titleSecondButton: Text("Close"), actionSecondButton: {self.isShowPopup.toggle()}) PopupView(sharedMainViewModel: sharedMainViewModel, isShowPopup: $isShowPopup,
.background(.black.opacity(0.65)) title: Text(isShowPopupForDefault ? "Default mode" : "Interoperable mode"),
.onTapGesture { content: Text(
self.isShowPopup.toggle() isShowPopupForDefault
} ? "Texte explicatif du default mode : lorem ipsum dolor sit amet, consectetur adipiscing elit."
} + "Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula."
} : "Texte explicatif du interoperable mode : lorem ipsum dolor sit amet, consectetur adipiscing elit."
} + " Etiam velit sapien, egestas sit amet dictum eget, condimentum a ligula."),
titleFirstButton: nil,
actionFirstButton: {},
titleSecondButton: Text("Close"),
actionSecondButton: {
self.isShowPopup.toggle()
}
)
.background(.black.opacity(0.65))
.onTapGesture {
self.isShowPopup.toggle()
}
}
}
}
} }
#Preview { #Preview {
ProfileModeFragment(sharedMainViewModel: SharedMainViewModel()) ProfileModeFragment(sharedMainViewModel: SharedMainViewModel())
} }

View file

@ -1,21 +1,21 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
@ -26,8 +26,8 @@ struct QrCodeScannerFragment: View {
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
@State var scanResult = "Scan a QR code" @State var scanResult = "Scan a QR code"
var body: some View { var body: some View {
ZStack(alignment: .top) { ZStack(alignment: .top) {
QRScanner(result: $scanResult) QRScanner(result: $scanResult)
@ -35,7 +35,7 @@ struct QrCodeScannerFragment: View {
.default_text_style_white_800(styleSize: 20) .default_text_style_white_800(styleSize: 20)
.padding(.top, 175) .padding(.top, 175)
HStack{ HStack {
Button { Button {
dismiss() dismiss()
} label: { } label: {
@ -55,15 +55,15 @@ struct QrCodeScannerFragment: View {
.navigationBarHidden(true) .navigationBarHidden(true)
if coreContext.toastMessage == "Successful" { if coreContext.toastMessage == "Successful" {
ZStack{ ZStack {
}.onAppear { }.onAppear {
dismiss() dismiss()
} }
} }
} }
} }
#Preview { #Preview {
QrCodeScannerFragment() QrCodeScannerFragment()
} }

View file

@ -23,12 +23,12 @@ struct RegisterFragment: View {
.frame(width: geometry.size.width, height: 100) .frame(width: geometry.size.width, height: 100)
.clipped() .clipped()
VStack (alignment: .leading) { VStack(alignment: .leading) {
HStack { HStack {
Image("caret-left") Image("caret-left")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 25, height: 25, alignment: .leading) .frame(width: 25, height: 25, alignment: .leading)
.padding(.top, -65) .padding(.top, -65)
.onTapGesture { .onTapGesture {
@ -60,5 +60,5 @@ struct RegisterFragment: View {
} }
#Preview { #Preview {
RegisterFragment() RegisterFragment()
} }

View file

@ -21,23 +21,23 @@ import SwiftUI
struct ThirdPartySipAccountLoginFragment: View { struct ThirdPartySipAccountLoginFragment: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
@ObservedObject var accountLoginViewModel : AccountLoginViewModel @ObservedObject var accountLoginViewModel: AccountLoginViewModel
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
@State private var isSecured: Bool = true @State private var isSecured: Bool = true
@FocusState var isNameFocused:Bool @FocusState var isNameFocused: Bool
@FocusState var isPasswordFocused:Bool @FocusState var isPasswordFocused: Bool
@FocusState var isDomainFocused:Bool @FocusState var isDomainFocused: Bool
@FocusState var isDisplayNameFocused:Bool @FocusState var isDisplayNameFocused: Bool
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
ScrollView(.vertical) { ScrollView(.vertical) {
VStack { VStack {
ZStack { ZStack {
Image("mountain") Image("mountain")
.resizable() .resizable()
@ -45,12 +45,12 @@ struct ThirdPartySipAccountLoginFragment: View {
.frame(width: geometry.size.width, height: 100) .frame(width: geometry.size.width, height: 100)
.clipped() .clipped()
VStack (alignment: .leading) { VStack(alignment: .leading) {
HStack { HStack {
Image("caret-left") Image("caret-left")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 25, height: 25, alignment: .leading) .frame(width: 25, height: 25, alignment: .leading)
.padding(.top, -65) .padding(.top, -65)
.onTapGesture { .onTapGesture {
@ -73,13 +73,13 @@ struct ThirdPartySipAccountLoginFragment: View {
} }
.padding(.top, 35) .padding(.top, 35)
.padding(.bottom, 10) .padding(.bottom, 10)
VStack(alignment: .leading) { VStack(alignment: .leading) {
Text(String(localized: "username")+"*") Text(String(localized: "username")+"*")
.default_text_style_700(styleSize: 15) .default_text_style_700(styleSize: 15)
.padding(.bottom, -5) .padding(.bottom, -5)
TextField("username", text : $accountLoginViewModel.username) TextField("username", text: $accountLoginViewModel.username)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.disabled(coreContext.loggedIn) .disabled(coreContext.loggedIn)
.frame(height: 25) .frame(height: 25)
@ -89,7 +89,7 @@ struct ThirdPartySipAccountLoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) .stroke(isNameFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
.focused($isNameFocused) .focused($isNameFocused)
@ -114,13 +114,13 @@ struct ThirdPartySipAccountLoginFragment: View {
} }
Button(action: { Button(action: {
isSecured.toggle() isSecured.toggle()
}) { }, label: {
Image(self.isSecured ? "eye-slash" : "eye") Image(self.isSecured ? "eye-slash" : "eye")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 20, height: 20) .frame(width: 20, height: 20)
} })
} }
.disabled(coreContext.loggedIn) .disabled(coreContext.loggedIn)
.padding(.horizontal, 20) .padding(.horizontal, 20)
@ -129,7 +129,7 @@ struct ThirdPartySipAccountLoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isPasswordFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) .stroke(isPasswordFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
@ -137,7 +137,7 @@ struct ThirdPartySipAccountLoginFragment: View {
.default_text_style_700(styleSize: 15) .default_text_style_700(styleSize: 15)
.padding(.bottom, -5) .padding(.bottom, -5)
TextField("sip.linphone.org", text : $accountLoginViewModel.domain) TextField("sip.linphone.org", text: $accountLoginViewModel.domain)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.disabled(coreContext.loggedIn) .disabled(coreContext.loggedIn)
.frame(height: 25) .frame(height: 25)
@ -147,7 +147,7 @@ struct ThirdPartySipAccountLoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isDomainFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) .stroke(isDomainFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
.focused($isDomainFocused) .focused($isDomainFocused)
@ -156,7 +156,7 @@ struct ThirdPartySipAccountLoginFragment: View {
.default_text_style_700(styleSize: 15) .default_text_style_700(styleSize: 15)
.padding(.bottom, -5) .padding(.bottom, -5)
TextField("Display Name", text : $accountLoginViewModel.displayName) TextField("Display Name", text: $accountLoginViewModel.displayName)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.disabled(coreContext.loggedIn) .disabled(coreContext.loggedIn)
.frame(height: 25) .frame(height: 25)
@ -166,7 +166,7 @@ struct ThirdPartySipAccountLoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isDisplayNameFocused ? Color.orange_main_500 : Color.gray_200, lineWidth: 1) .stroke(isDisplayNameFocused ? Color.orangeMain500 : Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
.focused($isDisplayNameFocused) .focused($isDisplayNameFocused)
@ -186,7 +186,7 @@ struct ThirdPartySipAccountLoginFragment: View {
Image("caret-down") Image("caret-down")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 20, height: 20) .frame(width: 20, height: 20)
} }
.frame(height: 25) .frame(height: 25)
@ -196,43 +196,40 @@ struct ThirdPartySipAccountLoginFragment: View {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(Color.gray_200, lineWidth: 1) .stroke(Color.gray200, lineWidth: 1)
) )
.padding(.bottom) .padding(.bottom)
Spacer() Spacer()
Button(action: { Button(action: {
if (self.coreContext.loggedIn){ self.accountLoginViewModel.login()
self.accountLoginViewModel.unregister()
self.accountLoginViewModel.delete()
} else {
self.accountLoginViewModel.login()
}
accountLoginViewModel.domain = "sip.linphone.org" accountLoginViewModel.domain = "sip.linphone.org"
accountLoginViewModel.transportType = "TLS" accountLoginViewModel.transportType = "TLS"
}) { }, label: {
Text(coreContext.loggedIn ? "Log out" : "assistant_account_login") Text(coreContext.loggedIn ? "Log out" : "assistant_account_login")
.default_text_style_white_600(styleSize: 20) .default_text_style_white_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.background((accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty) ? Color.orange_main_100 : Color.orange_main_500) .background(
(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty)
? Color.orangeMain100
: Color.orangeMain500)
.cornerRadius(60) .cornerRadius(60)
.disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty) .disabled(accountLoginViewModel.username.isEmpty || accountLoginViewModel.passwd.isEmpty || accountLoginViewModel.domain.isEmpty)
.padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0)
} }
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.padding(.horizontal, 20) .padding(.horizontal, 20)
} }
.frame(minHeight: geometry.size.height) .frame(minHeight: geometry.size.height)
} }
} }
.navigationBarHidden(true) .navigationBarHidden(true)
} }
} }
#Preview { #Preview {

View file

@ -21,17 +21,17 @@ import SwiftUI
struct ThirdPartySipAccountWarningFragment: View { struct ThirdPartySipAccountWarningFragment: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
@ObservedObject var accountLoginViewModel : AccountLoginViewModel @ObservedObject var accountLoginViewModel: AccountLoginViewModel
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
var body: some View { var body: some View {
NavigationView { NavigationView {
GeometryReader { geometry in GeometryReader { geometry in
ScrollView(.vertical) { ScrollView(.vertical) {
VStack { VStack {
ZStack { ZStack {
Image("mountain") Image("mountain")
.resizable() .resizable()
@ -39,12 +39,12 @@ struct ThirdPartySipAccountWarningFragment: View {
.frame(width: geometry.size.width, height: 100) .frame(width: geometry.size.width, height: 100)
.clipped() .clipped()
VStack (alignment: .leading) { VStack(alignment: .leading) {
HStack { HStack {
Image("caret-left") Image("caret-left")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 25, height: 25, alignment: .leading) .frame(width: 25, height: 25, alignment: .leading)
.padding(.top, -65) .padding(.top, -65)
.onTapGesture { .onTapGesture {
@ -67,94 +67,96 @@ struct ThirdPartySipAccountWarningFragment: View {
.padding(.bottom, 10) .padding(.bottom, 10)
Spacer() Spacer()
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack { HStack {
Spacer() Spacer()
HStack(alignment: .center) { HStack(alignment: .center) {
Image("conversation") Image("conversation")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 20, height: 20, alignment: .leading) .frame(width: 20, height: 20, alignment: .leading)
.onTapGesture { .onTapGesture {
withAnimation { withAnimation {
dismiss() dismiss()
} }
} }
} }
.padding(16) .padding(16)
.background(Color.gray_main2_200) .background(Color.grayMain2c200)
.cornerRadius(40) .cornerRadius(40)
.padding(.horizontal) .padding(.horizontal)
HStack(alignment: .center) { HStack(alignment: .center) {
Image("video-call") Image("video-call")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.gray_main2_500) .foregroundStyle(Color.grayMain2c500)
.frame(width: 20, height: 20, alignment: .leading) .frame(width: 20, height: 20, alignment: .leading)
.onTapGesture { .onTapGesture {
withAnimation { withAnimation {
dismiss() dismiss()
} }
} }
} }
.padding(16) .padding(16)
.background(Color.gray_main2_200) .background(Color.grayMain2c200)
.cornerRadius(40) .cornerRadius(40)
.padding(.horizontal) .padding(.horizontal)
Spacer() Spacer()
} }
.padding(.bottom, 40) .padding(.bottom, 40)
Text("Some features require a Linphone account, such as group messaging, video conferences...\n\nThese features are hidden when you register with a third party SIP account.\n\nTo enable it in a commercial projet, please contact us. ") Text("Some features require a Linphone account, such as group messaging, video conferences...\n\n"
.default_text_style(styleSize: 15) + "These features are hidden when you register with a third party SIP account.\n\n"
.multilineTextAlignment(.center) + "To enable it in a commercial projet, please contact us. ")
.padding(.bottom) .default_text_style(styleSize: 15)
.multilineTextAlignment(.center)
HStack { .padding(.bottom)
Spacer()
HStack {
HStack { Spacer()
Text("[linphone.org/contact](https://linphone.org/contact)")
.tint(Color.orange_main_500) HStack {
.default_text_style_orange_600(styleSize: 15) Text("[linphone.org/contact](https://linphone.org/contact)")
.frame(height: 35) .tint(Color.orangeMain500)
} .default_text_style_orange_600(styleSize: 15)
.padding(.horizontal, 15) .frame(height: 35)
.cornerRadius(60) }
.overlay( .padding(.horizontal, 15)
RoundedRectangle(cornerRadius: 60) .cornerRadius(60)
.inset(by: 0.5) .overlay(
.stroke(Color.orange_main_500, lineWidth: 1) RoundedRectangle(cornerRadius: 60)
) .inset(by: 0.5)
.stroke(Color.orangeMain500, lineWidth: 1)
Spacer() )
}
.padding(.vertical) Spacer()
} }
.padding(.vertical)
}
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.padding(.horizontal, 20) .padding(.horizontal, 20)
Spacer() Spacer()
Button(action: { Button(action: {
dismiss() dismiss()
}) { }, label: {
Text("I prefere create an account") Text("I prefere create an account")
.default_text_style_orange_600(styleSize: 20) .default_text_style_orange_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.cornerRadius(60) .cornerRadius(60)
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(Color.orange_main_500, lineWidth: 1) .stroke(Color.orangeMain500, lineWidth: 1)
) )
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.padding(.horizontal) .padding(.horizontal)
@ -170,19 +172,19 @@ struct ThirdPartySipAccountWarningFragment: View {
}) })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.background(Color.orange_main_500) .background(Color.orangeMain500)
.cornerRadius(60) .cornerRadius(60)
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.padding(.horizontal) .padding(.horizontal)
.padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0)
} }
.frame(minHeight: geometry.size.height) .frame(minHeight: geometry.size.height)
} }
} }
} }
.navigationViewStyle(StackNavigationViewStyle()) .navigationViewStyle(StackNavigationViewStyle())
.navigationBarHidden(true) .navigationBarHidden(true)
} }
} }
#Preview { #Preview {

View file

@ -1,34 +1,34 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import linphonesw import linphonesw
import SwiftUI import SwiftUI
class AccountLoginViewModel : ObservableObject { class AccountLoginViewModel: ObservableObject {
private var coreContext = CoreContext.shared private var coreContext = CoreContext.shared
@Published var username : String = "" @Published var username: String = ""
@Published var passwd : String = "" @Published var passwd: String = ""
@Published var domain : String = "sip.linphone.org" @Published var domain: String = "sip.linphone.org"
@Published var displayName : String = "" @Published var displayName: String = ""
@Published var transportType : String = "TLS" @Published var transportType: String = "TLS"
init() {} init() {}
@ -37,10 +37,12 @@ class AccountLoginViewModel : ObservableObject {
// Get the transport protocol to use. // Get the transport protocol to use.
// TLS is strongly recommended // TLS is strongly recommended
// Only use UDP if you don't have the choice // Only use UDP if you don't have the choice
var transport : TransportType var transport: TransportType
if (transportType == "TLS") { transport = TransportType.Tls } if transportType == "TLS" {
else if (transportType == "TCP") { transport = TransportType.Tcp } transport = TransportType.Tls
else { transport = TransportType.Udp } } else if transportType == "TCP" {
transport = TransportType.Tcp
} else { transport = TransportType.Udp }
// To configure a SIP account, we need an Account object and an AuthInfo object // To configure a SIP account, we need an Account object and an AuthInfo object
// The first one is how to connect to the proxy server, the second one stores the credentials // The first one is how to connect to the proxy server, the second one stores the credentials
@ -58,7 +60,7 @@ class AccountLoginViewModel : ObservableObject {
// A SIP account is identified by an identity address that we can construct from the username and domain // A SIP account is identified by an identity address that we can construct from the username and domain
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain)) let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
try! accountParams.setIdentityaddress(newValue: identity) try accountParams.setIdentityaddress(newValue: identity)
// We also need to configure where the proxy server is located // We also need to configure where the proxy server is located
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain)) let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))

View file

@ -1,21 +1,21 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import Foundation import Foundation
import SwiftUI import SwiftUI
@ -54,13 +54,15 @@ class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// Check if the metadataObjects array is not nil and it contains at least one object. // Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects.count == 0 { if metadataObjects.isEmpty {
scanResult = "Scan a QR code" scanResult = "Scan a QR code"
return return
} }
// Get the metadata object. // Get the metadata object.
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject guard let metadataObj = metadataObjects[0] as? AVMetadataMachineReadableCodeObject else {
return
}
if metadataObj.type == AVMetadataObject.ObjectType.qr, if metadataObj.type == AVMetadataObject.ObjectType.qr,
let result = metadataObj.stringValue { let result = metadataObj.stringValue {
@ -68,12 +70,11 @@ class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
if let url = NSURL(string: result) { if let url = NSURL(string: result) {
if UIApplication.shared.canOpenURL(url as URL) { if UIApplication.shared.canOpenURL(url as URL) {
lastResult = result lastResult = result
//scanResult = result
do { do {
try coreContext.mCore.setProvisioninguri(newValue: result) try coreContext.mCore.setProvisioninguri(newValue: result)
coreContext.mCore.stop() coreContext.mCore.stop()
try coreContext.mCore.start() try coreContext.mCore.start()
}catch { } catch {
} }

View file

@ -1,21 +1,21 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import Foundation import Foundation
import SwiftUI import SwiftUI
@ -25,52 +25,52 @@ class QRScannerController: UIViewController {
var captureSession = AVCaptureSession() var captureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer? var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var qrCodeFrameView: UIView? var qrCodeFrameView: UIView?
var delegate: AVCaptureMetadataOutputObjectsDelegate? var delegate: AVCaptureMetadataOutputObjectsDelegate?
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
// Get the back-facing camera for capturing videos // Get the back-facing camera for capturing videos
guard let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { guard let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
print("Failed to get the camera device") print("Failed to get the camera device")
return return
} }
let videoInput: AVCaptureDeviceInput let videoInput: AVCaptureDeviceInput
do { do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object. // Get an instance of the AVCaptureDeviceInput class using the previous device object.
videoInput = try AVCaptureDeviceInput(device: captureDevice) videoInput = try AVCaptureDeviceInput(device: captureDevice)
} catch { } catch {
// If any error occurs, simply print it out and don't continue any more. // If any error occurs, simply print it out and don't continue any more.
print(error) print(error)
return return
} }
// Set the input device on the capture session. // Set the input device on the capture session.
captureSession.addInput(videoInput) captureSession.addInput(videoInput)
// Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session. // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
let captureMetadataOutput = AVCaptureMetadataOutput() let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(captureMetadataOutput) captureSession.addOutput(captureMetadataOutput)
// Set delegate and use the default dispatch queue to execute the call back // Set delegate and use the default dispatch queue to execute the call back
captureMetadataOutput.setMetadataObjectsDelegate(delegate, queue: DispatchQueue.main) captureMetadataOutput.setMetadataObjectsDelegate(delegate, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = [ .qr ] captureMetadataOutput.metadataObjectTypes = [ .qr ]
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer. // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!) view.layer.addSublayer(videoPreviewLayer!)
// Start video capture. // Start video capture.
DispatchQueue.global(qos: .background).async { DispatchQueue.global(qos: .background).async {
self.captureSession.startRunning() self.captureSession.startRunning()
} }
} }
} }

View file

@ -1,26 +1,26 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of linphone-iphone * This file is part of linphone-iphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
struct ContactsView: View { struct ContactsView: View {
var body: some View { var body: some View {
VStack { VStack {
Spacer() Spacer()
Image("linphone") Image("linphone")
@ -28,9 +28,9 @@ struct ContactsView: View {
Text("Contacts View") Text("Contacts View")
Spacer() Spacer()
} }
} }
} }
#Preview { #Preview {
ContactsView() ContactsView()
} }

View file

@ -21,15 +21,15 @@ import SwiftUI
struct ContentView: View { struct ContentView: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
var body: some View { var body: some View {
if !sharedMainViewModel.welcomeViewDisplayed { if !sharedMainViewModel.welcomeViewDisplayed {
WelcomeView(sharedMainViewModel: sharedMainViewModel) WelcomeView(sharedMainViewModel: sharedMainViewModel)
} else if coreContext.mCore.defaultAccount == nil || sharedMainViewModel.displayProfileMode { } else if coreContext.mCore.defaultAccount == nil || sharedMainViewModel.displayProfileMode {
AssistantView(sharedMainViewModel: sharedMainViewModel) AssistantView(sharedMainViewModel: sharedMainViewModel)
} else { } else {
TabView { TabView {
ContactsView() ContactsView()
.tabItem { .tabItem {
@ -46,5 +46,5 @@ struct ContentView: View {
} }
#Preview { #Preview {
ContentView(sharedMainViewModel: SharedMainViewModel()) ContentView(sharedMainViewModel: SharedMainViewModel())
} }

View file

@ -1,41 +1,41 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
struct PopupLoadingView: View { struct PopupLoadingView: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
VStack (alignment: .leading){ VStack(alignment: .leading) {
ProgressView() ProgressView()
.controlSize(.large) .controlSize(.large)
.progressViewStyle(CircularProgressViewStyle(tint: Color.orange_main_500)) .progressViewStyle(CircularProgressViewStyle(tint: Color.orangeMain500))
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding(.top) .padding(.top)
.padding(.bottom) .padding(.bottom)
Text("Opération en cours...") Text("Opération en cours...")
.tint(Color.gray_main2_600) .tint(Color.grayMain2c600)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} }
@ -46,11 +46,11 @@ struct PopupLoadingView: View {
.padding(.horizontal) .padding(.horizontal)
.frame(maxHeight: .infinity) .frame(maxHeight: .infinity)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.shadow(color: Color.orange_main_500, radius: 0, x: 0, y: 2) .shadow(color: Color.orangeMain500, radius: 0, x: 0, y: 2)
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.position(x: geometry.size.width / 2, y: geometry.size.height / 2) .position(x: geometry.size.width / 2, y: geometry.size.height / 2)
} }
} }
} }
#Preview { #Preview {

View file

@ -22,70 +22,69 @@ import Photos
struct PopupView: View { struct PopupView: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
var permissionManager = PermissionManager.shared var permissionManager = PermissionManager.shared
@Binding var isShowPopup: Bool @Binding var isShowPopup: Bool
var title: Text var title: Text
var content: Text? var content: Text?
var titleFirstButton: Text? var titleFirstButton: Text?
var actionFirstButton: () -> () var actionFirstButton: () -> Void
var titleSecondButton: Text? var titleSecondButton: Text?
var actionSecondButton: () -> () var actionSecondButton: () -> Void
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
VStack (alignment: .leading) { VStack(alignment: .leading) {
title title
.default_text_style_800(styleSize: 16) .default_text_style_800(styleSize: 16)
.frame(alignment: .leading) .frame(alignment: .leading)
.padding(.bottom, 2) .padding(.bottom, 2)
if content != nil { if content != nil {
content content
.tint(Color.gray_main2_600) .tint(Color.grayMain2c600)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.padding(.bottom, 20) .padding(.bottom, 20)
} }
if titleFirstButton != nil { if titleFirstButton != nil {
Button(action: { Button(action: {
actionFirstButton() actionFirstButton()
}) { }, label: {
titleFirstButton titleFirstButton
.default_text_style_orange_600(styleSize: 20) .default_text_style_orange_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.cornerRadius(60) .cornerRadius(60)
.overlay( .overlay(
RoundedRectangle(cornerRadius: 60) RoundedRectangle(cornerRadius: 60)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(Color.orange_main_500, lineWidth: 1) .stroke(Color.orangeMain500, lineWidth: 1)
) )
.padding(.bottom, 10) .padding(.bottom, 10)
} }
if titleSecondButton != nil { if titleSecondButton != nil {
Button(action: { Button(action: {
actionSecondButton() actionSecondButton()
}) { }, label: {
titleSecondButton titleSecondButton
.default_text_style_white_600(styleSize: 20) .default_text_style_white_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.background(Color.orange_main_500) .background(Color.orangeMain500)
.cornerRadius(60) .cornerRadius(60)
} }
} }
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 20) .padding(.vertical, 20)
@ -93,7 +92,7 @@ struct PopupView: View {
.cornerRadius(20) .cornerRadius(20)
.padding(.horizontal) .padding(.horizontal)
.frame(maxHeight: .infinity) .frame(maxHeight: .infinity)
.shadow(color: Color.orange_main_500, radius: 0, x: 0, y: 2) .shadow(color: Color.orangeMain500, radius: 0, x: 0, y: 2)
.frame(maxWidth: sharedMainViewModel.maxWidth) .frame(maxWidth: sharedMainViewModel.maxWidth)
.position(x: geometry.size.width / 2, y: geometry.size.height / 2) .position(x: geometry.size.width / 2, y: geometry.size.height / 2)
} }
@ -101,6 +100,12 @@ struct PopupView: View {
} }
#Preview { #Preview {
PopupView(sharedMainViewModel: SharedMainViewModel(), isShowPopup: .constant(true), title: Text("Title"), content: Text("Content"), titleFirstButton: Text("Deny all"), actionFirstButton: {}, titleSecondButton: Text("Accept all"), actionSecondButton: {}) PopupView(sharedMainViewModel: SharedMainViewModel(), isShowPopup: .constant(true),
.background(.black.opacity(0.65)) title: Text("Title"),
content: Text("Content"),
titleFirstButton: Text("Deny all"),
actionFirstButton: {},
titleSecondButton: Text("Accept all"),
actionSecondButton: {})
.background(.black.opacity(0.65))
} }

View file

@ -1,27 +1,27 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
struct ToastView: ViewModifier { struct ToastView: ViewModifier {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
@Binding var isShowing: String @Binding var isShowing: String
@ -44,35 +44,35 @@ struct ToastView: ViewModifier {
case "Successful": case "Successful":
Text("QR code validated!") Text("QR code validated!")
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.foregroundStyle(Color.green_success_500) .foregroundStyle(Color.greenSuccess500)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.padding(8) .padding(8)
case "Failed": case "Failed":
Text("Invalid QR code!") Text("Invalid QR code!")
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.foregroundStyle(Color.red_danger_500) .foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.padding(8) .padding(8)
case "Invalide URI": case "Invalide URI":
Text("Invalide URI") Text("Invalide URI")
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.foregroundStyle(Color.red_danger_500) .foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.padding(8) .padding(8)
case "Registration failed": case "Registration failed":
Text("The user name or password is incorrects") Text("The user name or password is incorrects")
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.foregroundStyle(Color.red_danger_500) .foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.padding(8) .padding(8)
default: default:
Text("Error") Text("Error")
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.foregroundStyle(Color.red_danger_500) .foregroundStyle(Color.redDanger500)
.default_text_style(styleSize: 15) .default_text_style(styleSize: 15)
.padding(8) .padding(8)
} }
@ -83,10 +83,10 @@ struct ToastView: ViewModifier {
.overlay( .overlay(
RoundedRectangle(cornerRadius: 50) RoundedRectangle(cornerRadius: 50)
.inset(by: 0.5) .inset(by: 0.5)
.stroke(isShowing == "Successful" ? Color.green_success_500 : Color.red_danger_500, lineWidth: 1) .stroke(isShowing == "Successful" ? Color.greenSuccess500 : Color.redDanger500, lineWidth: 1)
) )
.onTapGesture { .onTapGesture {
isShowing = "" isShowing = ""
} }
.onAppear { .onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { DispatchQueue.main.asyncAfter(deadline: .now() + 2) {

View file

@ -1,21 +1,21 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import SwiftUI import SwiftUI
@ -23,7 +23,7 @@ struct HistoryView: View {
@ObservedObject private var coreContext = CoreContext.shared @ObservedObject private var coreContext = CoreContext.shared
var body: some View { var body: some View {
VStack { VStack {
Spacer() Spacer()
Image("linphone") Image("linphone")
@ -31,9 +31,9 @@ struct HistoryView: View {
Text("History View") Text("History View")
Spacer() Spacer()
} }
} }
} }
#Preview { #Preview {
HistoryView() HistoryView()
} }

View file

@ -1,25 +1,25 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import linphonesw import linphonesw
class SharedMainViewModel : ObservableObject { class SharedMainViewModel: ObservableObject {
@Published var welcomeViewDisplayed = false @Published var welcomeViewDisplayed = false
@Published var generalTermsAccepted = false @Published var generalTermsAccepted = false
@ -29,7 +29,7 @@ class SharedMainViewModel : ObservableObject {
init() { init() {
let preferences = UserDefaults.standard let preferences = UserDefaults.standard
let welcomeViewKey = "welcome_view" let welcomeViewKey = "welcome_view"
if preferences.object(forKey: welcomeViewKey) == nil { if preferences.object(forKey: welcomeViewKey) == nil {
@ -37,7 +37,7 @@ class SharedMainViewModel : ObservableObject {
} else { } else {
welcomeViewDisplayed = preferences.bool(forKey: welcomeViewKey) welcomeViewDisplayed = preferences.bool(forKey: welcomeViewKey)
} }
let generalTermsKey = "general_terms" let generalTermsKey = "general_terms"
if preferences.object(forKey: generalTermsKey) == nil { if preferences.object(forKey: generalTermsKey) == nil {
@ -55,33 +55,33 @@ class SharedMainViewModel : ObservableObject {
} }
} }
func changeWelcomeView(){ func changeWelcomeView() {
let preferences = UserDefaults.standard let preferences = UserDefaults.standard
welcomeViewDisplayed = true welcomeViewDisplayed = true
let welcomeViewKey = "welcome_view" let welcomeViewKey = "welcome_view"
preferences.set(welcomeViewDisplayed, forKey: welcomeViewKey) preferences.set(welcomeViewDisplayed, forKey: welcomeViewKey)
} }
func changeGeneralTerms(){ func changeGeneralTerms() {
let preferences = UserDefaults.standard let preferences = UserDefaults.standard
generalTermsAccepted = true generalTermsAccepted = true
let generalTermsKey = "general_terms" let generalTermsKey = "general_terms"
preferences.set(generalTermsAccepted, forKey: generalTermsKey) preferences.set(generalTermsAccepted, forKey: generalTermsKey)
} }
func changeDisplayProfileMode(){ func changeDisplayProfileMode() {
let preferences = UserDefaults.standard let preferences = UserDefaults.standard
displayProfileMode = true displayProfileMode = true
let displayProfileModeKey = "display_profile_mode" let displayProfileModeKey = "display_profile_mode"
preferences.set(displayProfileMode, forKey: displayProfileModeKey) preferences.set(displayProfileMode, forKey: displayProfileModeKey)
} }
func changeHideProfileMode(){ func changeHideProfileMode() {
let preferences = UserDefaults.standard let preferences = UserDefaults.standard
displayProfileMode = false displayProfileMode = false
let displayProfileModeKey = "display_profile_mode" let displayProfileModeKey = "display_profile_mode"
preferences.set(displayProfileMode, forKey: displayProfileModeKey) preferences.set(displayProfileMode, forKey: displayProfileModeKey)

View file

@ -20,20 +20,20 @@
import Foundation import Foundation
import SwiftUI import SwiftUI
struct WelcomePage1Fragment: View{ struct WelcomePage1Fragment: View {
var body: some View{ var body: some View {
VStack { VStack {
Spacer() Spacer()
VStack { VStack {
Image("linphone") Image("linphone")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
Text("Linphone") Text("Linphone")
.welcome_text_style_gray_800(styleSize: 30) .welcome_text_style_gray_800(styleSize: 30)
.padding(.bottom, 20) .padding(.bottom, 20)
Text("Une application de communication **sécurisée**, **open source** et **française**.") Text("Une application de communication **sécurisée**, **open source** et **française**.")
.welcome_text_style_gray(styleSize: 15) .welcome_text_style_gray(styleSize: 15)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)

View file

@ -22,18 +22,18 @@ import SwiftUI
struct WelcomePage2Fragment: View { struct WelcomePage2Fragment: View {
var body: some View{ var body: some View {
VStack { VStack {
Spacer() Spacer()
VStack { VStack {
Image("secure-image") Image("secure-image")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
.frame(width: 70, height: 100) .frame(width: 70, height: 100)
Text("Sécurisé") Text("Sécurisé")
.welcome_text_style_gray_800(styleSize: 30) .welcome_text_style_gray_800(styleSize: 30)
.padding(.bottom, 20) .padding(.bottom, 20)
Text("Vos communications sont en sécurité grâce aux **Chiffrement de bout en bout**.") Text("Vos communications sont en sécurité grâce aux **Chiffrement de bout en bout**.")
.welcome_text_style_gray(styleSize: 15) .welcome_text_style_gray(styleSize: 15)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)

View file

@ -22,18 +22,18 @@ import SwiftUI
struct WelcomePage3Fragment: View { struct WelcomePage3Fragment: View {
var body: some View{ var body: some View {
VStack { VStack {
Spacer() Spacer()
VStack { VStack {
Image("open-source") Image("open-source")
.renderingMode(.template) .renderingMode(.template)
.resizable() .resizable()
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
.frame(width: 100, height: 100) .frame(width: 100, height: 100)
Text("Open source") Text("Open source")
.welcome_text_style_gray_800(styleSize: 30) .welcome_text_style_gray_800(styleSize: 30)
.padding(.bottom, 20) .padding(.bottom, 20)
Text("Une application open source et un **service gratuit** depuis **2001**.") Text("Une application open source et un **service gratuit** depuis **2001**.")
.welcome_text_style_gray(styleSize: 15) .welcome_text_style_gray(styleSize: 15)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)

View file

@ -19,9 +19,9 @@
import SwiftUI import SwiftUI
struct WelcomeView: View{ struct WelcomeView: View {
@ObservedObject var sharedMainViewModel : SharedMainViewModel @ObservedObject var sharedMainViewModel: SharedMainViewModel
var permissionManager = PermissionManager.shared var permissionManager = PermissionManager.shared
@ -38,7 +38,7 @@ struct WelcomeView: View{
.frame(width: geometry.size.width, height: 100) .frame(width: geometry.size.width, height: 100)
.clipped() .clipped()
VStack (alignment: .trailing) { VStack(alignment: .trailing) {
Text("Skip") Text("Skip")
.underline() .underline()
.default_text_style_600(styleSize: 15) .default_text_style_600(styleSize: 15)
@ -68,7 +68,7 @@ struct WelcomeView: View{
Spacer() Spacer()
VStack{ VStack {
TabView(selection: $index) { TabView(selection: $index) {
ForEach((0..<3), id: \.self) { index in ForEach((0..<3), id: \.self) { index in
if index == 0 { if index == 0 {
@ -91,7 +91,7 @@ struct WelcomeView: View{
Spacer() Spacer()
Button(action: { Button(action: {
if index < 2 { if index < 2 {
withAnimation { withAnimation {
index += 1 index += 1
@ -99,15 +99,15 @@ struct WelcomeView: View{
} else if index == 2 { } else if index == 2 {
permissionManager.cameraRequestPermission() permissionManager.cameraRequestPermission()
} }
}) { }, label: {
Text(index == 2 ? "Start" : "Next") Text(index == 2 ? "Start" : "Next")
.default_text_style_white_600(styleSize: 20) .default_text_style_white_600(styleSize: 20)
.frame(height: 35) .frame(height: 35)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
} })
.padding(.horizontal, 20) .padding(.horizontal, 20)
.padding(.vertical, 10) .padding(.vertical, 10)
.background(Color.orange_main_500) .background(Color.orangeMain500)
.cornerRadius(60) .cornerRadius(60)
.padding(.horizontal) .padding(.horizontal)
.padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0) .padding(.bottom, geometry.safeAreaInsets.bottom.isEqual(to: 0.0) ? 20 : 0)
@ -126,7 +126,7 @@ struct WelcomeView: View{
} }
func setupAppearance() { func setupAppearance() {
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.orange_main_500) UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.orangeMain500)
if #available(iOS 16.0, *) { if #available(iOS 16.0, *) {
let dotCurrentImage = UIImage(named: "current-dot") let dotCurrentImage = UIImage(named: "current-dot")
@ -140,7 +140,7 @@ struct WelcomeView: View{
UIPageControl.appearance().setIndicatorImage(dotImage, forPage: 1) UIPageControl.appearance().setIndicatorImage(dotImage, forPage: 1)
UIPageControl.appearance().setIndicatorImage(dotImage, forPage: 2) UIPageControl.appearance().setIndicatorImage(dotImage, forPage: 2)
} }
UIPageControl.appearance().pageIndicatorTintColor = UIColor(Color.gray_main2_200) UIPageControl.appearance().pageIndicatorTintColor = UIColor(Color.grayMain2c200)
} }
} }

View file

@ -1,91 +1,91 @@
/* /*
* Copyright (c) 2010-2023 Belledonne Communications SARL. * Copyright (c) 2010-2023 Belledonne Communications SARL.
* *
* This file is part of Linphone * This file is part of Linphone
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import Foundation import Foundation
import SwiftUI import SwiftUI
extension Color { extension Color {
static let transparent_color = Color(hex: "#00000000") static let transparentColor = Color(hex: "#00000000")
static let black = Color(hex: "#000000") static let black = Color(hex: "#000000")
static let white = Color(hex: "#FFFFFF") static let white = Color(hex: "#FFFFFF")
static let orange_main_700 = Color(hex: "#B72D00") static let orangeMain700 = Color(hex: "#B72D00")
static let orange_main_500 = Color(hex: "#FF5E00") static let orangeMain500 = Color(hex: "#FF5E00")
static let orange_main_300 = Color(hex: "#FFB266") static let orangeMain300 = Color(hex: "#FFB266")
static let orange_main_100 = Color(hex: "#FFEACB") static let orangeMain100 = Color(hex: "#FFEACB")
static let orange_main_100_alpha_50 = Color(hex: "#80FFEACB") static let orangeMain100Alpha50 = Color(hex: "#80FFEACB")
static let gray_main2_800 = Color(hex: "#22334D") static let grayMain2c800 = Color(hex: "#22334D")
static let gray_main2_800_alpha_65 = Color(hex: "#A622334D") static let grayMain2c800Alpha65 = Color(hex: "#A622334D")
static let gray_main2_700 = Color(hex: "#364860") static let grayMain2c700 = Color(hex: "#364860")
static let gray_main2_600 = Color(hex: "#4E6074") static let grayMain2c600 = Color(hex: "#4E6074")
static let gray_main2_500 = Color(hex: "#6C7A87") static let grayMain2c500 = Color(hex: "#6C7A87")
static let gray_main2_400 = Color(hex: "#9AABB5") static let grayMain2c400 = Color(hex: "#9AABB5")
static let gray_main2_300 = Color(hex: "#C0D1D9") static let grayMain2c300 = Color(hex: "#C0D1D9")
static let gray_main2_200 = Color(hex: "#DFECF2") static let grayMain2c200 = Color(hex: "#DFECF2")
static let gray_main2_100 = Color(hex: "#EEF6F8") static let grayMain2c100 = Color(hex: "#EEF6F8")
static let gray_100 = Color(hex: "#F9F9F9") static let gray100 = Color(hex: "#F9F9F9")
static let gray_200 = Color(hex: "#EDEDED") static let gray200 = Color(hex: "#EDEDED")
static let gray_300 = Color(hex: "#C9C9C9") static let gray300 = Color(hex: "#C9C9C9")
static let gray_400 = Color(hex: "#949494") static let gray400 = Color(hex: "#949494")
static let gray_500 = Color(hex: "#4E4E4E") static let gray500 = Color(hex: "#4E4E4E")
static let gray_600 = Color(hex: "#2E3030") static let gray600 = Color(hex: "#2E3030")
static let gray_900 = Color(hex: "#070707") static let gray900 = Color(hex: "#070707")
static let red_danger_200 = Color(hex: "#F5CCBE") static let redDanger200 = Color(hex: "#F5CCBE")
static let red_danger_500 = Color(hex: "#DD5F5F") static let redDanger500 = Color(hex: "#DD5F5F")
static let red_danger_700 = Color(hex: "#9E3548") static let redDanger700 = Color(hex: "#9E3548")
static let green_success_500 = Color(hex: "#4FAE80") static let greenSuccess500 = Color(hex: "#4FAE80")
static let green_success_700 = Color(hex: "#377D71") static let greenSuccess700 = Color(hex: "#377D71")
static let green_success_200 = Color(hex: "#ACF5C1") static let greenSuccess200 = Color(hex: "#ACF5C1")
static let blue_info_500 = Color(hex: "#4AA8FF") static let blueInfo500 = Color(hex: "#4AA8FF")
static let orange_warning_600 = Color(hex: "#DBB820") static let orangeWarning600 = Color(hex: "#DBB820")
static let orange_away = Color(hex: "#FFA645") static let orangeAway = Color(hex: "#FFA645")
init(hex: String) { init(hex: String) {
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int: UInt64 = 0 var int: UInt64 = 0
Scanner(string: hex).scanHexInt64(&int) Scanner(string: hex).scanHexInt64(&int)
let a, r, g, b: UInt64 let alpha, red, green, blue: UInt64
switch hex.count { switch hex.count {
case 3: // RGB (12-bit) case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) (alpha, red, green, blue) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit) case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) (alpha, red, green, blue) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit) case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) (alpha, red, green, blue) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default: default:
(a, r, g, b) = (1, 1, 1, 0) (alpha, red, green, blue) = (1, 1, 1, 0)
} }
self.init( self.init(
.sRGB, .sRGB,
red: Double(r) / 255, red: Double(red) / 255,
green: Double(g) / 255, green: Double(green) / 255,
blue: Double(b) / 255, blue: Double(blue) / 255,
opacity: Double(a) / 255 opacity: Double(alpha) / 255
) )
} }
} }

View file

@ -20,7 +20,7 @@
import Foundation import Foundation
import Photos import Photos
class PermissionManager : ObservableObject { class PermissionManager: ObservableObject {
static let shared = PermissionManager() static let shared = PermissionManager()
@ -29,7 +29,7 @@ class PermissionManager : ObservableObject {
private init() {} private init() {}
func photoLibraryRequestPermission(){ func photoLibraryRequestPermission() {
PHPhotoLibrary.requestAuthorization(for: .readWrite, handler: {status in PHPhotoLibrary.requestAuthorization(for: .readWrite, handler: {status in
DispatchQueue.main.async { DispatchQueue.main.async {
self.photoLibraryPermissionGranted = (status == .authorized || status == .limited || status == .restricted) self.photoLibraryPermissionGranted = (status == .authorized || status == .limited || status == .restricted)

View file

@ -21,96 +21,96 @@ import Foundation
import SwiftUI import SwiftUI
extension View { extension View {
func default_text_style_300(styleSize: CGFloat) -> some View { func default_text_style_300(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Light", size: styleSize)) self.font(Font.custom("NotoSans-Light", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func default_text_style(styleSize: CGFloat) -> some View { func default_text_style(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Regular", size: styleSize)) self.font(Font.custom("NotoSans-Regular", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func default_text_style_500(styleSize: CGFloat) -> some View { func default_text_style_500(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Medium", size: styleSize)) self.font(Font.custom("NotoSans-Medium", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func default_text_style_600(styleSize: CGFloat) -> some View { func default_text_style_600(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-SemiBold", size: styleSize)) self.font(Font.custom("NotoSans-SemiBold", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func default_text_style_700(styleSize: CGFloat) -> some View { func default_text_style_700(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Bold", size: styleSize)) self.font(Font.custom("NotoSans-Bold", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func default_text_style_800(styleSize: CGFloat) -> some View { func default_text_style_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize)) self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func default_text_style_white_300(styleSize: CGFloat) -> some View { func default_text_style_white_300(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Light", size: styleSize)) self.font(Font.custom("NotoSans-Light", size: styleSize))
.foregroundStyle(Color.white) .foregroundStyle(Color.white)
} }
func default_text_style_white(styleSize: CGFloat) -> some View { func default_text_style_white(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Regular", size: styleSize)) self.font(Font.custom("NotoSans-Regular", size: styleSize))
.foregroundStyle(Color.white) .foregroundStyle(Color.white)
} }
func default_text_style_white_500(styleSize: CGFloat) -> some View { func default_text_style_white_500(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Medium", size: styleSize)) self.font(Font.custom("NotoSans-Medium", size: styleSize))
.foregroundStyle(Color.white) .foregroundStyle(Color.white)
} }
func default_text_style_white_600(styleSize: CGFloat) -> some View { func default_text_style_white_600(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-SemiBold", size: styleSize)) self.font(Font.custom("NotoSans-SemiBold", size: styleSize))
.foregroundStyle(Color.white) .foregroundStyle(Color.white)
} }
func default_text_style_white_700(styleSize: CGFloat) -> some View { func default_text_style_white_700(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Bold", size: styleSize)) self.font(Font.custom("NotoSans-Bold", size: styleSize))
.foregroundStyle(Color.white) .foregroundStyle(Color.white)
} }
func default_text_style_white_800(styleSize: CGFloat) -> some View { func default_text_style_white_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize)) self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
.foregroundStyle(Color.white) .foregroundStyle(Color.white)
} }
func default_text_style_orange_300(styleSize: CGFloat) -> some View { func default_text_style_orange_300(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Light", size: styleSize)) self.font(Font.custom("NotoSans-Light", size: styleSize))
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
} }
func default_text_style_orange(styleSize: CGFloat) -> some View { func default_text_style_orange(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Regular", size: styleSize)) self.font(Font.custom("NotoSans-Regular", size: styleSize))
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
} }
func default_text_style_orange_500(styleSize: CGFloat) -> some View { func default_text_style_orange_500(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Medium", size: styleSize)) self.font(Font.custom("NotoSans-Medium", size: styleSize))
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
} }
func default_text_style_orange_600(styleSize: CGFloat) -> some View { func default_text_style_orange_600(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-SemiBold", size: styleSize)) self.font(Font.custom("NotoSans-SemiBold", size: styleSize))
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
} }
func default_text_style_orange_700(styleSize: CGFloat) -> some View { func default_text_style_orange_700(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Bold", size: styleSize)) self.font(Font.custom("NotoSans-Bold", size: styleSize))
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
} }
func default_text_style_orange_800(styleSize: CGFloat) -> some View { func default_text_style_orange_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize)) self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
.foregroundStyle(Color.orange_main_500) .foregroundStyle(Color.orangeMain500)
} }
func welcome_text_style_white_800(styleSize: CGFloat) -> some View { func welcome_text_style_white_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize)) self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
@ -119,21 +119,21 @@ extension View {
func welcome_text_style_gray_800(styleSize: CGFloat) -> some View { func welcome_text_style_gray_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize)) self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
} }
func welcome_text_style_gray(styleSize: CGFloat) -> some View { func welcome_text_style_gray(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Regular", size: styleSize)) self.font(Font.custom("NotoSans-Regular", size: styleSize))
.foregroundStyle(Color.gray_main2_600) .foregroundStyle(Color.grayMain2c600)
}
func profile_mode_text_style_gray_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
.foregroundStyle(Color.gray900)
}
func profile_mode_text_style_gray(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Regular", size: styleSize))
.foregroundStyle(Color.grayMain2c600)
} }
func profile_mode_text_style_gray_800(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-ExtraBold", size: styleSize))
.foregroundStyle(Color.gray_900)
}
func profile_mode_text_style_gray(styleSize: CGFloat) -> some View {
self.font(Font.custom("NotoSans-Regular", size: styleSize))
.foregroundStyle(Color.gray_main2_600)
}
} }

View file

@ -23,3 +23,11 @@ target 'Linphone' do
basic_pods basic_pods
end end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
end
end
end