From 8d0f638d4647418996c58a537a2cf0b0192946c1 Mon Sep 17 00:00:00 2001 From: Benoit Martins Date: Thu, 29 Jan 2026 10:30:08 +0100 Subject: [PATCH] Refactor CorePreferences by adding new values --- Linphone/Core/CoreContext.swift | 43 +- Linphone/Core/CorePreferences.swift | 448 ++++++++++-------- Linphone/GeneratedGit.swift | 2 +- .../ViewModel/ConversationViewModel.swift | 2 +- .../Main/Help/Fragments/DebugFragment.swift | 2 +- .../Main/Viewmodel/SharedMainViewModel.swift | 7 + 6 files changed, 269 insertions(+), 235 deletions(-) diff --git a/Linphone/Core/CoreContext.swift b/Linphone/Core/CoreContext.swift index adb76dbaa..01125c8f6 100644 --- a/Linphone/Core/CoreContext.swift +++ b/Linphone/Core/CoreContext.swift @@ -59,41 +59,6 @@ class CoreContext: ObservableObject { var digestAuthInfoPendingPasswordUpdate: AuthInfo? - static let appGroupName: String = { - Bundle.main.object(forInfoDictionaryKey: "APP_GROUP_NAME") as? String - ?? { - fatalError("APP_GROUP_NAME not defined in Info.plist") - }() - }() - - var teamID: String { - AppServices.config.getString(section: "app", key: "team_id", defaultString: "") - } - - var earlymediaContentExtCatIdentifier: String { - AppServices.config.getString(section: "app", key: "extension_category", defaultString: "") - } - - var serveraddress: String { - AppServices.config.getString(section: "app", key: "server", defaultString: "") - } - - var defaultUsername: String { - AppServices.config.getString(section: "app", key: "user", defaultString: "") - } - - var defaultPass: String { - AppServices.config.getString(section: "app", key: "pass", defaultString: "") - } - - var pushNotificationsInterval: Int { - AppServices.config.getInt(section: "net", key: "pn-call-remote-push-interval", defaultValue: 3) - } - - var voiceRecordingMaxDuration: Int { - AppServices.config.getInt(section: "app", key: "voice_recording_max_duration", defaultValue: 600000) - } - @Published var reloadID = UUID() private init() { @@ -157,11 +122,11 @@ class CoreContext: ObservableObject { coreQueue.async { LoggingService.Instance.logLevel = LogLevel.Debug - Factory.Instance.logCollectionPath = Factory.Instance.getDataDir(context: UnsafeMutablePointer(mutating: (CoreContext.appGroupName as NSString).utf8String)) + Factory.Instance.logCollectionPath = Factory.Instance.getDataDir(context: UnsafeMutablePointer(mutating: (SharedMainViewModel.appGroupName as NSString).utf8String)) Factory.Instance.enableLogCollection(state: LogCollectionState.Enabled) Log.info("Checking if linphonerc file exists already. If not, creating one as a copy of linphonerc-default") - if let rcDir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: CoreContext.appGroupName)? + if let rcDir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: SharedMainViewModel.appGroupName)? .appendingPathComponent("Library/Preferences/linphone") { let rcFileUrl = rcDir.appendingPathComponent("linphonerc") if !FileManager.default.fileExists(atPath: rcFileUrl.path) { @@ -179,7 +144,7 @@ class CoreContext: ObservableObject { } } - self.mCore = try? Factory.Instance.createSharedCoreWithConfig(config: AppServices.config, systemContext: Unmanaged.passUnretained(coreQueue).toOpaque(), appGroupId: CoreContext.appGroupName, mainCore: true) + self.mCore = try? Factory.Instance.createSharedCoreWithConfig(config: AppServices.config, systemContext: Unmanaged.passUnretained(coreQueue).toOpaque(), appGroupId: SharedMainViewModel.appGroupName, mainCore: true) self.mCore.callkitEnabled = true self.mCore.pushNotificationEnabled = true @@ -559,7 +524,7 @@ class CoreContext: ObservableObject { } func copyDatabaseFileToDocumentsDirectory() { - if let rcDir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: CoreContext.appGroupName)? + if let rcDir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: SharedMainViewModel.appGroupName)? .appendingPathComponent("Library/Application Support/linphone") { let rcFileUrl = rcDir.appendingPathComponent("linphone.db") let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first diff --git a/Linphone/Core/CorePreferences.swift b/Linphone/Core/CorePreferences.swift index 6bca2ebe9..4b4851b23 100644 --- a/Linphone/Core/CorePreferences.swift +++ b/Linphone/Core/CorePreferences.swift @@ -1,7 +1,7 @@ /* * Copyright (c) 2010-2023 Belledonne Communications SARL. * - * This file is part of linphone-iphone + * This file is part of Linphone * * 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 @@ -28,30 +28,39 @@ class CorePreferences { self.config = config } - var printLogsInLogcat: Bool { + var acceptEarlyMedia: Bool { get { - config.getBool(section: "app", key: "debug", defaultValue: true) + config.getBool(section: "sip", key: "incoming_calls_early_media", defaultValue: false) } set { - config.setBool(section: "app", key: "debug", value: newValue) - } - } - - var firstLaunch: Bool { - get { - config.getBool(section: "app", key: "first_6.0_launch", defaultValue: true) - } - set { - config.setBool(section: "app", key: "first_6.0_launch", value: newValue) + config.setBool(section: "sip", key: "incoming_calls_early_media", value: newValue) } } - var linphoneConfigurationVersion: Int { + var allowOutgoingEarlyMedia: Bool { get { - config.getInt(section: "app", key: "config_version", defaultValue: 52005) + config.getBool(section: "sip", key: "real_early_media", defaultValue: false) } set { - config.setInt(section: "app", key: "config_version", value: newValue) + config.setBool(section: "sip", key: "real_early_media", value: newValue) + } + } + + var automaticallyStartCallRecording: Bool { + get { + config.getBool(section: "app", key: "auto_start_call_record", defaultValue: false) + } + set { + config.setBool(section: "app", key: "auto_start_call_record", value: newValue) + } + } + + var changeMainColorAllowed: Bool { + get { + config.getBool(section: "ui", key: "change_main_color_allowed", defaultValue: false) + } + set { + config.setBool(section: "ui", key: "change_main_color_allowed", value: newValue) } } @@ -74,70 +83,6 @@ class CorePreferences { } } - var publishPresence: Bool { - get { - config.getBool(section: "app", key: "publish_presence", defaultValue: true) - } - set { - config.setBool(section: "app", key: "publish_presence", value: newValue) - } - } - - var keepServiceAlive: Bool { - get { - config.getBool(section: "app", key: "keep_service_alive", defaultValue: false) - } - set { - config.setBool(section: "app", key: "keep_service_alive", value: newValue) - } - } - - var deviceName: String { - get { - let raw = config.getString(section: "app", key: "device", defaultString: "").trimmingCharacters(in: .whitespaces) - return safeString(raw, defaultValue: "") - } - set { - config.setString(section: "app", key: "device", value: newValue.trimmingCharacters(in: .whitespaces)) - } - } - - var routeAudioToSpeakerWhenVideoIsEnabled: Bool { - get { - config.getBool(section: "app", key: "route_audio_to_speaker_when_video_enabled", defaultValue: true) - } - set { - config.setBool(section: "app", key: "route_audio_to_speaker_when_video_enabled", value: newValue) - } - } - - var automaticallyStartCallRecording: Bool { - get { - return config.getBool(section: "app", key: "auto_start_call_record", defaultValue: false) - } - set { - config.setBool(section: "app", key: "auto_start_call_record", value: newValue) - } - } - - var showDialogWhenCallingDeviceUuidDirectly: Bool { - get { - return config.getBool(section: "app", key: "show_confirmation_dialog_zrtp_trust_call", defaultValue: true) - } - set { - config.setBool(section: "app", key: "show_confirmation_dialog_zrtp_trust_call", value: newValue) - } - } - - var markConversationAsReadWhenDismissingMessageNotification: Bool { - get { - config.getBool(section: "app", key: "mark_as_read_notif_dismissal", defaultValue: false) - } - set { - config.setBool(section: "app", key: "mark_as_read_notif_dismissal", value: newValue) - } - } - var contactsFilter: String { get { let raw = config.getString(section: "ui", key: "contacts_filter", defaultString: "") @@ -148,42 +93,6 @@ class CorePreferences { } } - var disableAddContact: Bool { - get { - config.getBool(section: "ui", key: "disable_add_contact", defaultValue: false) - } - set { - config.setBool(section: "ui", key: "disable_add_contact", value: newValue) - } - } - - var showFavoriteContacts: Bool { - get { - config.getBool(section: "ui", key: "show_favorites_contacts", defaultValue: true) - } - set { - config.setBool(section: "ui", key: "show_favorites_contacts", value: newValue) - } - } - - var friendListInWhichStoreNewlyCreatedFriends: String { - get { - config.getString(section: "app", key: "friend_list_to_store_newly_created_contacts", defaultString: "Linphone address-book") - } - set { - config.setString(section: "app", key: "friend_list_to_store_newly_created_contacts", value: newValue) - } - } - - var voiceRecordingMaxDuration: Int { - get { - config.getInt(section: "app", key: "voice_recording_max_duration", defaultValue: 600000) - } - set { - config.setInt(section: "app", key: "voice_recording_max_duration", value: newValue) - } - } - var darkMode: Int { get { if !darkModeAllowed { return 0 } @@ -194,86 +103,12 @@ class CorePreferences { } } - var enableSecureMode: Bool { - get { - config.getBool(section: "ui", key: "enable_secure_mode", defaultValue: true) - } - set { - config.setBool(section: "ui", key: "enable_secure_mode", value: newValue) - } - } - - var themeMainColor: String { - get { - let raw = config.getString(section: "ui", key: "theme_main_color", defaultString: "orange") - return safeString(raw, defaultValue: "orange") - } - set { - config.setString(section: "ui", key: "theme_main_color", value: newValue) - } - } - - var themeAboutPictureUrl: String? { - get { - return config.getString(section: "ui", key: "theme_about_picture_url", defaultString: nil) - } - } - var darkModeAllowed: Bool { - config.getBool(section: "ui", key: "dark_mode_allowed", defaultValue: true) - } - - var changeMainColorAllowed: Bool { - config.getBool(section: "ui", key: "change_main_color_allowed", defaultValue: false) - } - - var hideSettings: Bool { - config.getBool(section: "ui", key: "hide_settings", defaultValue: false) - } - - var maxAccountsCount: Int { - config.getInt(section: "ui", key: "max_account", defaultValue: 0) - } - - /* - var configPath: String { - return context.view.window?.rootViewController?.view.frame.origin.x ?? "" + "/.linphonerc" - } - - var factoryConfigPath: String { - return context.view.window?.rootViewController?.view.frame.origin.x ?? "" + "/linphonerc" - } - - func copyAssetsFromPackage() { - copy(from: "linphonerc_default", to: configPath) - copy(from: "linphonerc_factory", to: factoryConfigPath, overrideIfExists: true) - } - */ - - var vfsEnabled: Bool { get { - config.getBool(section: "app", key: "vfs_enabled", defaultValue: false) + config.getBool(section: "ui", key: "dark_mode_allowed", defaultValue: true) } set { - config.setBool(section: "app", key: "vfs_enabled", value: newValue) - } - } - - var acceptEarlyMedia: Bool { - get { - config.getBool(section: "sip", key: "incoming_calls_early_media", defaultValue: false) - } - set { - config.setBool(section: "sip", key: "incoming_calls_early_media", value: newValue) - } - } - - var allowOutgoingEarlyMedia: Bool { - get { - config.getBool(section: "sip", key: "real_early_media", defaultValue: false) - } - set { - config.setBool(section: "sip", key: "real_early_media", value: newValue) + config.setBool(section: "ui", key: "dark_mode_allowed", value: newValue) } } @@ -286,7 +121,44 @@ class CorePreferences { config.setString(section: "app", key: "default_domain", value: newValue) } } - + + var defaultPass: String { + get { + config.getString(section: "app", key: "pass", defaultString: "") + } + set { + config.setString(section: "app", key: "pass", value: newValue) + } + } + + var defaultUsername: String { + get { + config.getString(section: "app", key: "user", defaultString: "") + } + set { + config.setString(section: "app", key: "user", value: newValue) + } + } + + var deviceName: String { + get { + let raw = config.getString(section: "app", key: "device", defaultString: "").trimmingCharacters(in: .whitespaces) + return safeString(raw, defaultValue: "") + } + set { + config.setString(section: "app", key: "device", value: newValue.trimmingCharacters(in: .whitespaces)) + } + } + + var disableAddContact: Bool { + get { + config.getBool(section: "ui", key: "disable_add_contact", defaultValue: false) + } + set { + config.setBool(section: "ui", key: "disable_add_contact", value: newValue) + } + } + var disableChatFeature: Bool { get { config.getBool(section: "ui", key: "disable_chat_feature", defaultValue: false) @@ -305,6 +177,51 @@ class CorePreferences { } } + var earlymediaContentExtCatIdentifier: String { + get { + config.getString(section: "app", key: "extension_category", defaultString: "") + } + set { + config.setString(section: "app", key: "extension_category", value: newValue) + } + } + + var enableSecureMode: Bool { + get { + config.getBool(section: "ui", key: "enable_secure_mode", defaultValue: true) + } + set { + config.setBool(section: "ui", key: "enable_secure_mode", value: newValue) + } + } + + var firstLaunch: Bool { + get { + config.getBool(section: "app", key: "first_6.0_launch", defaultValue: true) + } + set { + config.setBool(section: "app", key: "first_6.0_launch", value: newValue) + } + } + + var friendListInWhichStoreNewlyCreatedFriends: String { + get { + config.getString(section: "app", key: "friend_list_to_store_newly_created_contacts", defaultString: "Linphone address-book") + } + set { + config.setString(section: "app", key: "friend_list_to_store_newly_created_contacts", value: newValue) + } + } + + var hideSettings: Bool { + get { + config.getBool(section: "ui", key: "hide_settings", defaultValue: false) + } + set { + config.setBool(section: "ui", key: "hide_settings", value: newValue) + } + } + var hideSipAddresses: Bool { get { config.getBool(section: "ui", key: "hide_sip_addresses", defaultValue: false) @@ -314,6 +231,151 @@ class CorePreferences { } } + var keepServiceAlive: Bool { + get { + config.getBool(section: "app", key: "keep_service_alive", defaultValue: false) + } + set { + config.setBool(section: "app", key: "keep_service_alive", value: newValue) + } + } + + var linphoneConfigurationVersion: Int { + get { + config.getInt(section: "app", key: "config_version", defaultValue: 52005) + } + set { + config.setInt(section: "app", key: "config_version", value: newValue) + } + } + + var markConversationAsReadWhenDismissingMessageNotification: Bool { + get { + config.getBool(section: "app", key: "mark_as_read_notif_dismissal", defaultValue: false) + } + set { + config.setBool(section: "app", key: "mark_as_read_notif_dismissal", value: newValue) + } + } + + var maxAccountsCount: Int { + get { + config.getInt(section: "ui", key: "max_account", defaultValue: 0) + } + set { + config.setInt(section: "ui", key: "max_account", value: newValue) + } + } + + var printLogsInLogcat: Bool { + get { + config.getBool(section: "app", key: "debug", defaultValue: true) + } + set { + config.setBool(section: "app", key: "debug", value: newValue) + } + } + + var publishPresence: Bool { + get { + config.getBool(section: "app", key: "publish_presence", defaultValue: true) + } + set { + config.setBool(section: "app", key: "publish_presence", value: newValue) + } + } + + var pushNotificationsInterval: Int { + get { + config.getInt(section: "net", key: "pn-call-remote-push-interval", defaultValue: 3) + } + set { + config.setInt(section: "net", key: "pn-call-remote-push-interval", value: newValue) + } + } + + var routeAudioToSpeakerWhenVideoIsEnabled: Bool { + get { + config.getBool(section: "app", key: "route_audio_to_speaker_when_video_enabled", defaultValue: true) + } + set { + config.setBool(section: "app", key: "route_audio_to_speaker_when_video_enabled", value: newValue) + } + } + + var serveraddress: String { + get { + config.getString(section: "app", key: "server", defaultString: "") + } + set { + config.setString(section: "app", key: "server", value: newValue) + } + } + + var showDialogWhenCallingDeviceUuidDirectly: Bool { + get { + config.getBool(section: "app", key: "show_confirmation_dialog_zrtp_trust_call", defaultValue: true) + } + set { + config.setBool(section: "app", key: "show_confirmation_dialog_zrtp_trust_call", value: newValue) + } + } + + var showFavoriteContacts: Bool { + get { + config.getBool(section: "ui", key: "show_favorites_contacts", defaultValue: true) + } + set { + config.setBool(section: "ui", key: "show_favorites_contacts", value: newValue) + } + } + + var teamID: String { + get { + config.getString(section: "app", key: "team_id", defaultString: "") + } + set { + config.setString(section: "app", key: "team_id", value: newValue) + } + } + + var themeAboutPictureUrl: String? { + get { + config.getString(section: "ui", key: "theme_about_picture_url", defaultString: nil) + } + set { + config.setString(section: "ui", key: "theme_about_picture_url", value: newValue) + } + } + + var themeMainColor: String { + get { + let raw = config.getString(section: "ui", key: "theme_main_color", defaultString: "orange") + return safeString(raw, defaultValue: "orange") + } + set { + config.setString(section: "ui", key: "theme_main_color", value: newValue) + } + } + + var vfsEnabled: Bool { + get { + config.getBool(section: "app", key: "vfs_enabled", defaultValue: false) + } + set { + config.setBool(section: "app", key: "vfs_enabled", value: newValue) + } + } + + var voiceRecordingMaxDuration: Int { + get { + config.getInt(section: "app", key: "voice_recording_max_duration", defaultValue: 600000) + } + set { + config.setInt(section: "app", key: "voice_recording_max_duration", value: newValue) + } + } + private func copy(from: String, to: String, overrideIfExists: Bool = false) { let fileManager = FileManager.default if fileManager.fileExists(atPath: to), !overrideIfExists { diff --git a/Linphone/GeneratedGit.swift b/Linphone/GeneratedGit.swift index b90db8bab..c1867309e 100644 --- a/Linphone/GeneratedGit.swift +++ b/Linphone/GeneratedGit.swift @@ -2,6 +2,6 @@ import Foundation public enum AppGitInfo { public static let branch = "master" - public static let commit = "d25c19ff8" + public static let commit = "907211903" public static let tag = "6.1.0-alpha" } diff --git a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift index e1a957515..a48fea884 100644 --- a/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift +++ b/Linphone/UI/Main/Conversations/ViewModel/ConversationViewModel.swift @@ -3593,7 +3593,7 @@ class AudioRecorder: NSObject, ObservableObject { func startTimer() { DispatchQueue.main.async { self.recordingTime = 0 - let maxVoiceRecordDuration = CoreContext.shared.voiceRecordingMaxDuration + let maxVoiceRecordDuration = AppServices.corePreferences.voiceRecordingMaxDuration self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in // More frequent updates self.recordingTime += 0.1 self.updateSoundPower() diff --git a/Linphone/UI/Main/Help/Fragments/DebugFragment.swift b/Linphone/UI/Main/Help/Fragments/DebugFragment.swift index 0fa2b48eb..21dc2d962 100644 --- a/Linphone/UI/Main/Help/Fragments/DebugFragment.swift +++ b/Linphone/UI/Main/Help/Fragments/DebugFragment.swift @@ -245,7 +245,7 @@ struct DebugFragment: View { func showConfigFile() { Log.info("[DebugFragment][showConfigFile] Dumping & displaying Core's config") - if let rcDir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: CoreContext.appGroupName)? + if let rcDir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: SharedMainViewModel.appGroupName)? .appendingPathComponent("Library/Preferences/linphone") { let rcFileUrl = rcDir.appendingPathComponent("linphonerc") if FileManager.default.fileExists(atPath: rcFileUrl.path) { diff --git a/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift b/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift index 18c625eba..793da071d 100644 --- a/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift +++ b/Linphone/UI/Main/Viewmodel/SharedMainViewModel.swift @@ -24,6 +24,13 @@ class SharedMainViewModel: ObservableObject { static let shared = SharedMainViewModel() + static let appGroupName: String = { + Bundle.main.object(forInfoDictionaryKey: "APP_GROUP_NAME") as? String + ?? { + fatalError("APP_GROUP_NAME not defined in Info.plist") + }() + }() + @Published var welcomeViewDisplayed = false @Published var generalTermsAccepted = false @Published var displayProfileMode = false