mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-09 01:12:05 +00:00
parent
1f5f56c35e
commit
6b2ba28728
@ -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()
|
||||
}
|
@ -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()
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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.";
|
||||
|
@ -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 δεν λειτουργούν χωρίς αγορά.";
|
||||
|
@ -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";
|
||||
|
@ -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.";
|
||||
|
@ -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.";
|
||||
|
@ -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.";
|
||||
|
@ -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.";
|
||||
|
@ -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.";
|
||||
|
@ -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.";
|
||||
|
@ -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" = "Профили для ТВ требуют покупки.";
|
||||
|
@ -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.";
|
||||
|
@ -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 не працюють без покупки.";
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user