Minor UI fixes (#910)

Update library with some more meaningful names for Profile accessors.

Refactor a few things about TV here and there.
This commit is contained in:
Davide 2024-11-22 10:05:46 +01:00 committed by GitHub
parent 366dc62231
commit 9b366dcaa0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 97 additions and 58 deletions

View File

@ -41,7 +41,7 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "git@github.com:passepartoutvpn/passepartoutkit-source", "location" : "git@github.com:passepartoutvpn/passepartoutkit-source",
"state" : { "state" : {
"revision" : "db4c0f0c01c237a7b50aa0f5c4acb33316c799f0" "revision" : "0d7f912460ca5365740d7196fe5db5a38e23d3e1"
} }
}, },
{ {

View File

@ -48,7 +48,7 @@ let package = Package(
], ],
dependencies: [ dependencies: [
// .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", from: "0.11.0"), // .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", from: "0.11.0"),
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", revision: "db4c0f0c01c237a7b50aa0f5c4acb33316c799f0"), .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", revision: "0d7f912460ca5365740d7196fe5db5a38e23d3e1"),
// .package(path: "../../../passepartoutkit-source"), // .package(path: "../../../passepartoutkit-source"),
.package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", from: "0.9.1"), .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", from: "0.9.1"),
// .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", revision: "031863a1cd683962a7dfe68e20b91fa820a1ecce"), // .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", revision: "031863a1cd683962a7dfe68e20b91fa820a1ecce"),

View File

@ -168,10 +168,10 @@ extension AppCoordinator {
enterDetail(of: profile) enterDetail(of: profile)
}, },
onEditProviderEntity: { onEditProviderEntity: {
guard let pair = $0.firstProviderModuleWithMetadata else { guard let pair = $0.selectedProvider else {
return return
} }
present(.editProviderEntity($0, pair.0, pair.1)) present(.editProviderEntity($0, pair.module, pair.selection))
}, },
onMigrateProfiles: { onMigrateProfiles: {
modalRoute = .migrateProfiles modalRoute = .migrateProfiles

View File

@ -134,12 +134,12 @@ private extension InstalledProfileView {
var providerSelectorButton: some View { var providerSelectorButton: some View {
profile? profile?
.firstProviderModuleWithMetadata .selectedProvider
.map { _, provider in .map { _, selection in
Button { Button {
flow?.onEditProviderEntity(profile!) flow?.onEditProviderEntity(profile!)
} label: { } label: {
providerSelectorLabel(with: provider) providerSelectorLabel(with: selection)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
} }

View File

@ -87,7 +87,7 @@ private extension ProfileContextMenu {
var providerConnectToButton: some View { var providerConnectToButton: some View {
profile? profile?
.firstProviderModuleWithMetadata .selectedProvider
.map { _ in .map { _ in
Button(Strings.Ui.ProfileContext.connectTo) { Button(Strings.Ui.ProfileContext.connectTo) {
flow?.onEditProviderEntity(profile!) flow?.onEditProviderEntity(profile!)

View File

@ -58,7 +58,7 @@ struct ReportIssueButton {
} }
var currentProvider: (ProviderID, Date?)? { var currentProvider: (ProviderID, Date?)? {
guard let id = installedProfile?.firstProviderModuleWithMetadata?.1.id else { guard let id = installedProfile?.selectedProvider?.selection.id else {
return nil return nil
} }
let lastUpdate = providerManager.lastUpdate(for: id) let lastUpdate = providerManager.lastUpdate(for: id)

View File

@ -54,27 +54,31 @@ struct ActiveProfileView: View {
var errorHandler: ErrorHandler var errorHandler: ErrorHandler
var body: some View { var body: some View {
VStack { VStack(spacing: .zero) {
Spacer()
VStack { VStack {
currentProfileView VStack {
statusView currentProfileView
} statusView
.padding(.bottom) }
.padding(.bottom)
profile.map { profile.map {
detailView(for: $0) detailView(for: $0)
} }
.padding(.bottom) .padding(.bottom)
Group { Group {
toggleConnectionButton toggleConnectionButton
switchProfileButton switchProfileButton
}
.clipShape(RoundedRectangle(cornerRadius: 50))
} }
.clipShape(RoundedRectangle(cornerRadius: 50)) .padding(.horizontal, 100)
Spacer()
} }
.padding([.top, .horizontal], 100)
Spacer()
} }
} }
@ -96,28 +100,19 @@ private extension ActiveProfileView {
func detailView(for profile: Profile) -> some View { func detailView(for profile: Profile) -> some View {
VStack(spacing: 10) { VStack(spacing: 10) {
if let connectionModule = profile.modules.first(where: { $0 is ConnectionModule }) { if let connectionModule = profile.firstConnectionModule(ifActive: true) {
HStack { DetailRowView(title: Strings.Global.protocol) {
Text(Strings.Global.protocol)
.fontWeight(.light)
Spacer()
Text(connectionModule.moduleHandler.id.name) Text(connectionModule.moduleHandler.id.name)
} }
} }
if let providerPair = profile.firstProviderModuleWithMetadata { if let pair = profile.selectedProvider {
if let provider = providerManager.provider(withId: providerPair.1.id) { if let metadata = providerManager.provider(withId: pair.selection.id) {
HStack { DetailRowView(title: Strings.Global.provider) {
Text(Strings.Global.provider) Text(metadata.description)
.fontWeight(.light)
Spacer()
Text(provider.description)
} }
} }
if let entity = providerPair.1.entity { if let entity = pair.selection.entity {
HStack { DetailRowView(title: Strings.Global.country) {
Text(Strings.Global.country)
.fontWeight(.light)
Spacer()
ThemeCountryText(entity.header.countryCode) ThemeCountryText(entity.header.countryCode)
} }
} }
@ -133,12 +128,8 @@ private extension ActiveProfileView {
nextProfileId: .constant(nil), nextProfileId: .constant(nil),
interactiveManager: interactiveManager, interactiveManager: interactiveManager,
errorHandler: errorHandler, errorHandler: errorHandler,
onProviderEntityRequired: { _ in onProviderEntityRequired: onProviderEntityRequired,
// FIXME: #788, TV missing provider entity onPurchaseRequired: onPurchaseRequired,
},
onPurchaseRequired: { _ in
// FIXME: #788, TV purchase required
},
label: { label: {
Text($0 ? Strings.Global.connect : Strings.Global.disconnect) Text($0 ? Strings.Global.connect : Strings.Global.disconnect)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
@ -174,6 +165,36 @@ private extension ActiveProfileView {
// MARK: - // MARK: -
private extension ActiveProfileView {
func onProviderEntityRequired(_ profile: Profile) {
// FIXME: #788, TV missing provider entity
}
func onPurchaseRequired(_ features: Set<AppFeature>) {
// FIXME: #788, TV purchase required
}
}
// MARK: - Subviews
private struct DetailRowView<Content>: View where Content: View {
let title: String
@ViewBuilder
let content: Content
var body: some View {
HStack {
Text(title)
.fontWeight(.light)
Spacer()
content
}
}
}
// MARK: - Previews
#Preview("Host") { #Preview("Host") {
let profile: Profile = { let profile: Profile = {
do { do {

View File

@ -81,12 +81,8 @@ private extension ProfileListView {
nextProfileId: .constant(nil), nextProfileId: .constant(nil),
interactiveManager: interactiveManager, interactiveManager: interactiveManager,
errorHandler: errorHandler, errorHandler: errorHandler,
onProviderEntityRequired: { _ in onProviderEntityRequired: onProviderEntityRequired,
// FIXME: #788, TV missing provider entity onPurchaseRequired: onPurchaseRequired,
},
onPurchaseRequired: { _ in
// FIXME: #788, TV purchase required
},
label: { _ in label: { _ in
toggleView(for: header) toggleView(for: header)
} }
@ -107,6 +103,18 @@ private extension ProfileListView {
// MARK: - // MARK: -
private extension ProfileListView {
func onProviderEntityRequired(_ profile: Profile) {
// FIXME: #788, TV missing provider entity
}
func onPurchaseRequired(_ features: Set<AppFeature>) {
// FIXME: #788, TV purchase required
}
}
// MARK: - Previews
#Preview("List") { #Preview("List") {
ContentPreview(profileManager: .mock) ContentPreview(profileManager: .mock)
} }

View File

@ -48,7 +48,7 @@ struct ProfileView: View, TunnelInstallationProviding {
var tunnel: ExtendedTunnel var tunnel: ExtendedTunnel
@State @State
private var showsSidePanel = false var showsSidePanel = false
@FocusState @FocusState
private var focusedField: Field? private var focusedField: Field?
@ -185,10 +185,20 @@ private extension ProfileView {
// MARK: - // MARK: -
#Preview { #Preview("List") {
ProfileView( ProfileView(
profileManager: .mock, profileManager: .mock,
tunnel: .mock tunnel: .mock,
showsSidePanel: true
)
.withMockEnvironment()
}
#Preview("Empty") {
ProfileView(
profileManager: ProfileManager(profiles: []),
tunnel: .mock,
showsSidePanel: true
) )
.withMockEnvironment() .withMockEnvironment()
} }

View File

@ -113,7 +113,7 @@ private extension TunnelToggleButton {
if canConnect { if canConnect {
// provider module -> check requirements // provider module -> check requirements
if let providerModule = profile.firstProviderModule, if let providerModule = profile.activeProviderModule,
providerModule.isProviderRequired { providerModule.isProviderRequired {
// missing required provider -> show error // missing required provider -> show error