Restore "Keep alive on sleep" feature (#1143)

Closes #1112
This commit is contained in:
Davide 2025-02-06 14:57:53 +01:00 committed by GitHub
parent 1f5f56c35e
commit 6b2ba28728
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 144 additions and 8 deletions

View File

@ -0,0 +1,68 @@
//
// ProfileBehaviorSection.swift
// Passepartout
//
// Created by Davide De Rosa on 2/6/25.
// Copyright (c) 2025 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout 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.
//
// Passepartout 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 Passepartout. If not, see <http://www.gnu.org/licenses/>.
//
import SwiftUI
struct ProfileBehaviorSection: View {
@ObservedObject
var profileEditor: ProfileEditor
var body: some View {
debugChanges()
return Group {
keepAliveToggle
.themeRowWithSubtitle(footer)
}
.themeSection(header: header, footer: footer)
}
}
private extension ProfileBehaviorSection {
var keepAliveToggle: some View {
Toggle(
Strings.Modules.General.Rows.keepAliveOnSleep,
isOn: $profileEditor.keepsAliveOnSleep
)
}
}
private extension ProfileBehaviorSection {
var header: String {
Strings.Modules.General.Sections.Behavior.header
}
var footer: String {
Strings.Modules.General.Rows.KeepAliveOnSleep.footer
}
}
#Preview {
Form {
ProfileBehaviorSection(profileEditor: ProfileEditor())
}
.themeForm()
.withMockEnvironment()
}

View File

