diff --git a/Linphone/Core/CoreContext.swift b/Linphone/Core/CoreContext.swift
index 37d55a18e..664574dff 100644
--- a/Linphone/Core/CoreContext.swift
+++ b/Linphone/Core/CoreContext.swift
@@ -305,6 +305,7 @@ class CoreContext: ObservableObject {
}
}, onConfiguringStatus: { (_: Core, status: ConfiguringState, message: String) in
Log.info("New configuration state is \(status) = \(message)\n")
+ let themeMainColor = CorePreferences.themeMainColor
DispatchQueue.main.async {
if status == ConfiguringState.Successful {
var accountModels: [AccountModel] = []
@@ -312,6 +313,7 @@ class CoreContext: ObservableObject {
accountModels.append(AccountModel(account: account, core: self.mCore))
}
self.accounts = accountModels
+ ThemeManager.shared.applyTheme(named: themeMainColor)
}
}
}, onLogCollectionUploadStateChanged: { (_: Core, _: Core.LogCollectionUploadState, info: String) in
diff --git a/Linphone/SplashScreen.swift b/Linphone/SplashScreen.swift
index e15c4aaac..8c9b2e48d 100644
--- a/Linphone/SplashScreen.swift
+++ b/Linphone/SplashScreen.swift
@@ -28,10 +28,13 @@ struct SplashScreen: View {
HStack {
Spacer()
Image("linphone")
+ .renderingMode(.template)
+ .foregroundColor(ThemeManager.shared.currentTheme.main500)
Spacer()
}
Spacer()
}
+
}
.ignoresSafeArea(.all)
diff --git a/Linphone/Utils/Extensions/ColorExtension.swift b/Linphone/Utils/Extensions/ColorExtension.swift
index 19fc96c2e..111472603 100644
--- a/Linphone/Utils/Extensions/ColorExtension.swift
+++ b/Linphone/Utils/Extensions/ColorExtension.swift
@@ -26,11 +26,11 @@ extension Color {
static let black = Color(hex: "#000000")
static let white = Color(hex: "#FFFFFF")
- static let orangeMain700 = Color(hex: "#B72D00")
- static let orangeMain500 = Color(hex: "#FF5E00")
- static let orangeMain300 = Color(hex: "#FFB266")
- static let orangeMain100 = Color(hex: "#FFEACB")
- static let orangeMain100Alpha50 = Color(hex: "#80FFEACB")
+ static let orangeMain700 = ThemeManager.shared.currentTheme.main700
+ static let orangeMain500 = ThemeManager.shared.currentTheme.main500
+ static let orangeMain300 = ThemeManager.shared.currentTheme.main300
+ static let orangeMain100 = ThemeManager.shared.currentTheme.main100
+ static let orangeMain100Alpha50 = ThemeManager.shared.currentTheme.main100Alpha50
static let grayMain2c800 = Color(hex: "#22334D")
static let grayMain2c800Alpha65 = Color(hex: "#A622334D")
diff --git a/Linphone/Utils/Extensions/ConfigExtension.swift b/Linphone/Utils/Extensions/ConfigExtension.swift
index 697b25221..843bb861b 100644
--- a/Linphone/Utils/Extensions/ConfigExtension.swift
+++ b/Linphone/Utils/Extensions/ConfigExtension.swift
@@ -38,6 +38,10 @@ extension Config {
if _instance == nil {
let factoryPath = FileUtil.bundleFilePath("linphonerc-factory")!
_instance = Config.newForSharedCore(appGroupId: Config.appGroupName, configFilename: "linphonerc", factoryConfigFilename: factoryPath)!
+ let themeMainColor = CorePreferences.themeMainColor
+ DispatchQueue.main.async {
+ ThemeManager.shared.applyTheme(named: themeMainColor)
+ }
}
return _instance!
}
diff --git a/Linphone/Utils/ThemeManager.swift b/Linphone/Utils/ThemeManager.swift
new file mode 100644
index 000000000..cc8a892fc
--- /dev/null
+++ b/Linphone/Utils/ThemeManager.swift
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2010-2025 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-iphone
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import SwiftUI
+
+
+struct Theme {
+ let name: String
+ let main100: Color
+ let main100Alpha50: Color
+ let main300: Color
+ let main500: Color
+ let main700: Color
+}
+
+class ThemeManager {
+
+ static let shared = ThemeManager()
+ private let themeKey = "selectedTheme"
+ var currentTheme: Theme
+
+ init () {
+ let storedName = UserDefaults.standard.string(forKey: themeKey)
+ currentTheme = themes[storedName ?? ""] ?? ThemeManager.orange
+ }
+
+ func applyTheme(named name: String) {
+ guard let theme = themes[name] else {
+ return
+ }
+ self.currentTheme = theme
+ UserDefaults.standard.setValue(name, forKey: self.themeKey)
+ }
+
+ // MARK: - Theme Instances
+
+ let themes: [String: Theme] = [
+ orange.name: orange,
+ yellow.name: yellow,
+ green.name: green,
+ blue.name: blue,
+ red.name: red,
+ pink.name: pink,
+ purple.name: purple
+ ]
+
+ static let orange = Theme(
+ name: "orange",
+ main100: Color(hex: "#FFEACB"),
+ main100Alpha50: Color(hex: "#80FFEACB"),
+ main300: Color(hex: "#FFB266"),
+ main500: Color(hex: "#FF5E00"),
+ main700: Color(hex: "#B72D00")
+ )
+
+ static let yellow = Theme(
+ name: "yellow",
+ main100: Color(hex: "#FFF5D6"),
+ main100Alpha50: Color(hex: "#80FFF5D6"),
+ main300: Color(hex: "#FFE799"),
+ main500: Color(hex: "#F5BC00"),
+ main700: Color(hex: "#A37D00")
+ )
+
+ static let green = Theme(
+ name: "green",
+ main100: Color(hex: "#DCF9E7"),
+ main100Alpha50: Color(hex: "#80DCF9E7"),
+ main300: Color(hex: "#A8F0C2"),
+ main500: Color(hex: "#25D366"),
+ main700: Color(hex: "#1C9C4B")
+ )
+
+ static let blue = Theme(
+ name: "blue",
+ main100: Color(hex: "#D6F4FF"),
+ main100Alpha50: Color(hex: "#80D6F4FF"),
+ main300: Color(hex: "#99E4FF"),
+ main500: Color(hex: "#00AFF0"),
+ main700: Color(hex: "#0078A3")
+ )
+
+ static let red = Theme(
+ name: "red",
+ main100: Color(hex: "#FBE1DA"),
+ main100Alpha50: Color(hex: "#80FBE1DA"),
+ main300: Color(hex: "#F5B53A"),
+ main500: Color(hex: "#E14318"),
+ main700: Color(hex: "#A63211")
+ )
+
+ static let pink = Theme(
+ name: "pink",
+ main100: Color(hex: "#FFD6F1"),
+ main100Alpha50: Color(hex: "#80FFD6F1"),
+ main300: Color(hex: "#FF99DD"),
+ main500: Color(hex: "#FF00A9"),
+ main700: Color(hex: "#B8007A")
+ )
+
+ static let purple = Theme(
+ name: "purple",
+ main100: Color(hex: "#FFD6FF"),
+ main100Alpha50: Color(hex: "#80FFD6FF"),
+ main300: Color(hex: "#FF99FF"),
+ main500: Color(hex: "#800080"),
+ main700: Color(hex: "#520052")
+ )
+
+}
diff --git a/LinphoneApp.xcodeproj/project.pbxproj b/LinphoneApp.xcodeproj/project.pbxproj
index 627028a27..a3573d7a7 100644
--- a/LinphoneApp.xcodeproj/project.pbxproj
+++ b/LinphoneApp.xcodeproj/project.pbxproj
@@ -47,6 +47,9 @@
C62817302C1C3DCC00DBA646 /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C628172F2C1C3DCC00DBA646 /* AccountModel.swift */; };
C62817322C1C400A00DBA646 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C62817312C1C400A00DBA646 /* StringExtension.swift */; };
C62817342C1C7C7400DBA646 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C62817332C1C7C7400DBA646 /* HelpView.swift */; };
+ C642277B2E8E4AC50094FEDC /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C642277A2E8E4AC50094FEDC /* ThemeManager.swift */; };
+ C642277C2E8E4D900094FEDC /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C642277A2E8E4AC50094FEDC /* ThemeManager.swift */; };
+ C642277D2E8E4E2B0094FEDC /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; };
C67586AE2C09F23C002E77BF /* URLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67586AD2C09F23C002E77BF /* URLExtension.swift */; };
C67586B02C09F247002E77BF /* URIHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67586AF2C09F247002E77BF /* URIHandler.swift */; };
C67586B52C09F617002E77BF /* SingleSignOnManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67586B22C09F617002E77BF /* SingleSignOnManager.swift */; };
@@ -268,6 +271,7 @@
C628172F2C1C3DCC00DBA646 /* AccountModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountModel.swift; sourceTree = ""; };
C62817312C1C400A00DBA646 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; };
C62817332C1C7C7400DBA646 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = ""; };
+ C642277A2E8E4AC50094FEDC /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = ""; };
C67586AD2C09F23C002E77BF /* URLExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLExtension.swift; sourceTree = ""; };
C67586AF2C09F247002E77BF /* URIHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URIHandler.swift; sourceTree = ""; };
C67586B22C09F617002E77BF /* SingleSignOnManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleSignOnManager.swift; sourceTree = ""; };
@@ -585,6 +589,7 @@
D717071C2AC591EF0037746F /* Utils */ = {
isa = PBXGroup;
children = (
+ C642277A2E8E4AC50094FEDC /* ThemeManager.swift */,
D738ACED2E857BEF0039F7D1 /* KeyboardResponder.swift */,
D7DF8BE82E2104E5003A3BC7 /* EmojiPickerView.swift */,
D703F7072DC8C5FF005B8F75 /* FilePicker.swift */,
@@ -1246,9 +1251,11 @@
66FBFC482B83B8CC00BC6AB1 /* Log.swift in Sources */,
6691CA7E2B839C2D00B2A7B8 /* NotificationService.swift in Sources */,
66FBFC492B83BD2400BC6AB1 /* ConfigExtension.swift in Sources */,
+ C642277D2E8E4E2B0094FEDC /* ColorExtension.swift in Sources */,
66FBFC4A2B83BD3300BC6AB1 /* FileUtils.swift in Sources */,
66FBFC4B2B83BD7B00BC6AB1 /* CoreExtension.swift in Sources */,
D756C8172D352C5F00A58F2F /* CorePreferences.swift in Sources */,
+ C642277C2E8E4D900094FEDC /* ThemeManager.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1400,6 +1407,7 @@
D7CEE0352B7A210300FD79B7 /* ConversationsView.swift in Sources */,
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */,
D71968922B86369D00DF4459 /* ChatBubbleView.swift in Sources */,
+ C642277B2E8E4AC50094FEDC /* ThemeManager.swift in Sources */,
D732C38C2D311D2500F78100 /* SettingsFragment.swift in Sources */,
D78290B82ADD3910004AA85C /* ContactsFragment.swift in Sources */,
D7DA67642ACCB31700E95002 /* ProfileModeFragment.swift in Sources */,