passepartout-apple/Passepartout/App/Views/OnDemandView.swift

159 lines
4.8 KiB
Swift
Raw Normal View History

2022-04-12 13:09:14 +00:00
//
// OnDemandView.swift
// Passepartout
//
// Created by Davide De Rosa on 2/23/22.
2023-03-17 15:56:19 +00:00
// Copyright (c) 2023 Davide De Rosa. All rights reserved.
2022-04-12 13:09:14 +00:00
//
// 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/>.
//
2022-06-23 21:31:01 +00:00
import PassepartoutLibrary
import SwiftUI
2022-04-12 13:09:14 +00:00
struct OnDemandView: View {
@ObservedObject private var productManager: ProductManager
@ObservedObject private var currentProfile: ObservableProfile
@State private var onDemand = Profile.OnDemand()
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
init(currentProfile: ObservableProfile) {
productManager = .shared
self.currentProfile = currentProfile
}
var body: some View {
debugChanges()
return List {
enabledView
if onDemand.isEnabled && onDemand.policy != .any {
2022-04-12 13:09:14 +00:00
mainView
}
2022-04-12 13:09:14 +00:00
}.navigationTitle(L10n.OnDemand.title)
.toolbar {
CopySavingButton(
original: $currentProfile.value.onDemand,
copy: $onDemand,
mapping: \.stripped,
label: themeSaveButtonLabel
)
}
// Siri
.onChange(of: onDemand.withMobileNetwork, perform: donateMobileIntent)
.onChange(of: onDemand.withSSIDs, perform: donateNetworkIntents)
}
}
// MARK: -
private extension OnDemandView {
var enabledView: some View {
2022-04-12 13:09:14 +00:00
Section {
2022-04-23 10:08:24 +00:00
Toggle(L10n.Global.Strings.enabled, isOn: $onDemand.isEnabled.themeAnimation())
if onDemand.isEnabled {
themeTextPicker(
// FIXME: l10n, on-demand
L10n.Global.Strings.policy,
selection: $onDemand.policy,
values: [.any, .including, .excluding],
description: \.localizedDescription
)
}
} footer: {
Text(policyFooterDescription ?? "")
2022-04-12 13:09:14 +00:00
}
}
2023-03-17 20:55:47 +00:00
// FIXME: l10n, on-demand
var policyFooterDescription: String {
guard onDemand.isEnabled else {
return "" // better animation than removing footer completely
}
let suffix: String
switch onDemand.policy {
case .any:
suffix = L10n.OnDemand.Sections.Policy.Footer.any
case .including, .excluding:
let arg: String
if onDemand.policy == .including {
arg = L10n.OnDemand.Sections.Policy.Footer.including
} else {
arg = L10n.OnDemand.Sections.Policy.Footer.excluding
}
suffix = L10n.OnDemand.Sections.Policy.Footer.matching(arg)
}
return L10n.OnDemand.Sections.Policy.footer(suffix)
}
2022-04-12 13:09:14 +00:00
@ViewBuilder
var mainView: some View {
2022-04-12 13:09:14 +00:00
if Utils.hasCellularData() {
Section {
2022-04-12 13:09:14 +00:00
Toggle(L10n.OnDemand.Items.Mobile.caption, isOn: $onDemand.withMobileNetwork)
} header: {
// FIXME: l10n, on-demand
Text(L10n.Global.Strings.networks)
2022-05-15 22:45:26 +00:00
}
} else if Utils.hasEthernet() {
Section {
Toggle(L10n.OnDemand.Items.Ethernet.caption, isOn: $onDemand.withEthernetNetwork)
} header: {
// FIXME: l10n, on-demand
Text(L10n.Global.Strings.networks)
2022-04-12 13:09:14 +00:00
}
}
Section {
SSIDList(withSSIDs: $onDemand.withSSIDs)
} header: {
if !Utils.hasCellularData() && !Utils.hasEthernet() {
Text(L10n.Global.Strings.networks)
}
2022-04-12 13:09:14 +00:00
}
}
var isEligibleForSiri: Bool {
productManager.isEligible(forFeature: .siriShortcuts)
}
}
// MARK: -
private extension OnDemandView {
2022-04-12 13:09:14 +00:00
// eligibility: donate intents if eligible for Siri
func donateMobileIntent(_ isEnabled: Bool) {
2022-04-12 13:09:14 +00:00
guard isEligibleForSiri else {
return
}
IntentDispatcher.donateTrustCellularNetwork()
IntentDispatcher.donateUntrustCellularNetwork()
}
2023-03-17 20:55:47 +00:00
2022-04-12 13:09:14 +00:00
// eligibility: donate intents if eligible for Siri
func donateNetworkIntents(_: [String: Bool]) {
2022-04-12 13:09:14 +00:00
guard isEligibleForSiri else {
return
}
IntentDispatcher.donateTrustCurrentNetwork()
IntentDispatcher.donateUntrustCurrentNetwork()
}
}