@ -1,5 +1,5 @@
//
// StorageSection.swift
// ProfileStorageSection.swift
// Passepartout
//
// Created by Davide De Rosa on 9/4/24.
@ -26,7 +26,7 @@
import CommonLibrary
import SwiftUI
struct StorageSection: View {
struct ProfileStorageSection: View {
@EnvironmentObject
private var iapManager: IAPManager
@ -46,7 +46,7 @@ struct StorageSection: View {
}
}
private extension StorageSection {
private extension ProfileStorageSection {
var sharingToggle: some View {
Toggle(isOn: $profileEditor.isShared) {
HStack {
@ -67,7 +67,7 @@ private extension StorageSection {
}
}
private extension StorageSection {
private extension ProfileStorageSection {
var header: String {
Strings.Modules.General.Sections.Storage.header(Strings.Unlocalized.iCloud)
}
@ -100,7 +100,7 @@ private extension StorageSection {
#Preview {
Form {
StorageSection(profileEditor: ProfileEditor())
ProfileStorageSection(profileEditor: ProfileEditor())
}
.themeForm()
.withMockEnvironment()

View File

@ -54,7 +54,8 @@ struct ProfileEditView: View, Routable {
name: $profileEditor.profile.name
)
modulesSection
StorageSection(profileEditor: profileEditor)
ProfileStorageSection(profileEditor: profileEditor)
ProfileBehaviorSection(profileEditor: profileEditor)
UUIDSection(uuid: profileEditor.profile.id)
}
.toolbar(content: toolbarContent)

View File

@ -36,7 +36,8 @@ struct ProfileGeneralView: View {
var body: some View {
Form {
ProfileNameSection(name: $profileEditor.profile.name)
StorageSection(profileEditor: profileEditor)
ProfileStorageSection(profileEditor: profileEditor)
ProfileBehaviorSection(profileEditor: profileEditor)
UUIDSection(uuid: profileEditor.profile.id)
}
.themeForm()

View File

@ -35,6 +35,8 @@ public struct EditableProfile: MutableProfileType {
public var activeModulesIds: Set<UUID>
public var behavior: ProfileBehavior?
public var userInfo: AnyHashable?
public init(
@ -42,12 +44,14 @@ public struct EditableProfile: MutableProfileType {
name: String = "",
modules: [any ModuleBuilder] = [],
activeModulesIds: Set<UUID> = [],
behavior: ProfileBehavior? = nil,
userInfo: AnyHashable? = nil
) {
self.id = id
self.name = name
self.modules = modules
self.activeModulesIds = activeModulesIds
self.behavior = behavior
self.userInfo = userInfo
}
@ -67,6 +71,7 @@ public struct EditableProfile: MutableProfileType {
throw AppError.emptyProfileName
}
builder.name = trimmedName
builder.behavior = behavior
builder.userInfo = userInfo
return builder
@ -80,6 +85,7 @@ extension Profile {
name: name,
modules: modulesBuilders(),
activeModulesIds: activeModulesIds,
behavior: behavior,
userInfo: userInfo
)
}

View File

@ -98,6 +98,17 @@ extension ProfileEditor {
}
}
public var keepsAliveOnSleep: Bool {
get {
!editableProfile.disconnectsOnSleep
}
set {
var behavior = editableProfile.behavior ?? ProfileBehavior()
behavior.disconnectsOnSleep = !newValue
editableProfile.behavior = behavior
}
}
public var isAvailableForTV: Bool {
get {
editableProfile.attributes.isAvailableForTV == true

View File

@ -375,18 +375,28 @@ public enum Strings {
}
/// Import from file
public static let importFromFile = Strings.tr("Localizable", "modules.general.rows.import_from_file", fallback: "Import from file")
/// Keep alive on sleep
public static let keepAliveOnSleep = Strings.tr("Localizable", "modules.general.rows.keep_alive_on_sleep", fallback: "Keep alive on sleep")
/// Enabled
public static let shared = Strings.tr("Localizable", "modules.general.rows.shared", fallback: "Enabled")
public enum Appletv {
/// Drop TV restriction
public static let purchase = Strings.tr("Localizable", "modules.general.rows.appletv.purchase", fallback: "Drop TV restriction")
}
public enum KeepAliveOnSleep {
/// Disable to improve battery usage, at the expense of occasional slowdowns due to wake-up reconnections.
public static let footer = Strings.tr("Localizable", "modules.general.rows.keep_alive_on_sleep.footer", fallback: "Disable to improve battery usage, at the expense of occasional slowdowns due to wake-up reconnections.")
}
public enum Shared {
/// Share on iCloud
public static let purchase = Strings.tr("Localizable", "modules.general.rows.shared.purchase", fallback: "Share on iCloud")
}
}
public enum Sections {
public enum Behavior {
/// Behavior
public static let header = Strings.tr("Localizable", "modules.general.sections.behavior.header", fallback: "Behavior")
}
public enum Storage {
/// Profiles are stored to %@ encrypted.
public static func footer(_ p1: Any) -> String {

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "TV-Einschränkung entfernen";
"modules.general.rows.import_from_file" = "Aus Datei importieren";
"modules.general.rows.keep_alive_on_sleep" = "Verbindung aktiv halten trotz Schlafmodus";
"modules.general.rows.keep_alive_on_sleep.footer" = "Deaktivieren um die Batterielaufzeit zu verbessern, allerdings verzögert sich der Verbindungsaufbau beim Aufwachen.";
"modules.general.rows.shared" = "Aktiviert";
"modules.general.rows.shared.purchase" = "Auf iCloud teilen";
"modules.general.sections.behavior.header" = "Verhalten";
"modules.general.sections.storage.footer" = "Profile werden in %@ verschlüsselt gespeichert.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "TV-Profile funktionieren nicht in Beta-Versionen.";
"modules.general.sections.storage.footer.purchase.tv_release" = "TV-Profile funktionieren ohne einen Kauf nicht.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Κατάργηση περιορισμού TV";
"modules.general.rows.import_from_file" = "Εισαγωγή από αρχείο";
"modules.general.rows.keep_alive_on_sleep" = "Κρατήστε ζωντανό στον ύπνο";
"modules.general.rows.keep_alive_on_sleep.footer" = "Απενεργοποιήστε για να βελτιώσετε τη χρήση της μπαταρίας, εις βάρος των περιστασιακών επιβραδύνσεων που οφείλονται σε επανασύνδεση αφύπνισης.";
"modules.general.rows.shared" = "Ενεργοποιημένο";
"modules.general.rows.shared.purchase" = "Κοινοποίηση στο iCloud";
"modules.general.sections.behavior.header" = "Συμπεριφορά";
"modules.general.sections.storage.footer" = "Τα προφίλ αποθηκεύονται κρυπτογραφημένα στο %@.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Τα προφίλ TV δεν λειτουργούν στις εκδόσεις beta.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Τα προφίλ TV δεν λειτουργούν χωρίς αγορά.";

View File

@ -142,11 +142,14 @@
"modules.general.sections.storage.footer" = "Profiles are stored to %@ encrypted.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "TV profiles do not work in beta builds.";
"modules.general.sections.storage.footer.purchase.tv_release" = "TV profiles do not work without a purchase.";
"modules.general.sections.behavior.header" = "Behavior";
"modules.general.rows.shared" = "Enabled";
"modules.general.rows.shared.purchase" = "Share on iCloud";
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Drop TV restriction";
"modules.general.rows.import_from_file" = "Import from file";
"modules.general.rows.keep_alive_on_sleep" = "Keep alive on sleep";
"modules.general.rows.keep_alive_on_sleep.footer" = "Disable to improve battery usage, at the expense of occasional slowdowns due to wake-up reconnections.";
"modules.dns.servers.add" = "Add address";
"modules.dns.search_domains.add" = "Add domain";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Eliminar restricción de TV";
"modules.general.rows.import_from_file" = "Importar desde archivo";
"modules.general.rows.keep_alive_on_sleep" = "Mantener en modo inactivo";
"modules.general.rows.keep_alive_on_sleep.footer" = "Deshabilitar para mejorar el uso de la batería, a costa de ralentizaciones ocasionales por las reconexiones al despertar el dispositivo.";
"modules.general.rows.shared" = "Habilitado";
"modules.general.rows.shared.purchase" = "Compartir en iCloud";
"modules.general.sections.behavior.header" = "Comportamiento";
"modules.general.sections.storage.footer" = "Los perfiles se almacenan en %@ de manera cifrada.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Los perfiles de TV no funcionan en las versiones beta.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Los perfiles de TV no funcionan sin una compra.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Retirer la restriction TV";
"modules.general.rows.import_from_file" = "Importer depuis un fichier";
"modules.general.rows.keep_alive_on_sleep" = "Garder actif lors de la veille";
"modules.general.rows.keep_alive_on_sleep.footer" = "Désactiver pour augmenter l'autonomie de la batterie, au dépends de la rapidité au réveil pour la reconnection.";
"modules.general.rows.shared" = "Activé";
"modules.general.rows.shared.purchase" = "Partager sur iCloud";
"modules.general.sections.behavior.header" = "Comportement";
"modules.general.sections.storage.footer" = "Les profils sont stockés dans %@ de manière cryptée.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Les profils TV ne fonctionnent pas dans les versions bêta.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Les profils TV ne fonctionnent pas sans un achat.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Rimuovi restrizione TV";
"modules.general.rows.import_from_file" = "Importa da file";
"modules.general.rows.keep_alive_on_sleep" = "Mantieni attivo in sleep";
"modules.general.rows.keep_alive_on_sleep.footer" = "Disabilita per migliorare il consumo della batteria, a discapito di rallentamenti occasionali causati dalle riconnessioni.";
"modules.general.rows.shared" = "Abilitato";
"modules.general.rows.shared.purchase" = "Condividi su iCloud";
"modules.general.sections.behavior.header" = "Comportamento";
"modules.general.sections.storage.footer" = "I profili sono archiviati su %@ in modo crittografato.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "I profili TV non funzionano nelle versioni beta.";
"modules.general.sections.storage.footer.purchase.tv_release" = "I profili TV non funzionano senza un acquisto.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "TV-beperking verwijderen";
"modules.general.rows.import_from_file" = "Importeren uit bestand";
"modules.general.rows.keep_alive_on_sleep" = "Actief tijdens slaapstand";
"modules.general.rows.keep_alive_on_sleep.footer" = "Uitschakelen om het batterijverbruik te verbeteren, ten koste van incidentele vertragingen als gevolg van het opnieuw opstarten na wake-up.";
"modules.general.rows.shared" = "Ingeschakeld";
"modules.general.rows.shared.purchase" = "Delen op iCloud";
"modules.general.sections.behavior.header" = "Gedrag";
"modules.general.sections.storage.footer" = "Profielen worden versleuteld opgeslagen in %@.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "TV-profielen werken niet in bètaversies.";
"modules.general.sections.storage.footer.purchase.tv_release" = "TV-profielen werken niet zonder aankoop.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Usuń ograniczenie TV";
"modules.general.rows.import_from_file" = "Importuj z pliku";
"modules.general.rows.keep_alive_on_sleep" = "Utrzymuj połączenie przy zablokowanym ekranie";
"modules.general.rows.keep_alive_on_sleep.footer" = "Wyłącz dla mniejszego zużycia baterii kosztem wolniejszego działania spowodowanego ponownym połączeniem przy wybudzeniu urządzenia.";
"modules.general.rows.shared" = "Włączone";
"modules.general.rows.shared.purchase" = "Udostępnij w iCloud";
"modules.general.sections.behavior.header" = "Zachowanie";
"modules.general.sections.storage.footer" = "Profile są przechowywane w %@ i szyfrowane.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Profile TV nie działają w wersjach beta.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Profile TV nie działają bez zakupu.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Remover restrição de TV";
"modules.general.rows.import_from_file" = "Importar de arquivo";
"modules.general.rows.keep_alive_on_sleep" = "Manter ativo em modo descanço";
"modules.general.rows.keep_alive_on_sleep.footer" = "Desative para melhorar o consumo de bateria, o que poderá ocasionar queda de performance quando o restabelecimento de conexão for realizado.";
"modules.general.rows.shared" = "Ativado";
"modules.general.rows.shared.purchase" = "Compartilhar no iCloud";
"modules.general.sections.behavior.header" = "Comportamento";
"modules.general.sections.storage.footer" = "Os perfis são armazenados no %@ de forma criptografada.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Perfis de TV não funcionam em versões beta.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Perfis de TV não funcionam sem uma compra.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Убрать ограничение для ТВ";
"modules.general.rows.import_from_file" = "Импортировать из файла";
"modules.general.rows.keep_alive_on_sleep" = "Оставлять включенным во время сна";
"modules.general.rows.keep_alive_on_sleep.footer" = "Отключите для уменьшения расхода заряда аккумулятора, может привести к временным замедлениям в связи с повторным подключением после \"пробуждения\".";
"modules.general.rows.shared" = "Включено";
"modules.general.rows.shared.purchase" = "Делиться через iCloud";
"modules.general.sections.behavior.header" = "Поведение";
"modules.general.sections.storage.footer" = "Профили хранятся в %@ и зашифрованы.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Профили для ТВ недоступны в бета-версиях.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Профили для ТВ требуют покупки.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Ta bort TV-begränsning";
"modules.general.rows.import_from_file" = "Importera från fil";
"modules.general.rows.keep_alive_on_sleep" = "Håll dig levande i sömnen";
"modules.general.rows.keep_alive_on_sleep.footer" = "Inaktivera för att förbättra batterianvändningen, på bekostnad av tillfälliga avmattningar på grund av återuppkoppling.";
"modules.general.rows.shared" = "Aktiverad";
"modules.general.rows.shared.purchase" = "Dela på iCloud";
"modules.general.sections.behavior.header" = "Beteende";
"modules.general.sections.storage.footer" = "Profiler sparas i %@ och är krypterade.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "TV-profiler fungerar inte i beta-versioner.";
"modules.general.sections.storage.footer.purchase.tv_release" = "TV-profiler fungerar inte utan ett köp.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "Зняти обмеження TV";
"modules.general.rows.import_from_file" = "Імпортувати з файлу";
"modules.general.rows.keep_alive_on_sleep" = "Залишати включеним під час сну";
"modules.general.rows.keep_alive_on_sleep.footer" = "Вимкніть, щоб покращити використання акумулятора, може привести до тимчасових затримок у зв’язку з повторним підключенням після \"пробудження\".";
"modules.general.rows.shared" = "Увімкнено";
"modules.general.rows.shared.purchase" = "Поділитися через iCloud";
"modules.general.sections.behavior.header" = "Поведінка";
"modules.general.sections.storage.footer" = "Профілі зберігаються в %@ у зашифрованому вигляді.";
"modules.general.sections.storage.footer.purchase.tv_beta" = "Профілі TV не працюють у бета-версіях.";
"modules.general.sections.storage.footer.purchase.tv_release" = "Профілі TV не працюють без покупки.";

View File

@ -142,8 +142,11 @@
"modules.general.rows.appletv" = "%@";
"modules.general.rows.appletv.purchase" = "取消 TV 限制";
"modules.general.rows.import_from_file" = "从文件导入";
"modules.general.rows.keep_alive_on_sleep" = "休眠时保持连接";
"modules.general.rows.keep_alive_on_sleep.footer" = "禁用以减少电池消耗,由于存在可能的唤醒时重连消耗。";
"modules.general.rows.shared" = "已启用";
"modules.general.rows.shared.purchase" = "通过 iCloud 共享";
"modules.general.sections.behavior.header" = "行为";
"modules.general.sections.storage.footer" = "配置文件加密存储于 %@。";
"modules.general.sections.storage.footer.purchase.tv_beta" = "TV 配置文件在测试版本中不可用。";
"modules.general.sections.storage.footer.purchase.tv_release" = "TV 配置文件需要购买才能使用。";

@ -1 +1 @@
Subproject commit 10da14db697d8c22d91f1d430ce94c31b6f93c7d
Subproject commit cb22bb2a7207836268c61792b943b34c6ec2990b