mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Merge branch 'master'
This commit is contained in:
commit
2ef76ae47b
9 changed files with 338 additions and 4 deletions
|
|
@ -35,6 +35,8 @@
|
|||
66FBFC492B83BD2400BC6AB1 /* ConfigExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491F82B24D25A00CEA16D /* ConfigExtension.swift */; };
|
||||
66FBFC4A2B83BD3300BC6AB1 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FE2B24D4AC00CEA16D /* FileUtils.swift */; };
|
||||
66FBFC4B2B83BD7B00BC6AB1 /* CoreExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66C491FA2B24D32600CEA16D /* CoreExtension.swift */; };
|
||||
C67586AE2C09F23C002E77BF /* URLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67586AD2C09F23C002E77BF /* URLExtension.swift */; };
|
||||
C67586B02C09F247002E77BF /* URIHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67586AF2C09F247002E77BF /* URIHandler.swift */; };
|
||||
D706BA822ADD72D100278F45 /* DeviceRotationViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */; };
|
||||
D70959F12B8DF3EC0014AC0B /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70959F02B8DF3EC0014AC0B /* ConversationModel.swift */; };
|
||||
D70A26EE2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A26ED2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift */; };
|
||||
|
|
@ -192,6 +194,8 @@
|
|||
66E56BCB2BA9A1E0006CE56F /* MeetingsListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingsListItemModel.swift; sourceTree = "<group>"; };
|
||||
66E56BCD2BA9A1F8006CE56F /* MeetingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingModel.swift; sourceTree = "<group>"; };
|
||||
66F626B12BCEBB86003E2DEC /* AddParticipantsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddParticipantsFragment.swift; sourceTree = "<group>"; };
|
||||
C67586AD2C09F23C002E77BF /* URLExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLExtension.swift; sourceTree = "<group>"; };
|
||||
C67586AF2C09F247002E77BF /* URIHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URIHandler.swift; sourceTree = "<group>"; };
|
||||
D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRotationViewModifier.swift; sourceTree = "<group>"; };
|
||||
D70959F02B8DF3EC0014AC0B /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; };
|
||||
D70A26ED2B7CF60B006CC8FC /* ConversationsListBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationsListBottomSheet.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -343,6 +347,7 @@
|
|||
66C491F72B24D25A00CEA16D /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C67586AD2C09F23C002E77BF /* URLExtension.swift */,
|
||||
D717071D2AC5922E0037746F /* ColorExtension.swift */,
|
||||
66C491F82B24D25A00CEA16D /* ConfigExtension.swift */,
|
||||
D76005F52B0798B00054B79A /* IntExtension.swift */,
|
||||
|
|
@ -426,6 +431,7 @@
|
|||
D732A9082AFD235500DB42BA /* ShareSheetController.swift */,
|
||||
D7B99E9A2B29F7C200BE7BF2 /* ActivityIndicator.swift */,
|
||||
D7173EBD2B7A5C0A00BCC481 /* LinphoneUtils.swift */,
|
||||
C67586AF2C09F247002E77BF /* URIHandler.swift */,
|
||||
);
|
||||
path = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -993,6 +999,7 @@
|
|||
D717630D2BD7BD0E00464097 /* ParticipantsListFragment.swift in Sources */,
|
||||
D732A90F2B04C3B400DB42BA /* HistoryFragment.swift in Sources */,
|
||||
D79622342B1DFE600037EACD /* DialerBottomSheet.swift in Sources */,
|
||||
C67586B02C09F247002E77BF /* URIHandler.swift in Sources */,
|
||||
D78290BB2ADD40B2004AA85C /* ContactViewModel.swift in Sources */,
|
||||
D7F4D9CB2B5FD27200CDCD76 /* CallsListFragment.swift in Sources */,
|
||||
D72992392ADD7F68003AF125 /* HistoryContactFragment.swift in Sources */,
|
||||
|
|
@ -1019,6 +1026,7 @@
|
|||
D78E06302BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.swift in Sources */,
|
||||
66E56BC92BA4A6D7006CE56F /* MeetingsListViewModel.swift in Sources */,
|
||||
D726E4392B16440C0083C415 /* ContactAvatarModel.swift in Sources */,
|
||||
C67586AE2C09F23C002E77BF /* URLExtension.swift in Sources */,
|
||||
6613A0B02BAEB7F4008923A4 /* MeetingsListFragment.swift in Sources */,
|
||||
D76005F62B0798B00054B79A /* IntExtension.swift in Sources */,
|
||||
D78E06282BE3811D00CE3783 /* CallStatsModel.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@ final class CoreContext: ObservableObject {
|
|||
let monitor = NWPathMonitor()
|
||||
|
||||
private var mCorePushIncomingDelegate: CoreDelegate!
|
||||
|
||||
private var actionsToPerformOnCoreQueueWhenCoreIsStarted : [((Core)->Void)] = []
|
||||
private var callStateCallBacks : [((Call.State)->Void)] = []
|
||||
private var configuringStateCallBacks : [((ConfiguringState)->Void)] = []
|
||||
|
||||
private init() {
|
||||
do {
|
||||
try initialiseCore()
|
||||
|
|
@ -141,6 +144,8 @@ final class CoreContext: ObservableObject {
|
|||
account.params = newParams
|
||||
}
|
||||
|
||||
self.actionsToPerformOnCoreQueueWhenCoreIsStarted.forEach {$0(cbVal.core)}
|
||||
self.actionsToPerformOnCoreQueueWhenCoreIsStarted.removeAll()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -292,6 +297,24 @@ final class CoreContext: ObservableObject {
|
|||
func crashForCrashlytics() {
|
||||
fatalError("Crashing app to test crashlytics")
|
||||
}
|
||||
|
||||
func performActionOnCoreQueueWhenCoreIsStarted(action: @escaping (_ core: Core)->Void ) {
|
||||
if (coreIsStarted) {
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
action(core)
|
||||
}
|
||||
} else {
|
||||
actionsToPerformOnCoreQueueWhenCoreIsStarted.append(action)
|
||||
}
|
||||
}
|
||||
|
||||
func addCoreDelegateStub(delegate: CoreDelegateStub) {
|
||||
mCore.addDelegate(delegate: delegate)
|
||||
}
|
||||
func removeCoreDelegateStub(delegate: CoreDelegateStub) {
|
||||
mCore.removeDelegate(delegate: delegate)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// swiftlint:enable large_tuple
|
||||
|
|
|
|||
|
|
@ -2,6 +2,89 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>linphone-config</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>sip</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>sips</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>sip-linphone</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>sips-linphone</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>linphone-sip</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>linphone-sips</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>org.linphone.phone</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>tel</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<true/>
|
||||
<key>ITSEncryptionExportComplianceCode</key>
|
||||
|
|
|
|||
|
|
@ -86,7 +86,12 @@ struct LinphoneApp: App {
|
|||
WindowGroup {
|
||||
if coreContext.coreIsStarted {
|
||||
if !sharedMainViewModel.welcomeViewDisplayed {
|
||||
WelcomeView()
|
||||
ZStack {
|
||||
WelcomeView()
|
||||
|
||||
ToastView()
|
||||
.zIndex(3)
|
||||
}
|
||||
} else if !coreContext.hasDefaultAccount || sharedMainViewModel.displayProfileMode {
|
||||
ZStack {
|
||||
AssistantView()
|
||||
|
|
@ -119,9 +124,13 @@ struct LinphoneApp: App {
|
|||
conversationViewModel: conversationViewModel!,
|
||||
meetingsListViewModel: meetingsListViewModel!,
|
||||
scheduleMeetingViewModel: scheduleMeetingViewModel!
|
||||
)
|
||||
).onOpenURL { url in
|
||||
URIHandler.handleURL(url: url)
|
||||
}
|
||||
} else {
|
||||
SplashScreen()
|
||||
SplashScreen().onOpenURL { url in
|
||||
URIHandler.handleURL(url: url)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SplashScreen()
|
||||
|
|
@ -137,6 +146,8 @@ struct LinphoneApp: App {
|
|||
conversationViewModel = ConversationViewModel()
|
||||
meetingsListViewModel = MeetingsListViewModel()
|
||||
scheduleMeetingViewModel = ScheduleMeetingViewModel()
|
||||
}.onOpenURL { url in
|
||||
URIHandler.handleURL(url: url)
|
||||
}
|
||||
}
|
||||
}.onChange(of: scenePhase) { newPhase in
|
||||
|
|
|
|||
|
|
@ -242,6 +242,9 @@
|
|||
},
|
||||
"Bluetooth" : {
|
||||
|
||||
},
|
||||
"Call failed" : {
|
||||
|
||||
},
|
||||
"Call has been successfully transferred" : {
|
||||
|
||||
|
|
@ -284,6 +287,12 @@
|
|||
},
|
||||
"Conditions de service" : {
|
||||
|
||||
},
|
||||
"Configuration failed" : {
|
||||
|
||||
},
|
||||
"Configuration successfully applied" : {
|
||||
|
||||
},
|
||||
"Connexion à la réunion" : {
|
||||
|
||||
|
|
@ -777,6 +786,12 @@
|
|||
},
|
||||
"UDP" : {
|
||||
|
||||
},
|
||||
"Unable to call, invalid address" : {
|
||||
|
||||
},
|
||||
"Unable to retrieve configuration, invalid address" : {
|
||||
|
||||
},
|
||||
"Une application de communication **sécurisée**, **open source** et **française**." : {
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,42 @@ struct ToastView: View {
|
|||
.foregroundStyle(Color.redDanger500)
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(8)
|
||||
|
||||
case "Failed_uri_handler_call_failed":
|
||||
Text("Call failed")
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundStyle(Color.redDanger500)
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(8)
|
||||
|
||||
case "Failed_uri_handler_config_failed":
|
||||
Text("Configuration failed")
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundStyle(Color.redDanger500)
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(8)
|
||||
|
||||
case "uri_handler_config_success":
|
||||
Text("Configuration successfully applied")
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundStyle(Color.redDanger500)
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(8)
|
||||
|
||||
case "Failed_uri_handler_bad_call_address":
|
||||
Text("Unable to call, invalid address")
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundStyle(Color.redDanger500)
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(8)
|
||||
|
||||
case "Failed_uri_handler_bad_config_address":
|
||||
Text("Unable to retrieve configuration, invalid address")
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundStyle(Color.redDanger500)
|
||||
.default_text_style(styleSize: 15)
|
||||
.padding(8)
|
||||
|
||||
default:
|
||||
Text("Error")
|
||||
.multilineTextAlignment(.center)
|
||||
|
|
|
|||
34
Linphone/Utils/Extensions/URLExtension.swift
Normal file
34
Linphone/Utils/Extensions/URLExtension.swift
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
extension URL {
|
||||
func withNewScheme(_ value: String) -> URL? {
|
||||
let components = NSURLComponents.init(url: self, resolvingAgainstBaseURL: true)
|
||||
components?.scheme = value
|
||||
return components?.url
|
||||
}
|
||||
var resourceSpecifier: String {
|
||||
get {
|
||||
let nrl : NSURL = self as NSURL
|
||||
return nrl.resourceSpecifier ?? self.absoluteString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,4 +59,9 @@ class LinphoneUtils: NSObject {
|
|||
public class func getChatRoomId(localSipUri: String, remoteSipUri: String) -> String {
|
||||
return "\(localSipUri)#~#\(remoteSipUri)"
|
||||
}
|
||||
|
||||
public class func applyInternationalPrefix(core: Core, account: Account? = nil) -> Bool {
|
||||
return account?.params?.useInternationalPrefixForCallsAndChats == true || core.defaultAccount?.params?.useInternationalPrefixForCallsAndChats == true
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
120
Linphone/Utils/URIHandler.swift
Normal file
120
Linphone/Utils/URIHandler.swift
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-iphone
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import linphonesw
|
||||
import Combine
|
||||
|
||||
class URIHandler {
|
||||
|
||||
// Need to cover all Info.plist URL schemes.
|
||||
private static let callSchemes = ["sip", "sip-linphone", "linphone-sip", "tel"]
|
||||
private static let secureCallSchemes = ["sips", "sips-linphone", "linphone-sips"]
|
||||
private static let configurationSchemes = ["linphone-config"]
|
||||
|
||||
private static var uriHandlerCoreDelegate: CoreDelegateStub? = nil
|
||||
|
||||
static func addCoreDelegate() {
|
||||
uriHandlerCoreDelegate = CoreDelegateStub(
|
||||
onCallStateChanged: { (core: Core, call: Call, state: Call.State, message: String) in
|
||||
if state == .Error {
|
||||
toast("Failed_uri_handler_call_failed")
|
||||
CoreContext.shared.removeCoreDelegateStub(delegate: uriHandlerCoreDelegate!)
|
||||
}
|
||||
if state == .End {
|
||||
CoreContext.shared.removeCoreDelegateStub(delegate: uriHandlerCoreDelegate!)
|
||||
}
|
||||
},
|
||||
onConfiguringStatus: { (core:Core, state:ConfiguringState, status: String) in
|
||||
if state == .Failed {
|
||||
toast("Failed_uri_handler_config_failed")
|
||||
CoreContext.shared.removeCoreDelegateStub(delegate: uriHandlerCoreDelegate!)
|
||||
}
|
||||
if state == .Successful {
|
||||
toast("uri_handler_config_success")
|
||||
CoreContext.shared.removeCoreDelegateStub(delegate: uriHandlerCoreDelegate!)
|
||||
}
|
||||
})
|
||||
CoreContext.shared.addCoreDelegateStub(delegate: uriHandlerCoreDelegate!)
|
||||
}
|
||||
|
||||
|
||||
static func handleURL(url: URL) {
|
||||
Log.info("[URIHandler] handleURL: \(url)")
|
||||
if let scheme = url.scheme {
|
||||
if secureCallSchemes.contains(scheme) {
|
||||
initiateCall(url: url, withScheme: "sips")
|
||||
} else if callSchemes.contains(scheme) {
|
||||
initiateCall(url: url, withScheme: "sip")
|
||||
} else if configurationSchemes.contains(scheme) {
|
||||
initiateConfiguration(url: url)
|
||||
} else {
|
||||
Log.error("[URIHandler] unhandled URL \(url) (check Info.plist)")
|
||||
}
|
||||
} else {
|
||||
Log.error("[URIHandler] invalid scheme for URL \(url)")
|
||||
}
|
||||
}
|
||||
|
||||
private static func initiateCall(url: URL, withScheme newScheme: String) {
|
||||
CoreContext.shared.performActionOnCoreQueueWhenCoreIsStarted { core in
|
||||
if let newSchemeUrl = url.withNewScheme(newScheme),
|
||||
let address = core.interpretUrl(url: newSchemeUrl.absoluteString,
|
||||
applyInternationalPrefix: LinphoneUtils.applyInternationalPrefix(core: core)) {
|
||||
Log.info("[URIHandler] initiating call to address : \(address.asString())")
|
||||
addCoreDelegate()
|
||||
TelecomManager.shared.doCallWithCore(addr: address, isVideo: false, isConference: false)
|
||||
} else {
|
||||
Log.error("[URIHandler] unable to call with \(url.resourceSpecifier)")
|
||||
toast("Failed_uri_handler_bad_call_address")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func initiateConfiguration(url: URL) {
|
||||
if autoRemoteProvisioningOnConfigUriHandler() {
|
||||
CoreContext.shared.performActionOnCoreQueueWhenCoreIsStarted { core in
|
||||
Log.info("[URIHandler] provisioning app with URI: \(url.resourceSpecifier)")
|
||||
do {
|
||||
addCoreDelegate()
|
||||
core.config?.setString(section: "misc", key: "config-uri", value: url.resourceSpecifier)
|
||||
try core.setProvisioninguri(newValue: url.resourceSpecifier)
|
||||
core.stop()
|
||||
try core.start()
|
||||
} catch {
|
||||
Log.error("[URIHandler] unable to configure the app with \(url.resourceSpecifier) \(error)")
|
||||
toast("Failed_uri_handler_bad_config_address")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.warn("[URIHandler] received configuration request, but automatic provisioning is disabled.")
|
||||
}
|
||||
}
|
||||
|
||||
private static func autoRemoteProvisioningOnConfigUriHandler() -> Bool {
|
||||
return Config.get().getBool(section: "app", key: "auto_apply_provisioning_config_uri_handler", defaultValue: true)
|
||||
}
|
||||
|
||||
private static func toast(_ message: String) {
|
||||
DispatchQueue.main.async {
|
||||
ToastViewModel.shared.toastMessage = message
|
||||
ToastViewModel.shared.displayToast = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue