Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split views into extensions #321

Merged
merged 2 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions Passepartout/App/Views/AboutView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
import SwiftUI

struct AboutView: View {
// private let appName = Unlocalized.appName

private let versionString = Constants.Global.appVersionString

private let redditURL = Constants.URLs.subreddit
Expand All @@ -52,11 +50,15 @@ struct AboutView: View {
supportSection
webSection
githubSection
}.themeSecondaryView()
.navigationTitle(L10n.About.title)
}.navigationTitle(L10n.About.title)
.themeSecondaryView()
}
}

private var infoSection: some View {
// MARK: -

private extension AboutView {
var infoSection: some View {
Section {
NavigationLink {
VersionView()
Expand All @@ -70,7 +72,7 @@ struct AboutView: View {
}
}

private var supportSection: some View {
var supportSection: some View {
Section {
Button(L10n.About.Items.JoinCommunity.caption) {
URL.open(redditURL)
Expand All @@ -82,7 +84,7 @@ struct AboutView: View {
}
}

private var webSection: some View {
var webSection: some View {
Section {
Button(L10n.About.Items.Website.caption) {
URL.open(homeURL)
Expand All @@ -101,7 +103,7 @@ struct AboutView: View {
}
}

private var githubSection: some View {
var githubSection: some View {
Section {
Button(Unlocalized.About.readme) {
URL.open(readmeURL)
Expand All @@ -115,13 +117,15 @@ struct AboutView: View {
}
}

extension AboutView {
private func shareOnTwitter() {
// MARK: -

private extension AboutView {
func shareOnTwitter() {
let url = Unlocalized.Social.twitterIntent(withMessage: shareMessage)
URL.open(url)
}

private func submitReview() {
func submitReview() {
let reviewURL = Reviewer.urlForReview(withAppId: Constants.App.appStoreId)
URL.open(reviewURL)
}
Expand Down
29 changes: 16 additions & 13 deletions Passepartout/App/Views/AccountView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct AccountView: View {

var body: some View {
List {
// TODO: interactive, re-enable after fixing
// TODO: interactive, re-enable after fixing
// Section {
// // TODO: interactive, l10n
// themeTextPicker(L10n.Global.Strings.authentication, selection: $liveAccount.authenticationMethod ?? .persistent, values: [
Expand All @@ -83,7 +83,7 @@ struct AccountView: View {
.withLeadingText(L10n.Account.Items.Password.caption)
}

// TODO: interactive, scan QR code
// TODO: interactive, scan QR code
case .totp:
themeSecureField(L10n.Account.Items.Password.placeholder, text: $liveAccount.password, contentType: .oneTimeCode)
.withLeadingText(L10n.Account.Items.Seed.caption)
Expand All @@ -102,8 +102,7 @@ struct AccountView: View {
}
}
}
}.navigationTitle(L10n.Account.title)
.toolbar {
}.toolbar {
CopySavingButton(
original: $account,
copy: $liveAccount,
Expand All @@ -112,25 +111,21 @@ struct AccountView: View {
saveAnyway: saveAnyway,
onSave: onSave
)
}
}

private func openGuidanceURL(_ url: URL) {
URL.open(url)
}.navigationTitle(L10n.Account.title)
}
}

// MARK: Provider
// MARK: -

extension AccountView {
private var usernamePlaceholder: String? {
private extension AccountView {
var usernamePlaceholder: String? {
guard let name = providerName else {
return nil
}
return providerManager.defaultUsername(name, vpnProtocol: vpnProtocol)
}

private var metadata: ProviderMetadata? {
var metadata: ProviderMetadata? {
guard let name = providerName else {
return nil
}
Expand All @@ -152,3 +147,11 @@ private extension Profile.Account.AuthenticationMethod {
}
}
}

// MARK: -

private extension AccountView {
func openGuidanceURL(_ url: URL) {
URL.open(url)
}
}
207 changes: 108 additions & 99 deletions Passepartout/App/Views/AddHostView+Name.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ extension AddHostView {

@State private var isEnteringCredentials = false

private var isComplete: Bool {
!viewModel.processedProfile.isPlaceholder
}

init(
url: URL,
deletingURLOnSuccess: Bool,
Expand Down Expand Up @@ -84,123 +80,136 @@ extension AddHostView {
.navigationTitle(L10n.AddProfile.Shared.title)
.themeSecondaryView()
}
}
}

@ViewBuilder
private var mainView: some View {
AddProfileView.ProfileNameSection(
profileName: $viewModel.profileName,
errorMessage: viewModel.errorMessage
) {
processProfile(replacingExisting: false)
}.onAppear {
viewModel.presetName(withURL: url)
}.disabled(isComplete)
// MARK: -

if !isComplete {
if viewModel.requiresPassphrase {
encryptionSection
}
let headers = profileManager.headers.sorted()
if !headers.isEmpty {
AddProfileView.ExistingProfilesSection(
headers: headers,
profileName: $viewModel.profileName
)
}
} else {
completeSection
}
}
private extension AddHostView.NameView {

private var encryptionSection: some View {
Section {
SecureField(L10n.AddProfile.Host.Sections.Encryption.footer, text: $viewModel.encryptionPassphrase) {
processProfile(replacingExisting: false)
}
} header: {
Text(L10n.Global.Strings.encryption)
@ViewBuilder
var mainView: some View {
AddProfileView.ProfileNameSection(
profileName: $viewModel.profileName,
errorMessage: viewModel.errorMessage
) {
processProfile(replacingExisting: false)
}.onAppear {
viewModel.presetName(withURL: url)
}.disabled(isComplete)

if !isComplete {
if viewModel.requiresPassphrase {
encryptionSection
}
}

private var completeSection: some View {
Section {
Text(Unlocalized.Network.url)
.withTrailingText(url.lastPathComponent)
viewModel.processedProfile.vpnProtocols.first.map {
Text(L10n.Global.Strings.protocol)
.withTrailingText($0.description)
}
} header: {
Text(L10n.AddProfile.Shared.title)
} footer: {
themeErrorMessage(viewModel.errorMessage)
let headers = profileManager.headers.sorted()
if !headers.isEmpty {
AddProfileView.ExistingProfilesSection(
headers: headers,
profileName: $viewModel.profileName
)
}
} else {
completeSection
}
}

private var hiddenAccountLink: some View {
NavigationLink("", isActive: $isEnteringCredentials) {
AddProfileView.AccountWrapperView(
profile: $viewModel.processedProfile,
bindings: bindings
)
var encryptionSection: some View {
Section {
SecureField(L10n.AddProfile.Host.Sections.Encryption.footer, text: $viewModel.encryptionPassphrase) {
processProfile(replacingExisting: false)
}
} header: {
Text(L10n.Global.Strings.encryption)
}
}

private var nextString: String {
if !viewModel.processedProfile.isPlaceholder {
return viewModel.processedProfile.requiresCredentials ? L10n.Global.Strings.next : L10n.Global.Strings.save
} else {
return L10n.Global.Strings.next
var completeSection: some View {
Section {
Text(Unlocalized.Network.url)
.withTrailingText(url.lastPathComponent)
viewModel.processedProfile.vpnProtocols.first.map {
Text(L10n.Global.Strings.protocol)
.withTrailingText($0.description)
}
} header: {
Text(L10n.AddProfile.Shared.title)
} footer: {
themeErrorMessage(viewModel.errorMessage)
}
}

private func requestResourcePermissions() {
_ = url.startAccessingSecurityScopedResource()
var hiddenAccountLink: some View {
NavigationLink("", isActive: $isEnteringCredentials) {
AddProfileView.AccountWrapperView(
profile: $viewModel.processedProfile,
bindings: bindings
)
}
}

private func dropResourcePermissions() {
url.stopAccessingSecurityScopedResource()
var nextString: String {
if !viewModel.processedProfile.isPlaceholder {
return viewModel.processedProfile.requiresCredentials ? L10n.Global.Strings.next : L10n.Global.Strings.save
} else {
return L10n.Global.Strings.next
}
}

@ViewBuilder
private func alertOverwriteActions() -> some View {
Button(role: .destructive) {
processProfile(replacingExisting: true)
} label: {
Text(L10n.Global.Strings.ok)
}
Button(role: .cancel) {
} label: {
Text(L10n.Global.Strings.cancel)
}
@ViewBuilder
func alertOverwriteActions() -> some View {
Button(role: .destructive) {
processProfile(replacingExisting: true)
} label: {
Text(L10n.Global.Strings.ok)
}

private func alertOverwriteMessage() -> some View {
Text(L10n.AddProfile.Shared.Alerts.Overwrite.message)
Button(role: .cancel) {
} label: {
Text(L10n.Global.Strings.cancel)
}
}

private func processProfile(replacingExisting: Bool) {
viewModel.processURL(
url,
with: profileManager,
replacingExisting: replacingExisting,
deletingURLOnSuccess: deletingURLOnSuccess
)
}
func alertOverwriteMessage() -> some View {
Text(L10n.AddProfile.Shared.Alerts.Overwrite.message)
}

private func saveProfile() {
let result = viewModel.addProcessedProfile(to: profileManager)
guard result else {
return
}
var isComplete: Bool {
!viewModel.processedProfile.isPlaceholder
}
}

let profile = viewModel.processedProfile
if profile.requiresCredentials {
isEnteringCredentials = true
} else {
bindings.isPresented = false
profileManager.didCreateProfile.send(profile)
}
// MARK: -

private extension AddHostView.NameView {
func requestResourcePermissions() {
_ = url.startAccessingSecurityScopedResource()
}

func dropResourcePermissions() {
url.stopAccessingSecurityScopedResource()
}

func processProfile(replacingExisting: Bool) {
viewModel.processURL(
url,
with: profileManager,
replacingExisting: replacingExisting,
deletingURLOnSuccess: deletingURLOnSuccess
)
}

func saveProfile() {
let result = viewModel.addProcessedProfile(to: profileManager)
guard result else {
return
}

let profile = viewModel.processedProfile
if profile.requiresCredentials {
isEnteringCredentials = true
} else {
bindings.isPresented = false
profileManager.didCreateProfile.send(profile)
}
}
}
Loading