mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-15 12:22:06 +00:00
Prevent save profile without active modules (#1164)
A further improvement over #1163 with the same purpose. That is: if a profile won't connect, don't let the user create/save it in the first place.
This commit is contained in:
parent
c189668f3b
commit
cc8a500dab
@ -71,6 +71,9 @@ private extension AppUIMain {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
if (error as? PassepartoutError)?.code == .incompleteModule {
|
||||
return
|
||||
}
|
||||
fatalError("\(moduleType): empty module is not buildable: \(error)")
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ private extension ProfileCoordinator {
|
||||
|
||||
do {
|
||||
try iapManager.verify(profileToSave, extra: profileEditor.extraFeatures)
|
||||
} catch AppError.ineligibleProfile(var requiredFeatures) {
|
||||
} catch AppError.ineligibleProfile(let requiredFeatures) {
|
||||
guard !iapManager.isLoadingReceipt else {
|
||||
let V = Strings.Views.Paywall.Alerts.Verification.self
|
||||
errorHandler.handle(
|
||||
|
@ -108,7 +108,7 @@ private extension ProfileEditView {
|
||||
.onMove(perform: moveModules)
|
||||
.onDelete(perform: removeModules)
|
||||
|
||||
addModuleButton
|
||||
addModuleMenu
|
||||
}
|
||||
.themeSection(
|
||||
header: Strings.Global.Nouns.modules,
|
||||
@ -137,7 +137,7 @@ private extension ProfileEditView {
|
||||
}
|
||||
}
|
||||
|
||||
var addModuleButton: some View {
|
||||
var addModuleMenu: some View {
|
||||
AddModuleMenu(moduleTypes: profileEditor.availableModuleTypes) {
|
||||
flow?.onNewModule($0)
|
||||
} label: {
|
||||
|
@ -191,6 +191,12 @@ private extension ProfileEditor {
|
||||
|
||||
extension ProfileEditor {
|
||||
public func build() throws -> Profile {
|
||||
|
||||
// add this check in the app, the library does not enforce it
|
||||
guard !editableProfile.activeModulesIds.isEmpty else {
|
||||
throw PassepartoutError(.noActiveModules)
|
||||
}
|
||||
|
||||
let builder = try editableProfile.builder()
|
||||
let profile = try builder.tryBuild()
|
||||
|
||||
|
@ -69,15 +69,22 @@ extension TaskTimeoutError: PassepartoutErrorMappable {
|
||||
|
||||
extension PassepartoutError: @retroactive LocalizedError {
|
||||
public var errorDescription: String? {
|
||||
let V = Strings.Errors.App.Passepartout.self
|
||||
switch code {
|
||||
case .connectionModuleRequired:
|
||||
return Strings.Errors.App.Passepartout.connectionModuleRequired
|
||||
return V.connectionModuleRequired
|
||||
|
||||
case .corruptProviderModule:
|
||||
return Strings.Errors.App.Passepartout.corruptProviderModule(reason?.localizedDescription ?? "")
|
||||
return V.corruptProviderModule(reason?.localizedDescription ?? "")
|
||||
|
||||
case .incompatibleModules:
|
||||
return Strings.Errors.App.Passepartout.incompatibleModules
|
||||
return V.incompatibleModules
|
||||
|
||||
case .incompleteModule:
|
||||
guard let builder = userInfo as? any ModuleBuilder else {
|
||||
break
|
||||
}
|
||||
return V.incompleteModule(builder.moduleType.localizedDescription)
|
||||
|
||||
case .invalidFields:
|
||||
let fields = (userInfo as? [String: String?])
|
||||
@ -88,35 +95,36 @@ extension PassepartoutError: @retroactive LocalizedError {
|
||||
.joined(separator: ",")
|
||||
}
|
||||
|
||||
return [Strings.Errors.App.Passepartout.invalidFields, fields]
|
||||
return [V.invalidFields, fields]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: " ")
|
||||
|
||||
case .missingProviderEntity:
|
||||
return Strings.Errors.App.Passepartout.missingProviderEntity
|
||||
return V.missingProviderEntity
|
||||
|
||||
case .noActiveModules:
|
||||
return Strings.Errors.App.Passepartout.noActiveModules
|
||||
return V.noActiveModules
|
||||
|
||||
case .parsing:
|
||||
let message = userInfo as? String ?? (reason as? LocalizedError)?.localizedDescription
|
||||
|
||||
return [Strings.Errors.App.Passepartout.parsing, message]
|
||||
return [V.parsing, message]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: " ")
|
||||
|
||||
case .providerRequired:
|
||||
return Strings.Errors.App.Passepartout.providerRequired
|
||||
return V.providerRequired
|
||||
|
||||
case .timeout:
|
||||
return Strings.Errors.App.Passepartout.timeout
|
||||
return V.timeout
|
||||
|
||||
case .unhandled:
|
||||
return reason?.localizedDescription
|
||||
|
||||
default:
|
||||
return Strings.Errors.App.Passepartout.default(code.rawValue)
|
||||
break
|
||||
}
|
||||
return V.default(code.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,10 @@ public enum Strings {
|
||||
}
|
||||
/// Some active modules are incompatible, try to only activate one of them.
|
||||
public static let incompatibleModules = Strings.tr("Localizable", "errors.app.passepartout.incompatible_modules", fallback: "Some active modules are incompatible, try to only activate one of them.")
|
||||
/// Please finish the configuration of the %@ module.
|
||||
public static func incompleteModule(_ p1: Any) -> String {
|
||||
return Strings.tr("Localizable", "errors.app.passepartout.incomplete_module", String(describing: p1), fallback: "Please finish the configuration of the %@ module.")
|
||||
}
|
||||
/// Invalid fields.
|
||||
public static let invalidFields = Strings.tr("Localizable", "errors.app.passepartout.invalid_fields", fallback: "Invalid fields.")
|
||||
/// No server selected in provider.
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Verbindung zum Anbieter-Server konnte nicht hergestellt werden (Grund=%@).";
|
||||
"errors.app.passepartout.default" = "Operation konnte nicht abgeschlossen werden (Code=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Einige aktive Module sind inkompatibel, versuche, nur eines von ihnen zu aktivieren.";
|
||||
"errors.app.passepartout.incomplete_module" = "Bitte schließen Sie die Konfiguration des %@-Moduls ab.";
|
||||
"errors.app.passepartout.invalid_fields" = "Ungültige Felder.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Kein Server beim Anbieter ausgewählt.";
|
||||
"errors.app.passepartout.no_active_modules" = "Das Profil hat keine aktiven Module.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Δεν ήταν δυνατή η σύνδεση στον διακομιστή παρόχου (λόγος=%@).";
|
||||
"errors.app.passepartout.default" = "Δεν ήταν δυνατή η ολοκλήρωση της λειτουργίας (κωδικός=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Μερικές ενεργές μονάδες είναι ασύμβατες, δοκιμάστε να ενεργοποιήσετε μόνο μία.";
|
||||
"errors.app.passepartout.incomplete_module" = "Ολοκληρώστε τη ρύθμιση του %@ module.";
|
||||
"errors.app.passepartout.invalid_fields" = "Μη έγκυρα πεδία.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Δεν επιλέχθηκε διακομιστής στον πάροχο.";
|
||||
"errors.app.passepartout.no_active_modules" = "Το προφίλ δεν έχει ενεργές μονάδες.";
|
||||
|
@ -372,6 +372,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Unable to connect to provider server (reason=%@).";
|
||||
"errors.app.passepartout.default" = "Unable to complete operation (code=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Some active modules are incompatible, try to only activate one of them.";
|
||||
"errors.app.passepartout.incomplete_module" = "Please finish the configuration of the %@ module.";
|
||||
"errors.app.passepartout.invalid_fields" = "Invalid fields.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "No server selected in provider.";
|
||||
"errors.app.passepartout.no_active_modules" = "The profile has no active modules.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "No se pudo conectar al servidor del proveedor (motivo=%@).";
|
||||
"errors.app.passepartout.default" = "No se pudo completar la operación (código=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Algunos módulos activos son incompatibles, intenta activar solo uno de ellos.";
|
||||
"errors.app.passepartout.incomplete_module" = "Por favor, completa la configuración del módulo %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Campos no válidos.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "No se seleccionó un servidor en el proveedor.";
|
||||
"errors.app.passepartout.no_active_modules" = "El perfil no tiene módulos activos.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Impossible de se connecter au serveur du fournisseur (raison=%@).";
|
||||
"errors.app.passepartout.default" = "Impossible de terminer l'opération (code=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Certains modules actifs sont incompatibles, essayez d'en activer un seul.";
|
||||
"errors.app.passepartout.incomplete_module" = "Veuillez terminer la configuration du module %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Champs invalides.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Aucun serveur sélectionné chez le fournisseur.";
|
||||
"errors.app.passepartout.no_active_modules" = "Le profil n'a pas de modules actifs.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Impossibile connettersi al server del provider (motivo=%@).";
|
||||
"errors.app.passepartout.default" = "Impossibile completare l'operazione (codice=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Alcuni moduli attivi sono incompatibili, prova ad attivare solo uno di essi.";
|
||||
"errors.app.passepartout.incomplete_module" = "Completa la configurazione del modulo %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Campi non validi.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Nessun server selezionato nel provider.";
|
||||
"errors.app.passepartout.no_active_modules" = "Il profilo non ha moduli attivi.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Kan geen verbinding maken met de provider-server (reden=%@).";
|
||||
"errors.app.passepartout.default" = "Kan bewerking niet voltooien (code=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Sommige actieve modules zijn incompatibel. Probeer er slechts één te activeren.";
|
||||
"errors.app.passepartout.incomplete_module" = "Voltooi de configuratie van de %@-module.";
|
||||
"errors.app.passepartout.invalid_fields" = "Ongeldige velden.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Geen server geselecteerd bij provider.";
|
||||
"errors.app.passepartout.no_active_modules" = "Het profiel heeft geen actieve modules.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Nie można połączyć się z serwerem dostawcy (powód=%@).";
|
||||
"errors.app.passepartout.default" = "Nie można ukończyć operacji (kod=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Niektóre aktywne moduły są niekompatybilne. Spróbuj aktywować tylko jeden.";
|
||||
"errors.app.passepartout.incomplete_module" = "Proszę dokończyć konfigurację modułu %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Nieprawidłowe pola.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Nie wybrano serwera w dostawcy.";
|
||||
"errors.app.passepartout.no_active_modules" = "Profil nie ma aktywnych modułów.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Não foi possível conectar ao servidor do provedor (motivo=%@).";
|
||||
"errors.app.passepartout.default" = "Não foi possível concluir a operação (código=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Alguns módulos ativos são incompatíveis, tente ativar apenas um.";
|
||||
"errors.app.passepartout.incomplete_module" = "Conclua a configuração do módulo %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Campos inválidos.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Nenhum servidor selecionado no provedor.";
|
||||
"errors.app.passepartout.no_active_modules" = "O perfil não possui módulos ativos.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Не удалось подключиться к серверу поставщика (причина=%@).";
|
||||
"errors.app.passepartout.default" = "Не удалось выполнить операцию (код=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Некоторые активные модули несовместимы, попробуйте активировать только один.";
|
||||
"errors.app.passepartout.incomplete_module" = "Пожалуйста, завершите настройку модуля %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Некорректные поля.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "На провайдере не выбран сервер.";
|
||||
"errors.app.passepartout.no_active_modules" = "В профиле нет активных модулей.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Kan inte ansluta till leverantörsservern (anledning=%@).";
|
||||
"errors.app.passepartout.default" = "Kan inte slutföra åtgärden (kod=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Vissa aktiva moduler är inkompatibla, försök att endast aktivera en.";
|
||||
"errors.app.passepartout.incomplete_module" = "Vänligen slutför konfigurationen av %@-modulen.";
|
||||
"errors.app.passepartout.invalid_fields" = "Ogiltiga fält.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Ingen server vald hos leverantören.";
|
||||
"errors.app.passepartout.no_active_modules" = "Profilen har inga aktiva moduler.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "Не вдалося підключитися до сервера постачальника (причина=%@).";
|
||||
"errors.app.passepartout.default" = "Не вдалося виконати операцію (код=%@).";
|
||||
"errors.app.passepartout.incompatible_modules" = "Деякі активні модулі несумісні, спробуйте активувати лише один.";
|
||||
"errors.app.passepartout.incomplete_module" = "Будь ласка, завершіть налаштування модуля %@.";
|
||||
"errors.app.passepartout.invalid_fields" = "Некоректні поля.";
|
||||
"errors.app.passepartout.missing_provider_entity" = "Не вибрано сервер у постачальника.";
|
||||
"errors.app.passepartout.no_active_modules" = "Профіль не має активних модулів.";
|
||||
|
@ -31,6 +31,7 @@
|
||||
"errors.app.passepartout.corrupt_provider_module" = "无法连接到提供商服务器(原因=%@)。";
|
||||
"errors.app.passepartout.default" = "无法完成操作(代码=%@)。";
|
||||
"errors.app.passepartout.incompatible_modules" = "某些激活的模块不兼容,请尝试仅激活一个模块。";
|
||||
"errors.app.passepartout.incomplete_module" = "请完成 %@ 模块的配置。";
|
||||
"errors.app.passepartout.invalid_fields" = "字段无效。";
|
||||
"errors.app.passepartout.missing_provider_entity" = "未在提供商中选择服务器。";
|
||||
"errors.app.passepartout.no_active_modules" = "配置文件没有激活模块。";
|
||||
|
@ -72,6 +72,9 @@ private extension UILibrary {
|
||||
fatalError("\(moduleType): #2 is not AppFeatureRequiring")
|
||||
}
|
||||
} catch {
|
||||
if (error as? PassepartoutError)?.code == .incompleteModule {
|
||||
return
|
||||
}
|
||||
fatalError("\(moduleType): empty module is not buildable: \(error)")
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c3101f02e620d4ff986a8b846c0ea35fd62d63ec
|
||||
Subproject commit 191369cb4a9a34acac747f2fffd19ea470f8f79e
|
Loading…
Reference in New Issue
Block a user